diff --git a/.codecov.yaml b/.codecov.yaml index cc6cbfdd31..9ce617cfa6 100644 --- a/.codecov.yaml +++ b/.codecov.yaml @@ -100,6 +100,10 @@ component_management: name: bridge-symfony-http-foundation-telemetry paths: - src/bridge/symfony/http-foundation-telemetry/** + - component_id: bridge-symfony-postgresql-bundle + name: bridge-symfony-postgresql-bundle + paths: + - src/bridge/symfony/postgresql-bundle/** - component_id: bridge-symfony-telemetry-bundle name: bridge-symfony-telemetry-bundle paths: diff --git a/.github/workflows/job-tests.yml b/.github/workflows/job-tests.yml index e117319cfc..d88e507554 100644 --- a/.github/workflows/job-tests.yml +++ b/.github/workflows/job-tests.yml @@ -141,6 +141,7 @@ jobs: - name: "Test - Bridges" run: "composer test:bridges" env: + PGSQL_DATABASE_URL: pgsql://postgres:postgres@127.0.0.1:${{ job.services.postgres.ports[5432] }}/postgres?serverVersion=11&charset=utf8 AZURITE_HOST: "localhost" AZURITE_BLOB_PORT: "10000" AZURITE_ACCOUNT_NAME: "flowphpaccount01" diff --git a/.github/workflows/monorepo-split.yml b/.github/workflows/monorepo-split.yml index be084138e7..251bbf9e41 100644 --- a/.github/workflows/monorepo-split.yml +++ b/.github/workflows/monorepo-split.yml @@ -94,6 +94,8 @@ jobs: split_repository: 'symfony-http-foundation-bridge' - local_path: 'src/bridge/symfony/http-foundation-telemetry' split_repository: 'symfony-http-foundation-telemetry-bridge' + - local_path: 'src/bridge/symfony/postgresql-bundle' + split_repository: 'symfony-postgresql-bundle' - local_path: 'src/bridge/symfony/telemetry-bundle' split_repository: 'symfony-telemetry-bundle' - local_path: 'src/bridge/telemetry/otlp' diff --git a/bin/docs.php b/bin/docs.php index dc829dcf8f..24e103f584 100755 --- a/bin/docs.php +++ b/bin/docs.php @@ -60,7 +60,12 @@ public function execute(InputInterface $input, OutputInterface $output) : int __DIR__ . '/../src/adapter/etl-adapter-xml/src/Flow/ETL/Adapter/XML/functions.php', __DIR__ . '/../src/lib/filesystem/src/Flow/Filesystem/DSL/functions.php', __DIR__ . '/../src/lib/types/src/Flow/Types/DSL/functions.php', - __DIR__ . '/../src/lib/postgresql/src/Flow/PostgreSql/DSL/functions.php', + __DIR__ . '/../src/lib/postgresql/src/Flow/PostgreSql/DSL/schema.php', + __DIR__ . '/../src/lib/postgresql/src/Flow/PostgreSql/DSL/query.php', + __DIR__ . '/../src/lib/postgresql/src/Flow/PostgreSql/DSL/condition.php', + __DIR__ . '/../src/lib/postgresql/src/Flow/PostgreSql/DSL/parser.php', + __DIR__ . '/../src/lib/postgresql/src/Flow/PostgreSql/DSL/client.php', + __DIR__ . '/../src/lib/postgresql/src/Flow/PostgreSql/Migrations/DSL/functions.php', __DIR__ . '/../src/lib/telemetry/src/Flow/Telemetry/DSL/functions.php', __DIR__ . '/../src/lib/azure-sdk/src/Flow/Azure/SDK/DSL/functions.php', __DIR__ . '/../src/bridge/filesystem/azure/src/Flow/Filesystem/Bridge/Azure/DSL/functions.php', diff --git a/composer.json b/composer.json index 51a0abc550..407f416a5a 100644 --- a/composer.json +++ b/composer.json @@ -20,7 +20,7 @@ "ext-xmlreader": "*", "ext-xmlwriter": "*", "ext-zlib": "*", - "composer-runtime-api": "^2.0", + "composer-runtime-api": "^2.2", "async-aws/s3": "^2.6", "brick/math": "^0.12 || ^0.13 || ^0.14", "coduo/php-humanizer": "^5.0", @@ -39,15 +39,15 @@ "psr/http-message": "^1.0 || ^2.0", "psr/log": "^2.0 || ^3.0", "psr/simple-cache": "^1.0 || ^2.0 || ^3.0", - "symfony/config": "^6.4 || ^7.3 || ^8.0", - "symfony/console": "^6.4 || ^7.3 || ^8.0", - "symfony/dependency-injection": "^6.4 || ^7.3 || ^8.0", - "symfony/event-dispatcher": "^6.4 || ^7.3 || ^8.0", - "symfony/http-foundation": "^6.4 || ^7.3 || ^8.0", - "symfony/http-kernel": "^6.4 || ^7.3 || ^8.0", + "symfony/config": "^6.4 || ^7.4 || ^8.0", + "symfony/console": "^6.4 || ^7.4 || ^8.0", + "symfony/dependency-injection": "^6.4 || ^7.4 || ^8.0", + "symfony/event-dispatcher": "^6.4 || ^7.4 || ^8.0", + "symfony/http-foundation": "^6.4 || ^7.4 || ^8.0", + "symfony/http-kernel": "^6.4 || ^7.4 || ^8.0", "symfony/polyfill-mbstring": "^1.33", - "symfony/string": "^6.4 || ^7.3 || ^8.0", - "symfony/uid": "^6.4 || ^7.3 || ^8.0", + "symfony/string": "^6.4 || ^7.4 || ^8.0", + "symfony/uid": "^6.4 || ^7.4 || ^8.0", "webmozart/glob": "^3.0 || ^4.0" }, "require-dev": { @@ -61,14 +61,14 @@ "php-http/curl-client": "^2.2", "php-http/mock-client": "^1.5", "ramsey/uuid": "^4.5", - "symfony/cache": "^6.4 || ^7.3 || ^8.0", - "symfony/dotenv": "^6.4 || ^7.3 || ^8.0", - "symfony/finder": "^6.4 || ^7.3 || ^8.0", - "symfony/framework-bundle": "^6.4 || ^7.3 || ^8.0", - "symfony/http-client": "^6.4 || ^7.3 || ^8.0", - "symfony/messenger": "^6.4 || ^7.3 || ^8.0", - "symfony/process": "^7.3 || ^8.0", - "symfony/routing": "^6.4 || ^7.3 || ^8.0", + "symfony/cache": "^6.4 || ^7.4 || ^8.0", + "symfony/dotenv": "^6.4 || ^7.4 || ^8.0", + "symfony/finder": "^6.4 || ^7.4 || ^8.0", + "symfony/framework-bundle": "^6.4 || ^7.4 || ^8.0", + "symfony/http-client": "^6.4 || ^7.4 || ^8.0", + "symfony/messenger": "^6.4 || ^7.4 || ^8.0", + "symfony/process": "^7.4 || ^8.0", + "symfony/routing": "^6.4 || ^7.4 || ^8.0", "twig/twig": "^3.0" }, "replace": { @@ -109,6 +109,7 @@ "flow-php/snappy": "self.version", "flow-php/symfony-http-foundation-bridge": "self.version", "flow-php/symfony-http-foundation-telemetry-bridge": "self.version", + "flow-php/symfony-postgresql-bundle": "self.version", "flow-php/symfony-telemetry-bundle": "self.version", "flow-php/telemetry": "self.version", "flow-php/telemetry-otlp-bridge": "self.version", @@ -144,6 +145,7 @@ "src/bridge/psr18/telemetry/src/Flow", "src/bridge/symfony/http-foundation-telemetry/src/Flow", "src/bridge/symfony/http-foundation/src/Flow", + "src/bridge/symfony/postgresql-bundle/src/Flow", "src/bridge/symfony/telemetry-bundle/src/Flow", "src/bridge/telemetry/otlp/src/Flow", "src/bridge/phpunit/telemetry/src/Flow", @@ -204,8 +206,13 @@ "src/lib/parquet/src/Flow/Parquet/functions.php", "src/lib/parquet/src/Flow/Parquet/Binary/functions.php", "src/lib/parquet/src/stubs.php", - "src/lib/postgresql/src/Flow/PostgreSql/DSL/functions.php", + "src/lib/postgresql/src/Flow/PostgreSql/DSL/client.php", + "src/lib/postgresql/src/Flow/PostgreSql/DSL/condition.php", + "src/lib/postgresql/src/Flow/PostgreSql/DSL/parser.php", + "src/lib/postgresql/src/Flow/PostgreSql/DSL/query.php", + "src/lib/postgresql/src/Flow/PostgreSql/DSL/schema.php", "src/lib/postgresql/src/stubs.php", + "src/lib/postgresql/src/Flow/PostgreSql/Migrations/DSL/functions.php", "src/lib/snappy/polyfill.php", "src/lib/telemetry/src/Flow/Telemetry/DSL/functions.php", "src/lib/types/src/Flow/Types/DSL/functions.php" @@ -237,6 +244,7 @@ "src/bridge/psr18/telemetry/tests/Flow", "src/bridge/symfony/http-foundation-telemetry/tests/Flow", "src/bridge/symfony/http-foundation/tests/Flow", + "src/bridge/symfony/postgresql-bundle/tests/Flow", "src/bridge/symfony/telemetry-bundle/tests/Flow", "src/bridge/telemetry/otlp/tests/Flow", "src/bridge/phpunit/telemetry/tests/Flow", @@ -296,6 +304,7 @@ "@test:lib:parquet", "@test:lib:parquet-viewer", "@test:lib:postgresql", + "@test:lib:postgresql-migrations", "@test:lib:snappy", "@test:lib:telemetry", "@test:lib:types" @@ -311,6 +320,7 @@ "@test:bridge:psr18-telemetry", "@test:bridge:symfony-http-foundation", "@test:bridge:symfony-http-foundation-telemetry", + "@test:bridge:symfony-postgresql-bundle", "@test:bridge:symfony-telemetry-bundle", "@test:bridge:telemetry-otlp" ], @@ -371,6 +381,10 @@ "tools/phpunit/vendor/bin/phpunit --testsuite=lib-postgresql-unit --log-junit ./var/phpunit/logs/lib-postgresql-unit.junit.xml --coverage-clover=./var/phpunit/coverage/clover/lib-postgresql-unit.coverage.xml", "tools/phpunit/vendor/bin/phpunit --testsuite=lib-postgresql-integration --log-junit ./var/phpunit/logs/lib-postgresql-integration.junit.xml --coverage-clover=./var/phpunit/coverage/clover/lib-postgresql-integration.coverage.xml" ], + "test:lib:postgresql-migrations": [ + "tools/phpunit/vendor/bin/phpunit --testsuite=lib-postgresql-migrations-unit --log-junit ./var/phpunit/logs/lib-postgresql-migrations-unit.junit.xml --coverage-clover=./var/phpunit/coverage/clover/lib-postgresql-migrations-unit.coverage.xml", + "tools/phpunit/vendor/bin/phpunit --testsuite=lib-postgresql-migrations-integration --log-junit ./var/phpunit/logs/lib-postgresql-migrations-integration.junit.xml --coverage-clover=./var/phpunit/coverage/clover/lib-postgresql-migrations-integration.coverage.xml" + ], "test:bridge:filesystem-azure": [ "tools/phpunit/vendor/bin/phpunit --testsuite=bridge-filesystem-azure-unit --log-junit ./var/phpunit/logs/bridge-filesystem-azure-unit.junit.xml --coverage-clover=./var/phpunit/coverage/clover/bridge-filesystem-azure-unit.coverage.xml", "tools/phpunit/vendor/bin/phpunit --testsuite=bridge-filesystem-azure-integration --log-junit ./var/phpunit/logs/bridge-filesystem-azure-integration.junit.xml --coverage-clover=./var/phpunit/coverage/clover/bridge-filesystem-azure-integration.coverage.xml" @@ -404,6 +418,10 @@ "tools/phpunit/vendor/bin/phpunit --testsuite=bridge-symfony-http-foundation-telemetry-unit --log-junit ./var/phpunit/logs/bridge-symfony-http-foundation-telemetry-unit.junit.xml --coverage-clover=./var/phpunit/coverage/clover/bridge-symfony-http-foundation-telemetry-unit.coverage.xml", "tools/phpunit/vendor/bin/phpunit --testsuite=bridge-symfony-http-foundation-telemetry-integration --log-junit ./var/phpunit/logs/bridge-symfony-http-foundation-telemetry-integration.junit.xml --coverage-clover=./var/phpunit/coverage/clover/bridge-symfony-http-foundation-telemetry-integration.coverage.xml" ], + "test:bridge:symfony-postgresql-bundle": [ + "tools/phpunit/vendor/bin/phpunit --testsuite=bridge-symfony-postgresql-bundle-unit --log-junit ./var/phpunit/logs/bridge-symfony-postgresql-bundle-unit.junit.xml --coverage-clover=./var/phpunit/coverage/clover/bridge-symfony-postgresql-bundle-unit.coverage.xml", + "tools/phpunit/vendor/bin/phpunit --testsuite=bridge-symfony-postgresql-bundle-integration --log-junit ./var/phpunit/logs/bridge-symfony-postgresql-bundle-integration.junit.xml --coverage-clover=./var/phpunit/coverage/clover/bridge-symfony-postgresql-bundle-integration.coverage.xml" + ], "test:bridge:symfony-telemetry-bundle": [ "tools/phpunit/vendor/bin/phpunit --testsuite=bridge-symfony-telemetry-bundle-unit --log-junit ./var/phpunit/logs/bridge-symfony-telemetry-bundle-unit.junit.xml --coverage-clover=./var/phpunit/coverage/clover/bridge-symfony-telemetry-bundle-unit.coverage.xml", "tools/phpunit/vendor/bin/phpunit --testsuite=bridge-symfony-telemetry-bundle-integration --log-junit ./var/phpunit/logs/bridge-symfony-telemetry-bundle-integration.junit.xml --coverage-clover=./var/phpunit/coverage/clover/bridge-symfony-telemetry-bundle-integration.coverage.xml" diff --git a/composer.lock b/composer.lock index cf5f1a39aa..8968f0aa4d 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": "ed336739d46dfa1e5132dbb97e65575c", + "content-hash": "a5802d7dd9648f8a2c0576222a39538d", "packages": [ { "name": "async-aws/core", @@ -536,16 +536,16 @@ }, { "name": "firebase/php-jwt", - "version": "v7.0.3", + "version": "v7.0.5", "source": { "type": "git", "url": "https://github.com/firebase/php-jwt.git", - "reference": "28aa0694bcfdfa5e2959c394d5a1ee7a5083629e" + "reference": "47ad26bab5e7c70ae8a6f08ed25ff83631121380" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/firebase/php-jwt/zipball/28aa0694bcfdfa5e2959c394d5a1ee7a5083629e", - "reference": "28aa0694bcfdfa5e2959c394d5a1ee7a5083629e", + "url": "https://api.github.com/repos/firebase/php-jwt/zipball/47ad26bab5e7c70ae8a6f08ed25ff83631121380", + "reference": "47ad26bab5e7c70ae8a6f08ed25ff83631121380", "shasum": "" }, "require": { @@ -553,6 +553,7 @@ }, "require-dev": { "guzzlehttp/guzzle": "^7.4", + "phpfastcache/phpfastcache": "^9.2", "phpspec/prophecy-phpunit": "^2.0", "phpunit/phpunit": "^9.5", "psr/cache": "^2.0||^3.0", @@ -593,22 +594,22 @@ ], "support": { "issues": "https://github.com/firebase/php-jwt/issues", - "source": "https://github.com/firebase/php-jwt/tree/v7.0.3" + "source": "https://github.com/firebase/php-jwt/tree/v7.0.5" }, - "time": "2026-02-25T22:16:40+00:00" + "time": "2026-04-01T20:38:03+00:00" }, { "name": "google/apiclient", - "version": "v2.19.0", + "version": "v2.19.2", "source": { "type": "git", "url": "https://github.com/googleapis/google-api-php-client.git", - "reference": "b18fa8aed7b2b2dd4bcce74e2c7d267e16007ea9" + "reference": "703ba9acfaf4ba71306108207feafb6d1d137eb0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/googleapis/google-api-php-client/zipball/b18fa8aed7b2b2dd4bcce74e2c7d267e16007ea9", - "reference": "b18fa8aed7b2b2dd4bcce74e2c7d267e16007ea9", + "url": "https://api.github.com/repos/googleapis/google-api-php-client/zipball/703ba9acfaf4ba71306108207feafb6d1d137eb0", + "reference": "703ba9acfaf4ba71306108207feafb6d1d137eb0", "shasum": "" }, "require": { @@ -619,11 +620,11 @@ "guzzlehttp/psr7": "^2.6", "monolog/monolog": "^2.9||^3.0", "php": "^8.1", - "phpseclib/phpseclib": "^3.0.36" + "phpseclib/phpseclib": "^3.0.50" }, "require-dev": { "cache/filesystem-adapter": "^1.1", - "composer/composer": "^1.10.23", + "composer/composer": "^2.9", "phpcompatibility/php-compatibility": "^9.2", "phpspec/prophecy-phpunit": "^2.1", "phpunit/phpunit": "^9.6", @@ -636,6 +637,9 @@ }, "type": "library", "extra": { + "component": { + "entry": "src/Client.php" + }, "branch-alias": { "dev-main": "2.x-dev" } @@ -662,9 +666,9 @@ ], "support": { "issues": "https://github.com/googleapis/google-api-php-client/issues", - "source": "https://github.com/googleapis/google-api-php-client/tree/v2.19.0" + "source": "https://github.com/googleapis/google-api-php-client/tree/v2.19.2" }, - "time": "2026-01-09T19:59:47+00:00" + "time": "2026-03-30T18:54:44+00:00" }, { "name": "google/apiclient-services", @@ -2491,16 +2495,16 @@ }, { "name": "symfony/config", - "version": "v7.4.7", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "6c17162555bfb58957a55bb0e43e00035b6ae3d5" + "reference": "2d19dde43fa2ff720b9a40763ace7226594f503b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/6c17162555bfb58957a55bb0e43e00035b6ae3d5", - "reference": "6c17162555bfb58957a55bb0e43e00035b6ae3d5", + "url": "https://api.github.com/repos/symfony/config/zipball/2d19dde43fa2ff720b9a40763ace7226594f503b", + "reference": "2d19dde43fa2ff720b9a40763ace7226594f503b", "shasum": "" }, "require": { @@ -2546,7 +2550,7 @@ "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/config/tree/v7.4.7" + "source": "https://github.com/symfony/config/tree/v7.4.8" }, "funding": [ { @@ -2566,20 +2570,20 @@ "type": "tidelift" } ], - "time": "2026-03-06T10:41:14+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/console", - "version": "v7.4.7", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "e1e6770440fb9c9b0cf725f81d1361ad1835329d" + "reference": "1e92e39c51f95b88e3d66fa2d9f06d1fb45dd707" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/e1e6770440fb9c9b0cf725f81d1361ad1835329d", - "reference": "e1e6770440fb9c9b0cf725f81d1361ad1835329d", + "url": "https://api.github.com/repos/symfony/console/zipball/1e92e39c51f95b88e3d66fa2d9f06d1fb45dd707", + "reference": "1e92e39c51f95b88e3d66fa2d9f06d1fb45dd707", "shasum": "" }, "require": { @@ -2644,7 +2648,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.4.7" + "source": "https://github.com/symfony/console/tree/v7.4.8" }, "funding": [ { @@ -2664,20 +2668,20 @@ "type": "tidelift" } ], - "time": "2026-03-06T14:06:20+00:00" + "time": "2026-03-30T13:54:39+00:00" }, { "name": "symfony/dependency-injection", - "version": "v7.4.7", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "0f651e58f4917fb0e2cd261ccbfe3d71e6e0f5db" + "reference": "f7025fd7b687c240426562f86ada06a93b1e771d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/0f651e58f4917fb0e2cd261ccbfe3d71e6e0f5db", - "reference": "0f651e58f4917fb0e2cd261ccbfe3d71e6e0f5db", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/f7025fd7b687c240426562f86ada06a93b1e771d", + "reference": "f7025fd7b687c240426562f86ada06a93b1e771d", "shasum": "" }, "require": { @@ -2728,7 +2732,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.7" + "source": "https://github.com/symfony/dependency-injection/tree/v7.4.8" }, "funding": [ { @@ -2748,7 +2752,7 @@ "type": "tidelift" } ], - "time": "2026-03-03T07:48:48+00:00" + "time": "2026-03-31T06:50:29+00:00" }, { "name": "symfony/deprecation-contracts", @@ -2819,16 +2823,16 @@ }, { "name": "symfony/error-handler", - "version": "v7.4.4", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "8da531f364ddfee53e36092a7eebbbd0b775f6b8" + "reference": "8dd79d8af777ee6cba2fd4d98da6ffb839f3c0fa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/8da531f364ddfee53e36092a7eebbbd0b775f6b8", - "reference": "8da531f364ddfee53e36092a7eebbbd0b775f6b8", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/8dd79d8af777ee6cba2fd4d98da6ffb839f3c0fa", + "reference": "8dd79d8af777ee6cba2fd4d98da6ffb839f3c0fa", "shasum": "" }, "require": { @@ -2877,7 +2881,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.4" + "source": "https://github.com/symfony/error-handler/tree/v7.4.8" }, "funding": [ { @@ -2897,20 +2901,20 @@ "type": "tidelift" } ], - "time": "2026-01-20T16:42:42+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v7.4.4", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "dc2c0eba1af673e736bb851d747d266108aea746" + "reference": "f57b899fa736fd71121168ef268f23c206083f0a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/dc2c0eba1af673e736bb851d747d266108aea746", - "reference": "dc2c0eba1af673e736bb851d747d266108aea746", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/f57b899fa736fd71121168ef268f23c206083f0a", + "reference": "f57b899fa736fd71121168ef268f23c206083f0a", "shasum": "" }, "require": { @@ -2962,7 +2966,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v7.4.4" + "source": "https://github.com/symfony/event-dispatcher/tree/v7.4.8" }, "funding": [ { @@ -2982,7 +2986,7 @@ "type": "tidelift" } ], - "time": "2026-01-05T11:45:34+00:00" + "time": "2026-03-30T13:54:39+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -3062,16 +3066,16 @@ }, { "name": "symfony/filesystem", - "version": "v7.4.6", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "3ebc794fa5315e59fd122561623c2e2e4280538e" + "reference": "58b9790d12f9670b7f53a1c1738febd3108970a5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/3ebc794fa5315e59fd122561623c2e2e4280538e", - "reference": "3ebc794fa5315e59fd122561623c2e2e4280538e", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/58b9790d12f9670b7f53a1c1738febd3108970a5", + "reference": "58b9790d12f9670b7f53a1c1738febd3108970a5", "shasum": "" }, "require": { @@ -3108,7 +3112,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v7.4.6" + "source": "https://github.com/symfony/filesystem/tree/v7.4.8" }, "funding": [ { @@ -3128,20 +3132,20 @@ "type": "tidelift" } ], - "time": "2026-02-25T16:50:00+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/http-client", - "version": "v7.4.7", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "1010624285470eb60e88ed10035102c75b4ea6af" + "reference": "01933e626c3de76bea1e22641e205e78f6a34342" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/1010624285470eb60e88ed10035102c75b4ea6af", - "reference": "1010624285470eb60e88ed10035102c75b4ea6af", + "url": "https://api.github.com/repos/symfony/http-client/zipball/01933e626c3de76bea1e22641e205e78f6a34342", + "reference": "01933e626c3de76bea1e22641e205e78f6a34342", "shasum": "" }, "require": { @@ -3209,7 +3213,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v7.4.7" + "source": "https://github.com/symfony/http-client/tree/v7.4.8" }, "funding": [ { @@ -3229,7 +3233,7 @@ "type": "tidelift" } ], - "time": "2026-03-05T11:16:58+00:00" + "time": "2026-03-30T12:55:43+00:00" }, { "name": "symfony/http-client-contracts", @@ -3311,16 +3315,16 @@ }, { "name": "symfony/http-foundation", - "version": "v7.4.7", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "f94b3e7b7dafd40e666f0c9ff2084133bae41e81" + "reference": "9381209597ec66c25be154cbf2289076e64d1eab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/f94b3e7b7dafd40e666f0c9ff2084133bae41e81", - "reference": "f94b3e7b7dafd40e666f0c9ff2084133bae41e81", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/9381209597ec66c25be154cbf2289076e64d1eab", + "reference": "9381209597ec66c25be154cbf2289076e64d1eab", "shasum": "" }, "require": { @@ -3369,7 +3373,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.7" + "source": "https://github.com/symfony/http-foundation/tree/v7.4.8" }, "funding": [ { @@ -3389,20 +3393,20 @@ "type": "tidelift" } ], - "time": "2026-03-06T13:15:18+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/http-kernel", - "version": "v7.4.7", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "3b3fcf386c809be990c922e10e4c620d6367cab1" + "reference": "017e76ad089bac281553389269e259e155935e1a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/3b3fcf386c809be990c922e10e4c620d6367cab1", - "reference": "3b3fcf386c809be990c922e10e4c620d6367cab1", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/017e76ad089bac281553389269e259e155935e1a", + "reference": "017e76ad089bac281553389269e259e155935e1a", "shasum": "" }, "require": { @@ -3488,7 +3492,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.7" + "source": "https://github.com/symfony/http-kernel/tree/v7.4.8" }, "funding": [ { @@ -3508,7 +3512,7 @@ "type": "tidelift" } ], - "time": "2026-03-06T16:33:18+00:00" + "time": "2026-03-31T20:57:01+00:00" }, { "name": "symfony/polyfill-ctype", @@ -4257,16 +4261,16 @@ }, { "name": "symfony/string", - "version": "v7.4.6", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "9f209231affa85aa930a5e46e6eb03381424b30b" + "reference": "114ac57257d75df748eda23dd003878080b8e688" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/9f209231affa85aa930a5e46e6eb03381424b30b", - "reference": "9f209231affa85aa930a5e46e6eb03381424b30b", + "url": "https://api.github.com/repos/symfony/string/zipball/114ac57257d75df748eda23dd003878080b8e688", + "reference": "114ac57257d75df748eda23dd003878080b8e688", "shasum": "" }, "require": { @@ -4324,7 +4328,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.4.6" + "source": "https://github.com/symfony/string/tree/v7.4.8" }, "funding": [ { @@ -4344,20 +4348,20 @@ "type": "tidelift" } ], - "time": "2026-02-09T09:33:46+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/translation", - "version": "v7.4.6", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "1888cf064399868af3784b9e043240f1d89d25ce" + "reference": "33600f8489485425bfcddd0d983391038d3422e7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/1888cf064399868af3784b9e043240f1d89d25ce", - "reference": "1888cf064399868af3784b9e043240f1d89d25ce", + "url": "https://api.github.com/repos/symfony/translation/zipball/33600f8489485425bfcddd0d983391038d3422e7", + "reference": "33600f8489485425bfcddd0d983391038d3422e7", "shasum": "" }, "require": { @@ -4424,7 +4428,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v7.4.6" + "source": "https://github.com/symfony/translation/tree/v7.4.8" }, "funding": [ { @@ -4444,7 +4448,7 @@ "type": "tidelift" } ], - "time": "2026-02-17T07:53:42+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/translation-contracts", @@ -4530,16 +4534,16 @@ }, { "name": "symfony/uid", - "version": "v7.4.4", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "7719ce8aba76be93dfe249192f1fbfa52c588e36" + "reference": "6883ebdf7bf6a12b37519dbc0df62b0222401b56" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/7719ce8aba76be93dfe249192f1fbfa52c588e36", - "reference": "7719ce8aba76be93dfe249192f1fbfa52c588e36", + "url": "https://api.github.com/repos/symfony/uid/zipball/6883ebdf7bf6a12b37519dbc0df62b0222401b56", + "reference": "6883ebdf7bf6a12b37519dbc0df62b0222401b56", "shasum": "" }, "require": { @@ -4584,7 +4588,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v7.4.4" + "source": "https://github.com/symfony/uid/tree/v7.4.8" }, "funding": [ { @@ -4604,20 +4608,20 @@ "type": "tidelift" } ], - "time": "2026-01-03T23:30:35+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/var-dumper", - "version": "v7.4.6", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "045321c440ac18347b136c63d2e9bf28a2dc0291" + "reference": "9510c3966f749a1d1ff0059e1eabef6cc621e7fd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/045321c440ac18347b136c63d2e9bf28a2dc0291", - "reference": "045321c440ac18347b136c63d2e9bf28a2dc0291", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/9510c3966f749a1d1ff0059e1eabef6cc621e7fd", + "reference": "9510c3966f749a1d1ff0059e1eabef6cc621e7fd", "shasum": "" }, "require": { @@ -4671,7 +4675,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v7.4.6" + "source": "https://github.com/symfony/var-dumper/tree/v7.4.8" }, "funding": [ { @@ -4691,20 +4695,20 @@ "type": "tidelift" } ], - "time": "2026-02-15T10:53:20+00:00" + "time": "2026-03-30T13:44:50+00:00" }, { "name": "symfony/var-exporter", - "version": "v7.4.0", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "03a60f169c79a28513a78c967316fbc8bf17816f" + "reference": "398907e89a2a56fe426f7955c6fa943ec0c77225" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/03a60f169c79a28513a78c967316fbc8bf17816f", - "reference": "03a60f169c79a28513a78c967316fbc8bf17816f", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/398907e89a2a56fe426f7955c6fa943ec0c77225", + "reference": "398907e89a2a56fe426f7955c6fa943ec0c77225", "shasum": "" }, "require": { @@ -4752,7 +4756,7 @@ "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v7.4.0" + "source": "https://github.com/symfony/var-exporter/tree/v7.4.8" }, "funding": [ { @@ -4772,7 +4776,7 @@ "type": "tidelift" } ], - "time": "2025-09-11T10:15:23+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "webmozart/glob", @@ -5082,20 +5086,20 @@ }, { "name": "grpc/grpc", - "version": "1.74.0", + "version": "1.80.0", "source": { "type": "git", "url": "https://github.com/grpc/grpc-php.git", - "reference": "32bf4dba256d60d395582fb6e4e8d3936bcdb713" + "reference": "a0dc463d5d5064cdd7ff344f13f61d7e233f9b5a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/grpc/grpc-php/zipball/32bf4dba256d60d395582fb6e4e8d3936bcdb713", - "reference": "32bf4dba256d60d395582fb6e4e8d3936bcdb713", + "url": "https://api.github.com/repos/grpc/grpc-php/zipball/a0dc463d5d5064cdd7ff344f13f61d7e233f9b5a", + "reference": "a0dc463d5d5064cdd7ff344f13f61d7e233f9b5a", "shasum": "" }, "require": { - "php": ">=7.0.0" + "php": ">=7.1.0" }, "require-dev": { "google/auth": "^v1.3.0" @@ -5120,9 +5124,9 @@ "rpc" ], "support": { - "source": "https://github.com/grpc/grpc-php/tree/v1.74.0" + "source": "https://github.com/grpc/grpc-php/tree/v1.80.0" }, - "time": "2025-07-24T20:02:16+00:00" + "time": "2026-03-30T09:22:39+00:00" }, { "name": "nikic/php-parser", @@ -5742,16 +5746,16 @@ }, { "name": "symfony/cache", - "version": "v7.4.7", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "665522ec357540e66c294c08583b40ee576574f0" + "reference": "467464da294734b0fb17e853e5712abc8470f819" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/665522ec357540e66c294c08583b40ee576574f0", - "reference": "665522ec357540e66c294c08583b40ee576574f0", + "url": "https://api.github.com/repos/symfony/cache/zipball/467464da294734b0fb17e853e5712abc8470f819", + "reference": "467464da294734b0fb17e853e5712abc8470f819", "shasum": "" }, "require": { @@ -5822,7 +5826,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v7.4.7" + "source": "https://github.com/symfony/cache/tree/v7.4.8" }, "funding": [ { @@ -5842,7 +5846,7 @@ "type": "tidelift" } ], - "time": "2026-03-06T08:14:57+00:00" + "time": "2026-03-30T15:15:47+00:00" }, { "name": "symfony/cache-contracts", @@ -5922,16 +5926,16 @@ }, { "name": "symfony/clock", - "version": "v7.4.0", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/clock.git", - "reference": "9169f24776edde469914c1e7a1442a50f7a4e110" + "reference": "674fa3b98e21531dd040e613479f5f6fa8f32111" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/clock/zipball/9169f24776edde469914c1e7a1442a50f7a4e110", - "reference": "9169f24776edde469914c1e7a1442a50f7a4e110", + "url": "https://api.github.com/repos/symfony/clock/zipball/674fa3b98e21531dd040e613479f5f6fa8f32111", + "reference": "674fa3b98e21531dd040e613479f5f6fa8f32111", "shasum": "" }, "require": { @@ -5976,7 +5980,7 @@ "time" ], "support": { - "source": "https://github.com/symfony/clock/tree/v7.4.0" + "source": "https://github.com/symfony/clock/tree/v7.4.8" }, "funding": [ { @@ -5996,20 +6000,20 @@ "type": "tidelift" } ], - "time": "2025-11-12T15:39:26+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/dotenv", - "version": "v7.4.7", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/dotenv.git", - "reference": "7e5529a0b02395cb4614cdf507495a4cef3115c5" + "reference": "5df79f11350166125fe754c85b87f7e13d735314" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dotenv/zipball/7e5529a0b02395cb4614cdf507495a4cef3115c5", - "reference": "7e5529a0b02395cb4614cdf507495a4cef3115c5", + "url": "https://api.github.com/repos/symfony/dotenv/zipball/5df79f11350166125fe754c85b87f7e13d735314", + "reference": "5df79f11350166125fe754c85b87f7e13d735314", "shasum": "" }, "require": { @@ -6054,7 +6058,7 @@ "environment" ], "support": { - "source": "https://github.com/symfony/dotenv/tree/v7.4.7" + "source": "https://github.com/symfony/dotenv/tree/v7.4.8" }, "funding": [ { @@ -6074,20 +6078,20 @@ "type": "tidelift" } ], - "time": "2026-03-03T07:48:48+00:00" + "time": "2026-03-30T12:55:43+00:00" }, { "name": "symfony/finder", - "version": "v7.4.6", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "8655bf1076b7a3a346cb11413ffdabff50c7ffcf" + "reference": "e0be088d22278583a82da281886e8c3592fbf149" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/8655bf1076b7a3a346cb11413ffdabff50c7ffcf", - "reference": "8655bf1076b7a3a346cb11413ffdabff50c7ffcf", + "url": "https://api.github.com/repos/symfony/finder/zipball/e0be088d22278583a82da281886e8c3592fbf149", + "reference": "e0be088d22278583a82da281886e8c3592fbf149", "shasum": "" }, "require": { @@ -6122,7 +6126,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.6" + "source": "https://github.com/symfony/finder/tree/v7.4.8" }, "funding": [ { @@ -6142,20 +6146,20 @@ "type": "tidelift" } ], - "time": "2026-01-29T09:40:50+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/framework-bundle", - "version": "v7.4.7", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/framework-bundle.git", - "reference": "c94bc78c85d76af67918404a95d44940f66a7c2f" + "reference": "180533cfbac2144349044267db31d5d3df9957cb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/c94bc78c85d76af67918404a95d44940f66a7c2f", - "reference": "c94bc78c85d76af67918404a95d44940f66a7c2f", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/180533cfbac2144349044267db31d5d3df9957cb", + "reference": "180533cfbac2144349044267db31d5d3df9957cb", "shasum": "" }, "require": { @@ -6280,7 +6284,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.7" + "source": "https://github.com/symfony/framework-bundle/tree/v7.4.8" }, "funding": [ { @@ -6300,20 +6304,20 @@ "type": "tidelift" } ], - "time": "2026-03-06T15:39:55+00:00" + "time": "2026-03-30T12:55:43+00:00" }, { "name": "symfony/messenger", - "version": "v7.4.7", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/messenger.git", - "reference": "13a00f01a46ba7d47ac7f0e3d9a901d19f9432f0" + "reference": "ddf5ab29bc0329ece30e16f01c86abb6241e92d8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/messenger/zipball/13a00f01a46ba7d47ac7f0e3d9a901d19f9432f0", - "reference": "13a00f01a46ba7d47ac7f0e3d9a901d19f9432f0", + "url": "https://api.github.com/repos/symfony/messenger/zipball/ddf5ab29bc0329ece30e16f01c86abb6241e92d8", + "reference": "ddf5ab29bc0329ece30e16f01c86abb6241e92d8", "shasum": "" }, "require": { @@ -6374,7 +6378,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.7" + "source": "https://github.com/symfony/messenger/tree/v7.4.8" }, "funding": [ { @@ -6394,20 +6398,20 @@ "type": "tidelift" } ], - "time": "2026-03-04T13:54:41+00:00" + "time": "2026-03-30T12:55:43+00:00" }, { "name": "symfony/options-resolver", - "version": "v7.4.0", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "b38026df55197f9e39a44f3215788edf83187b80" + "reference": "2888fcdc4dc2fd5f7c7397be78631e8af12e02b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/b38026df55197f9e39a44f3215788edf83187b80", - "reference": "b38026df55197f9e39a44f3215788edf83187b80", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/2888fcdc4dc2fd5f7c7397be78631e8af12e02b4", + "reference": "2888fcdc4dc2fd5f7c7397be78631e8af12e02b4", "shasum": "" }, "require": { @@ -6445,7 +6449,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v7.4.0" + "source": "https://github.com/symfony/options-resolver/tree/v7.4.8" }, "funding": [ { @@ -6465,7 +6469,7 @@ "type": "tidelift" } ], - "time": "2025-11-12T15:39:26+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/polyfill-php80", @@ -6553,16 +6557,16 @@ }, { "name": "symfony/process", - "version": "v7.4.5", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "608476f4604102976d687c483ac63a79ba18cc97" + "reference": "60f19cd3badc8de688421e21e4305eba50f8089a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/608476f4604102976d687c483ac63a79ba18cc97", - "reference": "608476f4604102976d687c483ac63a79ba18cc97", + "url": "https://api.github.com/repos/symfony/process/zipball/60f19cd3badc8de688421e21e4305eba50f8089a", + "reference": "60f19cd3badc8de688421e21e4305eba50f8089a", "shasum": "" }, "require": { @@ -6594,7 +6598,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.4.5" + "source": "https://github.com/symfony/process/tree/v7.4.8" }, "funding": [ { @@ -6614,20 +6618,20 @@ "type": "tidelift" } ], - "time": "2026-01-26T15:07:59+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/routing", - "version": "v7.4.6", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "238d749c56b804b31a9bf3e26519d93b65a60938" + "reference": "9608de9873ec86e754fb6c0a0fa7e5f1a960eb6b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/238d749c56b804b31a9bf3e26519d93b65a60938", - "reference": "238d749c56b804b31a9bf3e26519d93b65a60938", + "url": "https://api.github.com/repos/symfony/routing/zipball/9608de9873ec86e754fb6c0a0fa7e5f1a960eb6b", + "reference": "9608de9873ec86e754fb6c0a0fa7e5f1a960eb6b", "shasum": "" }, "require": { @@ -6679,7 +6683,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v7.4.6" + "source": "https://github.com/symfony/routing/tree/v7.4.8" }, "funding": [ { @@ -6699,7 +6703,7 @@ "type": "tidelift" } ], - "time": "2026-02-25T16:50:00+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "twig/twig", @@ -6801,5 +6805,5 @@ "composer-runtime-api": "^2.0" }, "platform-dev": {}, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.9.0" } diff --git a/documentation/components/bridges/symfony-postgresql-bundle.md b/documentation/components/bridges/symfony-postgresql-bundle.md new file mode 100644 index 0000000000..fcf010bee1 --- /dev/null +++ b/documentation/components/bridges/symfony-postgresql-bundle.md @@ -0,0 +1,340 @@ +# Symfony PostgreSQL Bundle + +Symfony bundle integrating Flow PHP's PostgreSQL library with Symfony applications, providing database management, +schema migrations, catalog-driven schema diffing, and optional telemetry for query tracing and metrics. + +- [Back](/documentation/introduction.md) +- [Packagist](https://packagist.org/packages/flow-php/symfony-postgresql-bundle) +- [Installation](/documentation/installation/packages/symfony-postgresql-bundle.md) +- [GitHub](https://github.com/flow-php/symfony-postgresql-bundle) + +[TOC] + +## Installation + +For detailed installation instructions, see the [installation page](/documentation/installation/packages/symfony-postgresql-bundle.md). + +## Overview + +This bundle integrates Flow PHP's PostgreSQL library with Symfony applications. It provides: + +- **Multiple database connections** - Configure and manage several PostgreSQL connections independently +- **Database management commands** - Create, drop databases and execute SQL from the console +- **Migration framework** - Generate, execute, and track schema migrations +- **Schema diffing** - Automatically generate migrations by comparing the database to catalog definitions +- **Rollback support** - Generate reversible migrations with automatic rollback files +- **Telemetry integration** - Distributed tracing, query logging, and metrics per connection +- **Catalog provider system** - Define target schemas via PHP attributes, service references, or inline YAML + +## Configuration Reference + +### Connections + +At least one connection is required. Each connection has a DSN and optional telemetry and migrations blocks. + +```yaml +flow_postgresql: + connections: + default: + dsn: '%env(DATABASE_URL)%' +``` + +### Telemetry + +Enable telemetry per connection to get distributed tracing, query logging, and metrics. + +```yaml +flow_postgresql: + connections: + default: + dsn: '%env(DATABASE_URL)%' + + telemetry: + service_id: "flow.telemetry" # Required: Telemetry service ID + clock_service_id: null # Optional: PSR-20 clock service (defaults to SystemClock) + trace_queries: true # Record query execution in traces + trace_transactions: true # Record transaction boundaries + collect_metrics: true # Collect query metrics (duration, row count) + log_queries: false # Log all queries + max_query_length: 1000 # Truncate queries longer than this (chars) + include_parameters: false # Include query parameters in traces + max_parameters: 10 # Max number of parameters to include + max_parameter_length: 100 # Max length of each parameter value (chars) +``` + +### Migrations + +Migrations are configured at the top level, not per connection. Use `--connection` to target a specific connection +when running migration commands. + +```yaml +flow_postgresql: + connections: + default: + dsn: '%env(DATABASE_URL)%' + + migrations: + enabled: true + directory: "%kernel.project_dir%/migrations" # Where migration files are stored + namespace: "App\\Migrations" # PHP namespace for generated migrations + table_name: "flow_migrations" # Database table tracking executed migrations + table_schema: "public" # Schema for the migrations table + migration_file_name: "migration.php" # Name of the migration file in each version directory + rollback_file_name: "rollback.php" # Name of the rollback file in each version directory + all_or_nothing: false # Wrap all migrations in a single transaction + generate_rollback: true # Generate rollback files automatically +``` + +### Catalog Providers + +Catalog providers define the target database schema. When you run `flow:migrations:diff`, the bundle compares +the current database state to the catalog and generates migration SQL to reconcile the differences. + +There are three ways to define catalog providers. + +#### Attribute-Based Discovery + +Annotate a class implementing `CatalogProvider` with `#[AsCatalogProvider]` for automatic discovery: + +```php +fetchInto( - User::class, + constructor_mapper(User::class), 'SELECT id, name, email, active FROM users WHERE id = $1', [1] ); @@ -51,7 +50,7 @@ Returns the first row mapped to an object, or `null` if no rows: fetchInto( - User::class, + constructor_mapper(User::class), 'SELECT id, name, email, active FROM users WHERE email = $1', ['john@example.com'] ); @@ -68,7 +67,7 @@ use Flow\PostgreSql\Client\Exception\QueryException; try { $user = $client->fetchOneInto( - User::class, + constructor_mapper(User::class), 'SELECT id, name, email, active FROM users WHERE id = $1', [1] ); @@ -86,7 +85,7 @@ Returns an array of objects: /** @var User[] $users */ $users = $client->fetchAllInto( - User::class, + constructor_mapper(User::class), 'SELECT id, name, email, active FROM users WHERE active = $1 ORDER BY name', [true] ); @@ -98,7 +97,7 @@ foreach ($users as $user) { ## ConstructorMapper -The default `pgsql_mapper()` creates a `ConstructorMapper` that: +The `constructor_mapper(ClassName::class)` DSL function creates a `ConstructorMapper` that: 1. Maps column names directly to constructor parameter names (1:1 matching) 2. Passes values as-is to the constructor (no type coercion) @@ -119,7 +118,7 @@ readonly class Product } $products = $client->fetchAllInto( - Product::class, + constructor_mapper(Product::class), 'SELECT id, name, price, description FROM products' ); ``` @@ -144,7 +143,7 @@ readonly class UserProfile // Alias snake_case columns to match parameter names $profile = $client->fetchInto( - UserProfile::class, + constructor_mapper(UserProfile::class), 'SELECT id, first_name AS firstName, last_name AS lastName, created_at AS createdAt FROM users WHERE id = $1', [1] @@ -165,7 +164,7 @@ readonly class UserMapper implements RowMapper /** * @param array $row */ - public function map(string $class, array $row): object + public function map(array $row): object { return new User( id: (int) $row['id'], @@ -176,18 +175,15 @@ readonly class UserMapper implements RowMapper } } -// Use custom mapper $client = pgsql_client( pgsql_connection('host=localhost dbname=mydb'), - mapper: new UserMapper(), ); -// Or override per-call +// Use custom mapper $user = $client->fetchInto( - User::class, + new UserMapper(), 'SELECT * FROM users WHERE id = $1', [1], - mapper: new UserMapper(), ); ``` @@ -200,7 +196,7 @@ Map objects while streaming large result sets: $cursor = $client->cursor('SELECT * FROM large_table'); -foreach ($cursor->map(User::class) as $user) { +foreach ($cursor->map(constructor_mapper(User::class)) as $user) { // Process one object at a time processUser($user); } @@ -226,7 +222,7 @@ readonly class OrderWithUser readonly class OrderMapper implements RowMapper { - public function map(string $class, array $row): object + public function map(array $row): object { $user = new User( id: (int) $row['user_id'], @@ -244,12 +240,11 @@ readonly class OrderMapper implements RowMapper } $order = $client->fetchInto( - OrderWithUser::class, + new OrderMapper(), 'SELECT o.id AS order_id, o.total, u.id AS user_id, u.name AS user_name, u.email AS user_email FROM orders o JOIN users u ON o.user_id = u.id WHERE o.id = $1', [1], - mapper: new OrderMapper(), ); ``` diff --git a/documentation/components/libs/postgresql/client-types.md b/documentation/components/libs/postgresql/client-types.md index 3d08308060..687d210097 100644 --- a/documentation/components/libs/postgresql/client-types.md +++ b/documentation/components/libs/postgresql/client-types.md @@ -96,7 +96,7 @@ When automatic detection isn't sufficient, use `typed()` to specify the exact Po use function Flow\PostgreSql\DSL\{ pgsql_client, pgsql_connection, typed, - pgsql_type_uuid, pgsql_type_json, pgsql_type_date, pgsql_type_int4_array + value_type_uuid, value_type_json, value_type_date, value_type_int4_array }; $client = pgsql_client(pgsql_connection('host=localhost dbname=mydb')); @@ -104,25 +104,25 @@ $client = pgsql_client(pgsql_connection('host=localhost dbname=mydb')); // UUID - string that should be treated as UUID $client->fetch( 'SELECT * FROM users WHERE id = $1', - [typed('550e8400-e29b-41d4-a716-446655440000', pgsql_type_uuid())] + [typed('550e8400-e29b-41d4-a716-446655440000', value_type_uuid())] ); // JSON - array to be sent as JSON $client->execute( 'INSERT INTO events (payload) VALUES ($1)', - [typed(['event' => 'login', 'user_id' => 42], pgsql_type_json())] + [typed(['event' => 'login', 'user_id' => 42], value_type_json())] ); // DATE - DateTime that should be DATE, not TIMESTAMP $client->fetch( 'SELECT * FROM events WHERE date = $1', - [typed(new \DateTimeImmutable('2024-01-15'), pgsql_type_date())] + [typed(new \DateTimeImmutable('2024-01-15'), value_type_date())] ); // Integer array $client->execute( 'INSERT INTO scores (values) VALUES ($1)', - [typed([100, 200, 300], pgsql_type_int4_array())] + [typed([100, 200, 300], value_type_int4_array())] ); ``` @@ -145,53 +145,53 @@ $client->execute( | DSL Function | PostgreSQL Type | Use Case | |--------------|-----------------|----------| | **String types** | | | -| `pgsql_type_text()` | TEXT | Text strings | -| `pgsql_type_varchar()` | VARCHAR | Variable-length strings | -| `pgsql_type_char()` | CHAR | Fixed-length strings | +| `value_type_text()` | TEXT | Text strings | +| `value_type_varchar()` | VARCHAR | Variable-length strings | +| `value_type_char()` | CHAR | Fixed-length strings | | **Integer types** | | | -| `pgsql_type_int2()` / `pgsql_type_smallint()` | SMALLINT | Small integers | -| `pgsql_type_int4()` / `pgsql_type_integer()` | INTEGER | Standard integers | -| `pgsql_type_int8()` / `pgsql_type_bigint()` | BIGINT | Large integers | +| `value_type_int2()` / `value_type_smallint()` | SMALLINT | Small integers | +| `value_type_int4()` / `value_type_integer()` | INTEGER | Standard integers | +| `value_type_int8()` / `value_type_bigint()` | BIGINT | Large integers | | **Floating point types** | | | -| `pgsql_type_float4()` / `pgsql_type_real()` | REAL | Single precision floats | -| `pgsql_type_float8()` / `pgsql_type_double()` | DOUBLE PRECISION | Double precision floats | -| `pgsql_type_numeric()` | NUMERIC | Arbitrary precision numbers | -| `pgsql_type_money()` | MONEY | Currency amounts | +| `value_type_float4()` / `value_type_real()` | REAL | Single precision floats | +| `value_type_float8()` / `value_type_double()` | DOUBLE PRECISION | Double precision floats | +| `value_type_numeric()` | NUMERIC | Arbitrary precision numbers | +| `value_type_money()` | MONEY | Currency amounts | | **Boolean type** | | | -| `pgsql_type_bool()` / `pgsql_type_boolean()` | BOOLEAN | True/false values | +| `value_type_bool()` / `value_type_boolean()` | BOOLEAN | True/false values | | **Binary types** | | | -| `pgsql_type_bytea()` | BYTEA | Binary data | -| `pgsql_type_bit()` | BIT | Bit strings | -| `pgsql_type_varbit()` | VARBIT | Variable-length bit strings | +| `value_type_bytea()` | BYTEA | Binary data | +| `value_type_bit()` | BIT | Bit strings | +| `value_type_varbit()` | VARBIT | Variable-length bit strings | | **Date/time types** | | | -| `pgsql_type_date()` | DATE | Dates without time | -| `pgsql_type_time()` | TIME | Time without timezone | -| `pgsql_type_timetz()` | TIMETZ | Time with timezone | -| `pgsql_type_timestamp()` | TIMESTAMP | Timestamp without timezone | -| `pgsql_type_timestamptz()` | TIMESTAMPTZ | Timestamp with timezone | -| `pgsql_type_interval()` | INTERVAL | Time intervals | +| `value_type_date()` | DATE | Dates without time | +| `value_type_time()` | TIME | Time without timezone | +| `value_type_timetz()` | TIMETZ | Time with timezone | +| `value_type_timestamp()` | TIMESTAMP | Timestamp without timezone | +| `value_type_timestamptz()` | TIMESTAMPTZ | Timestamp with timezone | +| `value_type_interval()` | INTERVAL | Time intervals | | **JSON types** | | | -| `pgsql_type_json()` | JSON | JSON data | -| `pgsql_type_jsonb()` | JSONB | Binary JSON data | +| `value_type_json()` | JSON | JSON data | +| `value_type_jsonb()` | JSONB | Binary JSON data | | **UUID type** | | | -| `pgsql_type_uuid()` | UUID | Universally unique identifiers | +| `value_type_uuid()` | UUID | Universally unique identifiers | | **Network types** | | | -| `pgsql_type_inet()` | INET | IPv4/IPv6 addresses | -| `pgsql_type_cidr()` | CIDR | Network addresses | -| `pgsql_type_macaddr()` | MACADDR | MAC addresses | -| `pgsql_type_macaddr8()` | MACADDR8 | MAC addresses (EUI-64) | +| `value_type_inet()` | INET | IPv4/IPv6 addresses | +| `value_type_cidr()` | CIDR | Network addresses | +| `value_type_macaddr()` | MACADDR | MAC addresses | +| `value_type_macaddr8()` | MACADDR8 | MAC addresses (EUI-64) | | **Other types** | | | -| `pgsql_type_xml()` | XML | XML data | -| `pgsql_type_oid()` | OID | Object identifiers | +| `value_type_xml()` | XML | XML data | +| `value_type_oid()` | OID | Object identifiers | | **Array types** | | | -| `pgsql_type_text_array()` | TEXT[] | Array of strings | -| `pgsql_type_int4_array()` | INTEGER[] | Array of integers | -| `pgsql_type_int8_array()` | BIGINT[] | Array of big integers | -| `pgsql_type_float8_array()` | FLOAT8[] | Array of floats | -| `pgsql_type_bool_array()` | BOOLEAN[] | Array of booleans | -| `pgsql_type_uuid_array()` | UUID[] | Array of UUIDs | -| `pgsql_type_json_array()` | JSON[] | Array of JSON | -| `pgsql_type_jsonb_array()` | JSONB[] | Array of JSONB | +| `value_type_text_array()` | TEXT[] | Array of strings | +| `value_type_int4_array()` | INTEGER[] | Array of integers | +| `value_type_int8_array()` | BIGINT[] | Array of big integers | +| `value_type_float8_array()` | FLOAT8[] | Array of floats | +| `value_type_bool_array()` | BOOLEAN[] | Array of booleans | +| `value_type_uuid_array()` | UUID[] | Array of UUIDs | +| `value_type_json_array()` | JSON[] | Array of JSON | +| `value_type_jsonb_array()` | JSONB[] | Array of JSONB | ## Built-in Value Converters diff --git a/documentation/components/libs/postgresql/condition-builder.md b/documentation/components/libs/postgresql/condition-builder.md index 6ff67f5f6a..cb9d9adfcf 100644 --- a/documentation/components/libs/postgresql/condition-builder.md +++ b/documentation/components/libs/postgresql/condition-builder.md @@ -23,7 +23,7 @@ $conditions = conditions() // Use in a query $query = select()->from(table('users'))->where($conditions); -echo $query->toSQL(); +echo $query->toSql(); // SELECT * FROM users WHERE status = 'active' AND age > 18 ``` @@ -35,7 +35,7 @@ The real power of `ConditionBuilder` is building conditions based on runtime log and(gte(col('age'), param($filters['min_age']))); + $conditions = $conditions->and(ge(col('age'), param($filters['min_age']))); } if (array_key_exists('email_domain', $filters)) { @@ -66,7 +66,7 @@ function buildUserQuery(array $filters): SelectFinalStep // Usage $query = buildUserQuery(['status' => 'active', 'min_age' => 21]); -echo $query->toSQL(); +echo $query->toSql(); // SELECT * FROM users WHERE status = $1 AND age >= $2 ``` @@ -93,7 +93,7 @@ $conditions = conditions() $query = select()->from(table('users'))->where($conditions); -echo $query->toSQL(); +echo $query->toSql(); // SELECT * FROM users WHERE status = 'active' AND (role = 'admin' OR role = 'moderator') AND age > 18 ``` @@ -152,15 +152,15 @@ $conditions = conditions() | `getCondition()` | Returns the built `Condition` or `null` if empty | | `isEmpty()` | Returns `true` if no conditions have been added | -## Comparison with cond_and/cond_or +## Comparison with and_/or_ -For static conditions known at build time, `cond_and()` and `cond_or()` are simpler: +For static conditions known at build time, `and_()` and `or_()` are simpler: ```php -// Static conditions - use cond_and/cond_or +// Static conditions - use and_/or_ $query = select() ->from(table('users')) - ->where(cond_and( + ->where(and_( eq(col('active'), literal(true)), gt(col('age'), literal(18)) )); diff --git a/documentation/components/libs/postgresql/copy-query-builder.md b/documentation/components/libs/postgresql/copy-query-builder.md index 434ffb6437..56b5c521f4 100644 --- a/documentation/components/libs/postgresql/copy-query-builder.md +++ b/documentation/components/libs/postgresql/copy-query-builder.md @@ -19,7 +19,7 @@ $query = copy() ->from('users') ->file('/tmp/users.csv'); -echo $query->toSQL(); +echo $query->toSql(); // COPY users FROM '/tmp/users.csv' ``` @@ -35,7 +35,7 @@ $query = copy() ->columns('id', 'name', 'email') ->file('/tmp/users.csv'); -echo $query->toSQL(); +echo $query->toSql(); // COPY users(id, name, email) FROM '/tmp/users.csv' ``` @@ -52,7 +52,7 @@ $query = copy() ->stdin() ->format(CopyFormat::CSV); -echo $query->toSQL(); +echo $query->toSql(); // COPY users FROM STDIN WITH (format csv) ``` @@ -67,7 +67,7 @@ $query = copy() ->from('logs') ->program('gunzip -c /var/log/app.log.gz'); -echo $query->toSQL(); +echo $query->toSql(); // COPY logs FROM PROGRAM 'gunzip -c /var/log/app.log.gz' ``` @@ -90,7 +90,7 @@ $query = copy() ->escape('\\') ->encoding('UTF8'); -echo $query->toSQL(); +echo $query->toSql(); // COPY data FROM '/tmp/data.csv' WITH (format csv, delimiter ';', null 'NULL', header true, quote '''', escape '\\', encoding 'UTF8') ``` @@ -110,7 +110,7 @@ $query = copy() ->format(CopyFormat::CSV) ->forceNotNull('name', 'email'); -echo $query->toSQL(); +echo $query->toSql(); // COPY users FROM '/tmp/users.csv' WITH (format csv, force_not_null (name, email)) ``` @@ -130,7 +130,7 @@ $query = copy() ->format(CopyFormat::CSV) ->forceNull('description', 'notes'); -echo $query->toSQL(); +echo $query->toSql(); // COPY users FROM '/tmp/users.csv' WITH (format csv, force_null (description, notes)) ``` @@ -149,7 +149,7 @@ $query = copy() ->file('/tmp/events.csv') ->onError(CopyOnError::IGNORE); -echo $query->toSQL(); +echo $query->toSql(); // COPY events FROM '/tmp/events.csv' WITH (on_error 'ignore') ``` @@ -166,7 +166,7 @@ $query = copy() ->to('users') ->file('/tmp/users.csv'); -echo $query->toSQL(); +echo $query->toSql(); // COPY users TO '/tmp/users.csv' ``` @@ -182,7 +182,7 @@ $query = copy() ->columns('id', 'name', 'email') ->file('/tmp/users.csv'); -echo $query->toSQL(); +echo $query->toSql(); // COPY users(id, name, email) TO '/tmp/users.csv' ``` @@ -199,7 +199,7 @@ $query = copy() ->stdout() ->format(CopyFormat::CSV); -echo $query->toSQL(); +echo $query->toSql(); // COPY users TO STDOUT WITH (format csv) ``` @@ -214,7 +214,7 @@ $query = copy() ->to('logs') ->program('gzip > /tmp/logs.csv.gz'); -echo $query->toSQL(); +echo $query->toSql(); // COPY logs TO PROGRAM 'gzip > /tmp/logs.csv.gz' ``` @@ -237,7 +237,7 @@ $query = copy() ->file('/tmp/active_users.csv') ->format(CopyFormat::CSV); -echo $query->toSQL(); +echo $query->toSql(); // COPY (SELECT id, name FROM users) TO '/tmp/active_users.csv' WITH (format csv) ``` @@ -254,7 +254,7 @@ $query = copy() ->file('/tmp/data.bin') ->format(CopyFormat::BINARY); -echo $query->toSQL(); +echo $query->toSql(); // COPY data TO '/tmp/data.bin' WITH (format binary) ``` @@ -275,7 +275,7 @@ $query = copy() ->format(CopyFormat::CSV) ->forceQuote('name', 'description'); -echo $query->toSQL(); +echo $query->toSql(); // COPY products TO '/tmp/products.csv' WITH (format csv, force_quote (name, description)) // Quote all columns @@ -285,7 +285,7 @@ $query = copy() ->format(CopyFormat::CSV) ->forceQuoteAll(); -echo $query->toSQL(); +echo $query->toSql(); // COPY products TO '/tmp/products.csv' WITH (format csv, force_quote *) ``` @@ -300,14 +300,14 @@ $query = copy() ->from('analytics.events') ->file('/tmp/events.csv'); -echo $query->toSQL(); +echo $query->toSql(); // COPY analytics.events FROM '/tmp/events.csv' $query = copy() ->to('analytics.events') ->file('/tmp/events.csv'); -echo $query->toSQL(); +echo $query->toSql(); // COPY analytics.events TO '/tmp/events.csv' ``` diff --git a/documentation/components/libs/postgresql/delete-query-builder.md b/documentation/components/libs/postgresql/delete-query-builder.md index 0bc6046b26..553a91b3ec 100644 --- a/documentation/components/libs/postgresql/delete-query-builder.md +++ b/documentation/components/libs/postgresql/delete-query-builder.md @@ -17,7 +17,7 @@ $query = delete() ->from('users') ->where(eq(col('id'), literal(1))); -echo $query->toSQL(); +echo $query->toSql(); // DELETE FROM users WHERE id = 1 ``` @@ -34,7 +34,7 @@ $query = delete() ->from('users') ->where(eq(col('id'), param(1))); -echo $query->toSQL(); +echo $query->toSql(); // DELETE FROM users WHERE id = $1 ``` @@ -49,7 +49,7 @@ $query = delete() ->from('users', 'u') ->where(eq(col('u.id'), literal(1))); -echo $query->toSQL(); +echo $query->toSql(); // DELETE FROM users u WHERE u.id = 1 ``` @@ -67,7 +67,7 @@ $query = delete() ->using(table('users')) ->where(eq(col('orders.user_id'), col('users.id'))); -echo $query->toSQL(); +echo $query->toSql(); // DELETE FROM orders USING users WHERE orders.user_id = users.id ``` @@ -77,7 +77,7 @@ echo $query->toSQL(); from('users') - ->where(any_sub_select(col('id'), ComparisonOperator::EQ, $subquery)); + ->where(any_(col('id'), ComparisonOperator::EQ, $subquery)); -echo $query->toSQL(); +echo $query->toSql(); // DELETE FROM users WHERE id = ANY (SELECT user_id FROM inactive_users) ``` @@ -107,7 +107,7 @@ $query = delete() ->where(eq(col('id'), literal(1))) ->returning(col('id'), col('name')); -echo $query->toSQL(); +echo $query->toSql(); // DELETE FROM users WHERE id = 1 RETURNING id, name // Return all columns @@ -116,7 +116,7 @@ $query = delete() ->where(eq(col('id'), literal(1))) ->returningAll(); -echo $query->toSQL(); +echo $query->toSql(); // DELETE FROM users WHERE id = 1 RETURNING * ``` @@ -126,19 +126,19 @@ echo $query->toSQL(); from('sessions') ->where( - cond_and( + and_( eq(col('active'), literal(false)), lt(col('expires_at'), literal('2024-01-01')) ) ); -echo $query->toSQL(); +echo $query->toSql(); // DELETE FROM sessions WHERE active = false AND expires_at < '2024-01-01' ``` diff --git a/documentation/components/libs/postgresql/domain-query-builder.md b/documentation/components/libs/postgresql/domain-query-builder.md index 1e10ba357a..c561173f30 100644 --- a/documentation/components/libs/postgresql/domain-query-builder.md +++ b/documentation/components/libs/postgresql/domain-query-builder.md @@ -21,7 +21,7 @@ use function Flow\PostgreSql\DSL\create; $query = create()->domain('email') ->as('text'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE DOMAIN email AS text ``` @@ -35,7 +35,7 @@ use function Flow\PostgreSql\DSL\create; $query = create()->domain('public.email') ->as('text'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE DOMAIN public.email AS text ``` @@ -50,7 +50,7 @@ $query = create()->domain('email') ->as('text') ->notNull(); -echo $query->toSQL(); +echo $query->toSql(); // CREATE DOMAIN email AS text NOT NULL ``` @@ -67,7 +67,7 @@ $query = create()->domain('email') ->as('text') ->null(); -echo $query->toSQL(); +echo $query->toSql(); // CREATE DOMAIN email AS text NULL ``` @@ -84,7 +84,7 @@ $query = create()->domain('email') ->as('text') ->default("'default@example.com'"); -echo $query->toSQL(); +echo $query->toSql(); // CREATE DOMAIN email AS text DEFAULT 'default@example.com' ``` @@ -101,7 +101,7 @@ $query = create()->domain('positive_int') ->as('int4') ->check('VALUE > 0'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE DOMAIN positive_int AS int4 CHECK (value > 0) ``` @@ -119,7 +119,7 @@ $query = create()->domain('positive_int') ->constraint('positive_check') ->check('VALUE > 0'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE DOMAIN positive_int AS int4 CONSTRAINT positive_check CHECK (value > 0) ``` @@ -136,7 +136,7 @@ $query = create()->domain('email') ->as('text') ->collate('en_US'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE DOMAIN email AS text COLLATE "en_US" ``` @@ -152,7 +152,7 @@ $query = create()->domain('email') ->notNull() ->check("VALUE ~ '^.+@.+$'"); -echo $query->toSQL(); +echo $query->toSql(); // CREATE DOMAIN email AS text NOT NULL CHECK (value ~ '^.+@.+$') ``` @@ -168,7 +168,7 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->domain('email') ->setNotNull(); -echo $query->toSQL(); +echo $query->toSql(); // ALTER DOMAIN email SET NOT NULL ``` @@ -182,7 +182,7 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->domain('email') ->dropNotNull(); -echo $query->toSQL(); +echo $query->toSql(); // ALTER DOMAIN email DROP NOT NULL ``` @@ -196,7 +196,7 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->domain('email') ->setDefault("'default@example.com'"); -echo $query->toSQL(); +echo $query->toSql(); // ALTER DOMAIN email SET DEFAULT 'default@example.com' ``` @@ -210,7 +210,7 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->domain('email') ->dropDefault(); -echo $query->toSQL(); +echo $query->toSql(); // ALTER DOMAIN email DROP DEFAULT ``` @@ -224,7 +224,7 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->domain('email') ->addConstraint('valid_email', "VALUE ~ '^.+@.+$'"); -echo $query->toSQL(); +echo $query->toSql(); // ALTER DOMAIN email ADD CONSTRAINT valid_email CHECK (value ~ '^.+@.+$') ``` @@ -238,7 +238,7 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->domain('email') ->dropConstraint('valid_email'); -echo $query->toSQL(); +echo $query->toSql(); // ALTER DOMAIN email DROP CONSTRAINT valid_email ``` @@ -253,7 +253,7 @@ $query = alter()->domain('email') ->dropConstraint('valid_email') ->cascade(); -echo $query->toSQL(); +echo $query->toSql(); // ALTER DOMAIN email DROP CONSTRAINT valid_email CASCADE ``` @@ -269,7 +269,7 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->domain('email') ->validateConstraint('valid_email'); -echo $query->toSQL(); +echo $query->toSql(); // ALTER DOMAIN email VALIDATE CONSTRAINT valid_email ``` @@ -283,7 +283,7 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->domain('public.email') ->setNotNull(); -echo $query->toSQL(); +echo $query->toSql(); // ALTER DOMAIN public.email SET NOT NULL ``` @@ -298,7 +298,7 @@ use function Flow\PostgreSql\DSL\drop; $query = drop()->domain('email'); -echo $query->toSQL(); +echo $query->toSql(); // DROP DOMAIN email ``` @@ -312,7 +312,7 @@ use function Flow\PostgreSql\DSL\drop; $query = drop()->domain('email') ->ifExists(); -echo $query->toSQL(); +echo $query->toSql(); // DROP DOMAIN IF EXISTS email ``` @@ -328,7 +328,7 @@ use function Flow\PostgreSql\DSL\drop; $query = drop()->domain('email') ->cascade(); -echo $query->toSQL(); +echo $query->toSql(); // DROP DOMAIN email CASCADE ``` @@ -344,7 +344,7 @@ use function Flow\PostgreSql\DSL\drop; $query = drop()->domain('email') ->restrict(); -echo $query->toSQL(); +echo $query->toSql(); // DROP DOMAIN email ``` @@ -357,7 +357,7 @@ use function Flow\PostgreSql\DSL\drop; $query = drop()->domain('email', 'phone', 'url'); -echo $query->toSQL(); +echo $query->toSql(); // DROP DOMAIN email, phone, url ``` @@ -372,7 +372,7 @@ $query = drop()->domain('email') ->ifExists() ->cascade(); -echo $query->toSQL(); +echo $query->toSql(); // DROP DOMAIN IF EXISTS email CASCADE ``` diff --git a/documentation/components/libs/postgresql/extension-query-builder.md b/documentation/components/libs/postgresql/extension-query-builder.md index f37ef339d9..10d1e8d2a3 100644 --- a/documentation/components/libs/postgresql/extension-query-builder.md +++ b/documentation/components/libs/postgresql/extension-query-builder.md @@ -18,7 +18,7 @@ use function Flow\PostgreSql\DSL\create; $query = create()->extension('uuid-ossp'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE EXTENSION "uuid-ossp" ``` @@ -32,7 +32,7 @@ use function Flow\PostgreSql\DSL\create; $query = create()->extension('uuid-ossp') ->ifNotExists(); -echo $query->toSQL(); +echo $query->toSql(); // CREATE EXTENSION IF NOT EXISTS "uuid-ossp" ``` @@ -48,7 +48,7 @@ use function Flow\PostgreSql\DSL\create; $query = create()->extension('uuid-ossp') ->schema('public'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE EXTENSION "uuid-ossp" SCHEMA public ``` @@ -64,7 +64,7 @@ use function Flow\PostgreSql\DSL\create; $query = create()->extension('postgis') ->version('3.0'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE EXTENSION postgis VERSION "3.0" ``` @@ -80,7 +80,7 @@ use function Flow\PostgreSql\DSL\create; $query = create()->extension('postgis_raster') ->cascade(); -echo $query->toSQL(); +echo $query->toSql(); // CREATE EXTENSION postgis_raster CASCADE ``` @@ -97,7 +97,7 @@ $query = create()->extension('postgis') ->version('3.0') ->cascade(); -echo $query->toSQL(); +echo $query->toSql(); // CREATE EXTENSION IF NOT EXISTS postgis SCHEMA extensions VERSION "3.0" CASCADE ``` @@ -115,7 +115,7 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->extension('postgis') ->update(); -echo $query->toSQL(); +echo $query->toSql(); // ALTER EXTENSION postgis UPDATE ``` @@ -129,7 +129,7 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->extension('postgis') ->updateTo('3.0'); -echo $query->toSQL(); +echo $query->toSql(); // ALTER EXTENSION postgis UPDATE TO "3.0" ``` @@ -145,7 +145,7 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->extension('uuid-ossp') ->setSchema('public'); -echo $query->toSQL(); +echo $query->toSql(); // ALTER EXTENSION "uuid-ossp" SET SCHEMA public ``` @@ -161,7 +161,7 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->extension('my_extension') ->addFunction('my_func', ['integer', 'text']); -echo $query->toSQL(); +echo $query->toSql(); // ALTER EXTENSION my_extension ADD FUNCTION my_func("integer", text) ``` @@ -175,7 +175,7 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->extension('my_extension') ->addTable('my_table'); -echo $query->toSQL(); +echo $query->toSql(); // ALTER EXTENSION my_extension ADD TABLE my_table ``` @@ -189,13 +189,13 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->extension('my_extension') ->dropFunction('my_func', ['integer']); -echo $query->toSQL(); +echo $query->toSql(); // ALTER EXTENSION my_extension DROP FUNCTION my_func("integer") $query = alter()->extension('my_extension') ->dropTable('my_table'); -echo $query->toSQL(); +echo $query->toSql(); // ALTER EXTENSION my_extension DROP TABLE my_table ``` @@ -210,7 +210,7 @@ use function Flow\PostgreSql\DSL\drop; $query = drop()->extension('uuid-ossp'); -echo $query->toSQL(); +echo $query->toSql(); // DROP EXTENSION "uuid-ossp" ``` @@ -224,7 +224,7 @@ use function Flow\PostgreSql\DSL\drop; $query = drop()->extension('uuid-ossp') ->ifExists(); -echo $query->toSQL(); +echo $query->toSql(); // DROP EXTENSION IF EXISTS "uuid-ossp" ``` @@ -240,7 +240,7 @@ use function Flow\PostgreSql\DSL\drop; $query = drop()->extension('postgis') ->cascade(); -echo $query->toSQL(); +echo $query->toSql(); // DROP EXTENSION postgis CASCADE ``` @@ -256,7 +256,7 @@ use function Flow\PostgreSql\DSL\drop; $query = drop()->extension('uuid-ossp') ->restrict(); -echo $query->toSQL(); +echo $query->toSql(); // DROP EXTENSION "uuid-ossp" ``` @@ -269,7 +269,7 @@ use function Flow\PostgreSql\DSL\drop; $query = drop()->extension('postgis', 'postgis_raster', 'postgis_topology'); -echo $query->toSQL(); +echo $query->toSql(); // DROP EXTENSION postgis, postgis_raster, postgis_topology ``` @@ -284,7 +284,7 @@ $query = drop()->extension('postgis') ->ifExists() ->cascade(); -echo $query->toSQL(); +echo $query->toSql(); // DROP EXTENSION IF EXISTS postgis CASCADE ``` diff --git a/documentation/components/libs/postgresql/function-procedure-query-builder.md b/documentation/components/libs/postgresql/function-procedure-query-builder.md index ac5fa4e033..f837415820 100644 --- a/documentation/components/libs/postgresql/function-procedure-query-builder.md +++ b/documentation/components/libs/postgresql/function-procedure-query-builder.md @@ -14,15 +14,15 @@ CREATE FUNCTION, CREATE PROCEDURE, ALTER FUNCTION, ALTER PROCEDURE, DROP FUNCTIO ```php function('add_numbers') - ->arguments(func_arg('integer')->named('a'), func_arg('integer')->named('b')) + ->arguments(func_arg(column_type_integer())->named('a'), func_arg(column_type_integer())->named('b')) ->returns('integer') ->language('sql') ->as('SELECT a + b'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE FUNCTION add_numbers(IN a "integer", IN b "integer") RETURNS "integer" LANGUAGE sql AS $$SELECT a + b$$ ``` @@ -31,15 +31,15 @@ echo $query->toSQL(); ```php function('increment') - ->arguments(func_arg('integer')->named('val')) + ->arguments(func_arg(column_type_integer())->named('val')) ->returns('integer') ->language('plpgsql') ->as('BEGIN RETURN val + 1; END;'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE FUNCTION increment(IN val "integer") RETURNS "integer" LANGUAGE plpgsql AS $$BEGIN RETURN val + 1; END;$$ ``` @@ -56,7 +56,7 @@ $query = create()->function('my_func') ->language('sql') ->as('SELECT 1'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE OR REPLACE FUNCTION my_func() RETURNS "integer" LANGUAGE sql AS $$SELECT 1$$ ``` @@ -74,7 +74,7 @@ $query = create()->function('get_users') ->language('sql') ->as('SELECT id, name FROM users'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE FUNCTION get_users() RETURNS TABLE (id "integer", name text) LANGUAGE sql AS $$SELECT id, name FROM users$$ ``` @@ -92,7 +92,7 @@ $query = create()->function('get_user_ids') ->language('sql') ->as('SELECT id FROM users'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE FUNCTION get_user_ids() RETURNS SETOF "integer" LANGUAGE sql AS $$SELECT id FROM users$$ ``` @@ -110,7 +110,7 @@ $query = create()->function('log_event') ->language('sql') ->as('INSERT INTO logs (msg) VALUES (current_timestamp)'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE FUNCTION log_event() RETURNS void LANGUAGE sql AS $$INSERT INTO logs (msg) VALUES (current_timestamp)$$ ``` @@ -119,11 +119,11 @@ echo $query->toSQL(); ```php function('double') - ->arguments(func_arg('integer')->named('x')) + ->arguments(func_arg(column_type_integer())->named('x')) ->returns('integer') ->language('sql') ->immutable() @@ -149,11 +149,11 @@ $query = create()->function('get_time') ```php function('compute') - ->arguments(func_arg('integer')->named('x')) + ->arguments(func_arg(column_type_integer())->named('x')) ->returns('integer') ->language('sql') ->parallel(ParallelSafety::SAFE) @@ -170,10 +170,10 @@ $query = create()->function('compute') ```php function('safe_add') - ->arguments(func_arg('integer')->named('a'), func_arg('integer')->named('b')) + ->arguments(func_arg(column_type_integer())->named('a'), func_arg(column_type_integer())->named('b')) ->returns('integer') ->language('sql') ->strict() // Returns NULL if any input is NULL @@ -181,7 +181,7 @@ $query = create()->function('safe_add') // Or explicitly call on NULL input $query = create()->function('nullable_add') - ->arguments(func_arg('integer')->named('a'), func_arg('integer')->named('b')) + ->arguments(func_arg(column_type_integer())->named('a'), func_arg(column_type_integer())->named('b')) ->returns('integer') ->language('sql') ->calledOnNullInput() // Function is called even with NULL inputs @@ -265,22 +265,22 @@ The `func_arg()` DSL function creates function arguments with various options: ```php named('user_id'); +$arg = func_arg(column_type_integer())->named('user_id'); // With default value -$arg = func_arg('integer')->named('limit')->default('100'); +$arg = func_arg(column_type_integer())->named('limit')->default('100'); // Argument modes -$arg = func_arg('integer')->in(); // IN - input only (default) -$arg = func_arg('integer')->out(); // OUT - output only -$arg = func_arg('integer')->inout(); // INOUT - both input and output -$arg = func_arg('text')->variadic(); // VARIADIC - variable number of arguments +$arg = func_arg(column_type_integer())->in(); // IN - input only (default) +$arg = func_arg(column_type_integer())->out(); // OUT - output only +$arg = func_arg(column_type_integer())->inout(); // INOUT - both input and output +$arg = func_arg(column_type_text())->variadic(); // VARIADIC - variable number of arguments ``` ### Complete Example @@ -288,14 +288,14 @@ $arg = func_arg('text')->variadic(); // VARIADIC - variable number of argumen ```php function('calculate_discount') ->orReplace() ->arguments( - func_arg('numeric')->named('price'), - func_arg('numeric')->named('discount_percent')->default('10') + func_arg(column_type_numeric())->named('price'), + func_arg(column_type_numeric())->named('discount_percent')->default('10') ) ->returns('numeric') ->language('sql') @@ -312,14 +312,14 @@ $query = create()->function('calculate_discount') ```php procedure('update_stats') - ->arguments(func_arg('integer')->named('user_id')) + ->arguments(func_arg(column_type_integer())->named('user_id')) ->language('plpgsql') ->as('BEGIN UPDATE stats SET count = count + 1 WHERE id = user_id; END;'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE PROCEDURE update_stats(IN user_id "integer") LANGUAGE plpgsql AS $$BEGIN UPDATE stats SET count = count + 1 WHERE id = user_id; END;$$ ``` @@ -335,7 +335,7 @@ $query = create()->procedure('my_proc') ->language('sql') ->as('SELECT 1'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE OR REPLACE PROCEDURE my_proc() LANGUAGE sql AS $$SELECT 1$$ ``` @@ -372,13 +372,13 @@ $query = create()->procedure('my_proc') ```php function('my_func') - ->arguments(func_arg('integer')) + ->arguments(func_arg(column_type_integer())) ->immutable(); -echo $query->toSQL(); +echo $query->toSql(); // ALTER FUNCTION my_func("integer") IMMUTABLE ``` @@ -387,14 +387,14 @@ echo $query->toSQL(); ```php function('my_func') - ->arguments(func_arg('integer')) + ->arguments(func_arg(column_type_integer())) ->parallel(ParallelSafety::SAFE); -echo $query->toSQL(); +echo $query->toSql(); // ALTER FUNCTION my_func("integer") PARALLEL safe ``` @@ -403,13 +403,13 @@ echo $query->toSQL(); ```php function('old_name') - ->arguments(func_arg('text')) + ->arguments(func_arg(column_type_text())) ->renameTo('new_name'); -echo $query->toSQL(); +echo $query->toSql(); // ALTER FUNCTION old_name(text) RENAME TO new_name ``` @@ -418,10 +418,10 @@ echo $query->toSQL(); ```php function('my_func') - ->arguments(func_arg('integer')) + ->arguments(func_arg(column_type_integer())) ->cost(500); $query = alter()->function('set_returning_func') @@ -455,13 +455,13 @@ $query = alter()->function('my_func') ```php procedure('old_proc') - ->arguments(func_arg('integer')) + ->arguments(func_arg(column_type_integer())) ->renameTo('new_proc'); -echo $query->toSQL(); +echo $query->toSql(); // ALTER PROCEDURE old_proc("integer") RENAME TO new_proc ``` @@ -475,7 +475,7 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->procedure('my_proc') ->securityDefiner(); -echo $query->toSQL(); +echo $query->toSql(); // ALTER PROCEDURE my_proc SECURITY DEFINER ``` @@ -507,7 +507,7 @@ use function Flow\PostgreSql\DSL\drop; $query = drop()->function('my_func'); -echo $query->toSQL(); +echo $query->toSql(); // DROP FUNCTION my_func ``` @@ -516,12 +516,12 @@ echo $query->toSQL(); ```php function('my_func') - ->arguments(func_arg('integer'), func_arg('text')); + ->arguments(func_arg(column_type_integer()), func_arg(column_type_text())); -echo $query->toSQL(); +echo $query->toSql(); // DROP FUNCTION my_func("integer", text) ``` @@ -530,13 +530,13 @@ echo $query->toSQL(); ```php function('my_func') ->ifExists() - ->arguments(func_arg('integer')); + ->arguments(func_arg(column_type_integer())); -echo $query->toSQL(); +echo $query->toSql(); // DROP FUNCTION IF EXISTS my_func("integer") ``` @@ -545,14 +545,14 @@ echo $query->toSQL(); ```php function('my_func') ->ifExists() - ->arguments(func_arg('integer'), func_arg('text')) + ->arguments(func_arg(column_type_integer()), func_arg(column_type_text())) ->cascade(); -echo $query->toSQL(); +echo $query->toSql(); // DROP FUNCTION IF EXISTS my_func("integer", text) CASCADE ``` @@ -566,7 +566,7 @@ use function Flow\PostgreSql\DSL\drop; $query = drop()->function('my_func') ->restrict(); -echo $query->toSQL(); +echo $query->toSql(); // DROP FUNCTION my_func RESTRICT ``` @@ -581,7 +581,7 @@ use function Flow\PostgreSql\DSL\drop; $query = drop()->procedure('my_proc'); -echo $query->toSQL(); +echo $query->toSql(); // DROP PROCEDURE my_proc ``` @@ -590,14 +590,14 @@ echo $query->toSQL(); ```php procedure('my_proc') ->ifExists() - ->arguments(func_arg('integer')) + ->arguments(func_arg(column_type_integer())) ->cascade(); -echo $query->toSQL(); +echo $query->toSql(); // DROP PROCEDURE IF EXISTS my_proc("integer") CASCADE ``` @@ -612,7 +612,7 @@ use function Flow\PostgreSql\DSL\call; $query = call('update_stats'); -echo $query->toSQL(); +echo $query->toSql(); // CALL update_stats() ``` @@ -626,7 +626,7 @@ use function Flow\PostgreSql\DSL\call; $query = call('update_stats') ->with(123, 'test'); -echo $query->toSQL(); +echo $query->toSql(); // CALL update_stats(123, 'test') ``` @@ -640,7 +640,7 @@ use function Flow\PostgreSql\DSL\call; $query = call('process_data') ->with(42, 'hello', 3.14, true, null); -echo $query->toSQL(); +echo $query->toSql(); // CALL process_data(42, 'hello', 3.14, true, NULL) ``` @@ -655,7 +655,7 @@ use function Flow\PostgreSql\DSL\do_block; $query = do_block('BEGIN RAISE NOTICE $$Hello$$; END;'); -echo $query->toSQL(); +echo $query->toSql(); // DO $outer$BEGIN RAISE NOTICE $$Hello$$; END;$outer$ LANGUAGE plpgsql ``` @@ -668,7 +668,7 @@ use function Flow\PostgreSql\DSL\do_block; $query = do_block('SELECT 1')->language('sql'); -echo $query->toSQL(); +echo $query->toSql(); // DO $$SELECT 1$$ LANGUAGE sql ``` @@ -676,7 +676,7 @@ echo $query->toSQL(); | Function | Description | |----------|-------------| -| `func_arg(string $type)` | Create a function argument | +| `func_arg(ColumnType $type)` | Create a function argument | | `create()->function(string $name)` | Create a new function | | `create()->procedure(string $name)` | Create a new procedure | | `alter()->function(string $name)` | Alter an existing function | diff --git a/documentation/components/libs/postgresql/index-query-builder.md b/documentation/components/libs/postgresql/index-query-builder.md index f88bd718c4..b45a25d1b6 100644 --- a/documentation/components/libs/postgresql/index-query-builder.md +++ b/documentation/components/libs/postgresql/index-query-builder.md @@ -20,7 +20,7 @@ $query = create()->index('idx_users_email') ->on('users') ->columns('email'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE INDEX idx_users_email ON users (email) ``` @@ -36,7 +36,7 @@ $query = create()->index('idx_users_email') ->on('users') ->columns('email'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE UNIQUE INDEX idx_users_email ON users (email) ``` @@ -52,7 +52,7 @@ $query = create()->index('idx_users_email') ->on('users') ->columns('email'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE INDEX IF NOT EXISTS idx_users_email ON users (email) ``` @@ -70,7 +70,7 @@ $query = create()->index('idx_users_email') ->on('users') ->columns('email'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE INDEX CONCURRENTLY idx_users_email ON users (email) ``` @@ -88,7 +88,7 @@ $query = create()->index('idx_users_email') ->on('users') ->columns('email'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE UNIQUE INDEX CONCURRENTLY IF NOT EXISTS idx_users_email ON users (email) ``` @@ -103,7 +103,7 @@ $query = create()->index('idx_users_email') ->on('users', 'public') ->columns('email'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE INDEX idx_users_email ON public.users (email) ``` @@ -164,7 +164,7 @@ $query = create()->index('idx_users_name_email') ->on('users') ->columns('name', 'email'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE INDEX idx_users_name_email ON users (name, email) ``` @@ -182,7 +182,7 @@ $query = create()->index('idx_users_created_at') ->on('users') ->columns(index_col('created_at')->desc()); -echo $query->toSQL(); +echo $query->toSql(); // CREATE INDEX idx_users_created_at ON users (created_at DESC) // With NULLS ordering @@ -190,14 +190,14 @@ $query = create()->index('idx_users_created_at') ->on('users') ->columns(index_col('created_at')->desc()->nullsFirst()); -echo $query->toSQL(); +echo $query->toSql(); // CREATE INDEX idx_users_created_at ON users (created_at DESC NULLS FIRST) $query = create()->index('idx_users_created_at') ->on('users') ->columns(index_col('created_at')->nullsLast()); -echo $query->toSQL(); +echo $query->toSql(); // CREATE INDEX idx_users_created_at ON users (created_at NULLS LAST) ``` @@ -214,7 +214,7 @@ $query = create()->index('idx_users_name_pattern') ->on('users') ->columns(index_col('name')->opclass('text_pattern_ops')); -echo $query->toSQL(); +echo $query->toSql(); // CREATE INDEX idx_users_name_pattern ON users (name text_pattern_ops) ``` @@ -246,7 +246,7 @@ $query = create()->index('idx_users_lower_email') ->on('users') ->columns(index_expr(new RawExpression('lower(email)'))); -echo $query->toSQL(); +echo $query->toSql(); // CREATE INDEX idx_users_lower_email ON users ((lower(email))) ``` @@ -264,7 +264,7 @@ $query = create()->index('idx_users_email') ->columns('email') ->include('name', 'created_at'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE INDEX idx_users_email ON users (email) INCLUDE (name, created_at) ``` @@ -282,7 +282,7 @@ $query = create()->index('idx_users_active_email') ->columns('email') ->where(eq(col('active'), literal(true))); -echo $query->toSQL(); +echo $query->toSql(); // CREATE INDEX idx_users_active_email ON users (email) WHERE active = true ``` @@ -300,7 +300,7 @@ $query = create()->index('idx_users_email') ->columns('email') ->tablespace('fast_storage'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE INDEX idx_users_email ON users (email) TABLESPACE fast_storage ``` @@ -319,7 +319,7 @@ $query = create()->index('idx_users_email') ->columns('email') ->nullsNotDistinct(); -echo $query->toSQL(); +echo $query->toSql(); // CREATE UNIQUE INDEX idx_users_email ON users (email) NULLS NOT DISTINCT ``` @@ -336,7 +336,7 @@ $query = create()->index('idx_users_email') ->onOnly('users') ->columns('email'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE INDEX idx_users_email ON ONLY users (email) ``` @@ -351,7 +351,7 @@ use function Flow\PostgreSql\DSL\drop; $query = drop()->index('idx_users_email'); -echo $query->toSQL(); +echo $query->toSql(); // DROP INDEX idx_users_email ``` @@ -365,7 +365,7 @@ use function Flow\PostgreSql\DSL\drop; $query = drop()->index('idx_users_email') ->ifExists(); -echo $query->toSQL(); +echo $query->toSql(); // DROP INDEX IF EXISTS idx_users_email ``` @@ -381,7 +381,7 @@ use function Flow\PostgreSql\DSL\drop; $query = drop()->index('idx_users_email') ->concurrently(); -echo $query->toSQL(); +echo $query->toSql(); // DROP INDEX CONCURRENTLY idx_users_email ``` @@ -397,7 +397,7 @@ use function Flow\PostgreSql\DSL\drop; $query = drop()->index('idx_users_email') ->cascade(); -echo $query->toSQL(); +echo $query->toSql(); // DROP INDEX idx_users_email CASCADE ``` @@ -412,7 +412,7 @@ $query = drop()->index('idx_users_email') ->ifExists() ->cascade(); -echo $query->toSQL(); +echo $query->toSql(); // DROP INDEX IF EXISTS idx_users_email CASCADE ``` @@ -425,7 +425,7 @@ use function Flow\PostgreSql\DSL\drop; $query = drop()->index('idx_users_email', 'idx_users_name', 'idx_orders_date'); -echo $query->toSQL(); +echo $query->toSql(); // DROP INDEX idx_users_email, idx_users_name, idx_orders_date ``` @@ -438,7 +438,7 @@ use function Flow\PostgreSql\DSL\drop; $query = drop()->index('public.idx_users_email'); -echo $query->toSQL(); +echo $query->toSql(); // DROP INDEX public.idx_users_email ``` @@ -453,7 +453,7 @@ use function Flow\PostgreSql\DSL\reindex_index; $query = reindex_index('idx_users_email'); -echo $query->toSQL(); +echo $query->toSql(); // REINDEX INDEX idx_users_email ``` @@ -468,7 +468,7 @@ use function Flow\PostgreSql\DSL\reindex_table; $query = reindex_table('users'); -echo $query->toSQL(); +echo $query->toSql(); // REINDEX TABLE users ``` @@ -483,7 +483,7 @@ use function Flow\PostgreSql\DSL\reindex_schema; $query = reindex_schema('public'); -echo $query->toSQL(); +echo $query->toSql(); // REINDEX SCHEMA public ``` @@ -498,7 +498,7 @@ use function Flow\PostgreSql\DSL\reindex_database; $query = reindex_database('mydb'); -echo $query->toSQL(); +echo $query->toSql(); // REINDEX DATABASE mydb ``` @@ -514,7 +514,7 @@ use function Flow\PostgreSql\DSL\reindex_index; $query = reindex_index('idx_users_email') ->concurrently(); -echo $query->toSQL(); +echo $query->toSql(); // REINDEX (CONCURRENTLY) INDEX idx_users_email ``` @@ -530,7 +530,7 @@ use function Flow\PostgreSql\DSL\reindex_table; $query = reindex_table('users') ->verbose(); -echo $query->toSQL(); +echo $query->toSql(); // REINDEX (VERBOSE) TABLE users ``` @@ -546,7 +546,7 @@ use function Flow\PostgreSql\DSL\reindex_index; $query = reindex_index('idx_users_email') ->tablespace('fast_storage'); -echo $query->toSQL(); +echo $query->toSql(); // REINDEX (TABLESPACE fast_storage) INDEX idx_users_email ``` @@ -559,7 +559,7 @@ use function Flow\PostgreSql\DSL\reindex_table; $query = reindex_table('public.users'); -echo $query->toSQL(); +echo $query->toSql(); // REINDEX TABLE public.users ``` @@ -575,7 +575,7 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->index('idx_old') ->renameTo('idx_new'); -echo $query->toSQL(); +echo $query->toSql(); // ALTER INDEX idx_old RENAME TO idx_new ``` @@ -590,7 +590,7 @@ $query = alter()->index('idx_old') ->ifExists() ->renameTo('idx_new'); -echo $query->toSQL(); +echo $query->toSql(); // ALTER INDEX IF EXISTS idx_old RENAME TO idx_new ``` @@ -604,7 +604,7 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->index('idx_old', 'public') ->renameTo('idx_new'); -echo $query->toSQL(); +echo $query->toSql(); // ALTER INDEX public.idx_old RENAME TO idx_new ``` @@ -620,7 +620,7 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->index('idx_users_email') ->setTablespace('fast_storage'); -echo $query->toSQL(); +echo $query->toSql(); // ALTER INDEX idx_users_email SET TABLESPACE fast_storage ``` @@ -635,7 +635,7 @@ $query = alter()->index('idx_users_email') ->ifExists() ->setTablespace('fast_storage'); -echo $query->toSQL(); +echo $query->toSql(); // ALTER INDEX IF EXISTS idx_users_email SET TABLESPACE fast_storage ``` diff --git a/documentation/components/libs/postgresql/insert-query-builder.md b/documentation/components/libs/postgresql/insert-query-builder.md index 9a9ddb7de7..c615f18f76 100644 --- a/documentation/components/libs/postgresql/insert-query-builder.md +++ b/documentation/components/libs/postgresql/insert-query-builder.md @@ -18,7 +18,7 @@ $query = insert() ->columns('name', 'email') ->values(literal('John'), literal('john@example.com')); -echo $query->toSQL(); +echo $query->toSql(); // INSERT INTO users (name, email) VALUES ('John', 'john@example.com') ``` @@ -36,10 +36,43 @@ $query = insert() ->columns('name', 'email') ->values(param(1), param(2)); -echo $query->toSQL(); +echo $query->toSql(); // INSERT INTO users (name, email) VALUES ($1, $2) ``` +For queries with many columns, use `parameters()` to generate all positional parameters at once: + +```php +into('users') + ->columns('id', 'name', 'email', 'created_at', 'updated_at') + ->values(...parameters(5)); + +echo $query->toSql(); +// INSERT INTO users (id, name, email, created_at, updated_at) VALUES ($1, $2, $3, $4, $5) +``` + +The `parameters()` function accepts an optional `startAt` argument for multi-row inserts: + +```php +into('users') + ->columns('name', 'email') + ->values(...parameters(2)) + ->values(...parameters(2, startAt: 3)); + +echo $query->toSql(); +// INSERT INTO users (name, email) VALUES ($1, $2), ($3, $4) +``` + ## Multi-Row Insert ```php @@ -53,7 +86,7 @@ $query = insert() ->values(literal('John'), literal('john@example.com')) ->values(literal('Jane'), literal('jane@example.com')); -echo $query->toSQL(); +echo $query->toSql(); // INSERT INTO users (name, email) VALUES ('John', 'john@example.com'), ('Jane', 'jane@example.com') ``` @@ -68,7 +101,7 @@ $query = insert() ->into('users') ->defaultValues(); -echo $query->toSQL(); +echo $query->toSql(); // INSERT INTO users DEFAULT VALUES ``` @@ -88,7 +121,7 @@ $query = insert() ->columns('name', 'email') ->select($selectQuery); -echo $query->toSQL(); +echo $query->toSql(); // INSERT INTO users (name, email) SELECT name, email FROM archived_users ``` @@ -108,7 +141,7 @@ $query = insert() ->values(literal('John'), literal('john@example.com')) ->onConflictDoNothing(); -echo $query->toSQL(); +echo $query->toSql(); // INSERT INTO users (name, email) VALUES ('John', 'john@example.com') ON CONFLICT DO NOTHING ``` @@ -125,7 +158,7 @@ $query = insert() ->values(literal('John'), literal('john@example.com')) ->onConflictDoNothing(conflict_columns(['email'])); -echo $query->toSQL(); +echo $query->toSql(); // INSERT INTO users (name, email) VALUES ('John', 'john@example.com') ON CONFLICT (email) DO NOTHING ``` @@ -142,7 +175,7 @@ $query = insert() ->values(literal('John'), literal('john@example.com')) ->onConflictDoNothing(conflict_constraint('users_pkey')); -echo $query->toSQL(); +echo $query->toSql(); // INSERT INTO users (name, email) VALUES ('John', 'john@example.com') ON CONFLICT ON CONSTRAINT users_pkey DO NOTHING ``` @@ -162,7 +195,7 @@ $query = insert() ['name' => literal('Updated John')] ); -echo $query->toSQL(); +echo $query->toSql(); // INSERT INTO users (email, name) VALUES ('john@example.com', 'John') ON CONFLICT (email) DO UPDATE SET name = 'Updated John' ``` @@ -184,7 +217,7 @@ $query = insert() ['name' => col('excluded.name')] ); -echo $query->toSQL(); +echo $query->toSql(); // INSERT INTO users (email, name) VALUES ($1, $2) ON CONFLICT (email) DO UPDATE SET name = excluded.name ``` @@ -207,7 +240,7 @@ $query = insert() ) ->where(eq(col('users.active'), literal(true))); -echo $query->toSQL(); +echo $query->toSql(); // INSERT INTO users (email, name, active) VALUES ('john@example.com', 'John', true) ON CONFLICT (email) DO UPDATE SET name = 'Updated John' WHERE users.active = true ``` @@ -225,7 +258,7 @@ $query = insert() ->values(literal('John')) ->returning(col('id')); -echo $query->toSQL(); +echo $query->toSql(); // INSERT INTO users (name) VALUES ('John') RETURNING id // Return all columns @@ -235,7 +268,7 @@ $query = insert() ->values(literal('John')) ->returningAll(); -echo $query->toSQL(); +echo $query->toSql(); // INSERT INTO users (name) VALUES ('John') RETURNING * ``` @@ -251,7 +284,7 @@ $query = insert() ->columns('name') ->values(literal('John')); -echo $query->toSQL(); +echo $query->toSql(); // INSERT INTO public.users (name) VALUES ('John') ``` diff --git a/documentation/components/libs/postgresql/merge-query-builder.md b/documentation/components/libs/postgresql/merge-query-builder.md index 3d985f51b4..d32ab75876 100644 --- a/documentation/components/libs/postgresql/merge-query-builder.md +++ b/documentation/components/libs/postgresql/merge-query-builder.md @@ -22,7 +22,7 @@ $query = merge('target_table', 't') 'value' => col('s.value'), ]); -echo $query->toSQL(); +echo $query->toSql(); // MERGE INTO target_table t USING source_table s ON t.id = s.id WHEN MATCHED THEN UPDATE SET name = s.name, value = s.value ``` @@ -39,7 +39,7 @@ $query = merge('target_table', 't') ->whenMatched() ->thenDelete(); -echo $query->toSQL(); +echo $query->toSql(); // MERGE INTO target_table t USING source_table s ON t.id = s.id WHEN MATCHED THEN DELETE ``` @@ -59,7 +59,7 @@ $query = merge('customers') [col('nc.id'), col('nc.name'), col('nc.email')] ); -echo $query->toSQL(); +echo $query->toSql(); // MERGE INTO customers USING new_customers nc ON customers.id = nc.id WHEN NOT MATCHED THEN INSERT (id, name, email) VALUES (nc.id, nc.name, nc.email) ``` @@ -82,7 +82,7 @@ $query = merge('users') 'status' => literal('active'), ]); -echo $query->toSQL(); +echo $query->toSql(); // MERGE INTO users USING new_users n ON users.id = n.id WHEN NOT MATCHED THEN INSERT (id, name, status) VALUES (n.id, n.name, 'active') ``` @@ -109,7 +109,7 @@ $query = merge('inventory', 'i') [col('u.product_id'), col('u.quantity')] ); -echo $query->toSQL(); +echo $query->toSql(); // MERGE INTO inventory i USING updates u ON i.product_id = u.product_id WHEN MATCHED THEN UPDATE SET quantity = u.quantity, updated_at = u.updated_at WHEN NOT MATCHED THEN INSERT (product_id, quantity) VALUES (u.product_id, u.quantity) ``` @@ -130,7 +130,7 @@ $query = merge('products', 'p') 'price' => col('pu.price'), ]); -echo $query->toSQL(); +echo $query->toSql(); // MERGE INTO products p USING price_updates pu ON p.id = pu.product_id WHEN MATCHED AND pu.price > 0 THEN UPDATE SET price = pu.price ``` @@ -147,7 +147,7 @@ $query = merge('products') ->whenMatched() ->thenDoNothing(); -echo $query->toSQL(); +echo $query->toSql(); // MERGE INTO products USING updates u ON products.id = u.id WHEN MATCHED THEN DO NOTHING ``` @@ -173,7 +173,7 @@ $query = merge('users') 'email' => col('src.email'), ]); -echo $query->toSQL(); +echo $query->toSql(); // MERGE INTO users USING (SELECT id, name, email FROM staged_data) src ON users.id = src.id WHEN MATCHED THEN UPDATE SET name = src.name, email = src.email ``` @@ -219,7 +219,7 @@ $query = merge('accounts') 'balance' => param(1), ]); -echo $query->toSQL(); +echo $query->toSql(); // MERGE INTO accounts USING transactions t ON accounts.id = t.account_id WHEN MATCHED THEN UPDATE SET balance = $1 ``` @@ -238,7 +238,7 @@ $query = merge('target', 't') ->whenNotMatchedBySource() ->thenDelete(); -echo $query->toSQL(); +echo $query->toSql(); // MERGE INTO target t USING source s ON t.id = s.id WHEN NOT MATCHED BY SOURCE THEN DELETE ``` @@ -255,7 +255,7 @@ $query = merge('myschema.users', 'u') ->whenMatched() ->thenDoNothing(); -echo $query->toSQL(); +echo $query->toSql(); // MERGE INTO myschema.users u USING public.updates s ON u.id = s.id WHEN MATCHED THEN DO NOTHING ``` diff --git a/documentation/components/libs/postgresql/schema-query-builder.md b/documentation/components/libs/postgresql/schema-query-builder.md index 252c520d63..9ab4e1cb8e 100644 --- a/documentation/components/libs/postgresql/schema-query-builder.md +++ b/documentation/components/libs/postgresql/schema-query-builder.md @@ -18,21 +18,21 @@ use function Flow\PostgreSql\DSL\create; // Simple schema creation $query = create()->schema('my_schema'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE SCHEMA my_schema // With IF NOT EXISTS $query = create()->schema('my_schema') ->ifNotExists(); -echo $query->toSQL(); +echo $query->toSql(); // CREATE SCHEMA IF NOT EXISTS my_schema // With authorization $query = create()->schema('my_schema') ->authorization('admin_user'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE SCHEMA my_schema AUTHORIZATION admin_user // Combined options @@ -40,7 +40,7 @@ $query = create()->schema('my_schema') ->ifNotExists() ->authorization('admin_user'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE SCHEMA IF NOT EXISTS my_schema AUTHORIZATION admin_user ``` @@ -65,7 +65,7 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->schema('old_schema') ->renameTo('new_schema'); -echo $query->toSQL(); +echo $query->toSql(); // ALTER SCHEMA old_schema RENAME TO new_schema ``` @@ -79,7 +79,7 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->schema('my_schema') ->ownerTo('new_owner'); -echo $query->toSQL(); +echo $query->toSql(); // ALTER SCHEMA my_schema OWNER TO new_owner ``` @@ -95,21 +95,21 @@ use function Flow\PostgreSql\DSL\drop; // Simple drop $query = drop()->schema('my_schema'); -echo $query->toSQL(); +echo $query->toSql(); // DROP SCHEMA my_schema // With IF EXISTS $query = drop()->schema('my_schema') ->ifExists(); -echo $query->toSQL(); +echo $query->toSql(); // DROP SCHEMA IF EXISTS my_schema // With CASCADE $query = drop()->schema('my_schema') ->cascade(); -echo $query->toSQL(); +echo $query->toSql(); // DROP SCHEMA my_schema CASCADE // Combined options @@ -117,14 +117,14 @@ $query = drop()->schema('my_schema') ->ifExists() ->cascade(); -echo $query->toSQL(); +echo $query->toSql(); // DROP SCHEMA IF EXISTS my_schema CASCADE // Drop multiple schemas $query = drop()->schema('schema1', 'schema2', 'schema3') ->cascade(); -echo $query->toSQL(); +echo $query->toSql(); // DROP SCHEMA schema1, schema2, schema3 CASCADE ``` diff --git a/documentation/components/libs/postgresql/select-query-builder.md b/documentation/components/libs/postgresql/select-query-builder.md index 097674fdf5..b7d903cfe7 100644 --- a/documentation/components/libs/postgresql/select-query-builder.md +++ b/documentation/components/libs/postgresql/select-query-builder.md @@ -17,14 +17,14 @@ use function Flow\PostgreSql\DSL\{select, col, star, table}; $query = select(col('id'), col('name')) ->from(table('users')); -echo $query->toSQL(); +echo $query->toSql(); // SELECT id, name FROM users // Select all columns $query = select(star()) ->from(table('users')); -echo $query->toSQL(); +echo $query->toSql(); // SELECT * FROM users ``` @@ -35,9 +35,9 @@ echo $query->toSQL(); use function Flow\PostgreSql\DSL\{ select, star, table, col, - eq, gt, lt, gte, lte, neq, between, is_in, like, is_null, + eq, gt, lt, ge, le, ne, between, in_, like, is_null, literal, literal, - cond_and, cond_or, cond_not + and_, or_, not_ }; // Simple condition @@ -45,37 +45,37 @@ $query = select(star()) ->from(table('users')) ->where(eq(col('active'), literal(true))); -echo $query->toSQL(); +echo $query->toSql(); // SELECT * FROM users WHERE active = true // Multiple conditions with AND $query = select(star()) ->from(table('products')) ->where( - cond_and( + and_( gt(col('price'), literal(10)), lt(col('price'), literal(100)), eq(col('in_stock'), literal(true)) ) ); -echo $query->toSQL(); +echo $query->toSql(); // SELECT * FROM products WHERE price > 10 AND price < 100 AND in_stock = true // Complex conditions with AND/OR $query = select(star()) ->from(table('users')) ->where( - cond_and( + and_( eq(col('status'), literal('active')), - cond_or( - gte(col('age'), literal(18)), + or_( + ge(col('age'), literal(18)), eq(col('guardian_approved'), literal(true)) ) ) ); -echo $query->toSQL(); +echo $query->toSql(); // SELECT * FROM users WHERE status = 'active' AND (age >= 18 OR guardian_approved = true) // BETWEEN condition @@ -83,19 +83,19 @@ $query = select(star()) ->from(table('products')) ->where(between(col('price'), literal(10), literal(100))); -echo $query->toSQL(); +echo $query->toSql(); // SELECT * FROM products WHERE price BETWEEN 10 AND 100 // IN condition $query = select(star()) ->from(table('users')) - ->where(is_in(col('status'), [ + ->where(in_(col('status'), [ literal('active'), literal('pending'), literal('verified') ])); -echo $query->toSQL(); +echo $query->toSql(); // SELECT * FROM users WHERE status IN ('active', 'pending', 'verified') // LIKE condition @@ -103,7 +103,7 @@ $query = select(star()) ->from(table('users')) ->where(like(col('email'), literal('%@example.com'))); -echo $query->toSQL(); +echo $query->toSql(); // SELECT * FROM users WHERE email LIKE '%@example.com' ``` @@ -126,7 +126,7 @@ $query = select(col('u.name'), col('o.total')) eq(col('u.id'), col('o.user_id')) ); -echo $query->toSQL(); +echo $query->toSql(); // SELECT u.name, o.total FROM users u JOIN orders o ON u.id = o.user_id // LEFT JOIN @@ -137,7 +137,7 @@ $query = select(col('u.name'), col('o.total')) eq(col('u.id'), col('o.user_id')) ); -echo $query->toSQL(); +echo $query->toSql(); // SELECT u.name, o.total FROM users u LEFT JOIN orders o ON u.id = o.user_id // RIGHT JOIN @@ -148,7 +148,7 @@ $query = select(star()) eq(col('o.user_id'), col('u.id')) ); -echo $query->toSQL(); +echo $query->toSql(); // SELECT * FROM orders o RIGHT JOIN users u ON o.user_id = u.id // FULL JOIN @@ -159,7 +159,7 @@ $query = select(star()) eq(col('a.key'), col('b.key')) ); -echo $query->toSQL(); +echo $query->toSql(); // SELECT * FROM table_a a FULL JOIN table_b b ON a.key = b.key // CROSS JOIN @@ -167,7 +167,7 @@ $query = select(star()) ->from(table('colors')) ->crossJoin(table('sizes')); -echo $query->toSQL(); +echo $query->toSql(); // SELECT * FROM colors CROSS JOIN sizes ``` @@ -187,7 +187,7 @@ $query = select(star()) ->from(table('users')) ->orderBy(asc(col('name'))); -echo $query->toSQL(); +echo $query->toSql(); // SELECT * FROM users ORDER BY name ASC // Multiple columns @@ -198,7 +198,7 @@ $query = select(star()) desc(col('first_name')) ); -echo $query->toSQL(); +echo $query->toSql(); // SELECT * FROM users ORDER BY last_name ASC, first_name DESC // NULLS FIRST / NULLS LAST @@ -209,7 +209,7 @@ $query = select(star()) order_by(col('name'), SortDirection::DESC, NullsPosition::LAST) ); -echo $query->toSQL(); +echo $query->toSql(); // SELECT * FROM products ORDER BY price ASC NULLS FIRST, name DESC NULLS LAST ``` @@ -226,7 +226,7 @@ $query = select(star()) ->limit(10) ->offset(20); -echo $query->toSQL(); +echo $query->toSql(); // SELECT * FROM users ORDER BY id ASC LIMIT 10 OFFSET 20 ``` @@ -253,7 +253,7 @@ $query = with( ->select(star()) ->from(table('active_users')); -echo $query->toSQL(); +echo $query->toSql(); // WITH active_users AS (SELECT id, name FROM users WHERE active = true) SELECT * FROM active_users // Multiple CTEs @@ -264,7 +264,7 @@ $query = with( ->select(star()) ->from(table('users_cte')); -echo $query->toSQL(); +echo $query->toSql(); // WITH users_cte AS (SELECT id, name FROM users), orders_cte AS (SELECT id, user_id FROM orders) SELECT * FROM users_cte // Recursive CTE @@ -273,7 +273,7 @@ $query = with(cte('tree', $recursiveQuery)) ->select(star()) ->from(table('tree')); -echo $query->toSQL(); +echo $query->toSql(); // WITH RECURSIVE tree AS (...) SELECT * FROM tree // Materialized CTE @@ -290,7 +290,7 @@ $query = with( ->select(star()) ->from(table('active_users')); -echo $query->toSQL(); +echo $query->toSql(); // WITH active_users AS MATERIALIZED (SELECT id, name FROM users WHERE active = true) SELECT * FROM active_users ``` @@ -314,7 +314,7 @@ $query = select(col('u.name'), col('o.total')) eq(col('u.id'), col('o.user_id')) ); -echo $query->toSQL(); +echo $query->toSql(); // SELECT u.name, o.total FROM users u LEFT JOIN (SELECT user_id, sum(amount) AS total FROM orders GROUP BY user_id) o ON u.id = o.user_id ``` @@ -324,7 +324,7 @@ echo $query->toSQL(); from(table('users')->as('u')) ->leftJoin( lateral(derived($lateralQuery, 'recent')), - raw_cond('true') + is_true(literal(true)) ); -echo $query->toSQL(); +echo $query->toSql(); // SELECT u.name, recent.id FROM users u LEFT JOIN LATERAL (SELECT * FROM orders WHERE orders.user_id = u.id ORDER BY created_at DESC LIMIT 3) recent ON true ``` @@ -353,7 +353,7 @@ The query builder provides native support for PostgreSQL JSONB operators: from(table('products')) ->where(json_contains(col('metadata'), literal('{"category": "electronics"}'))); -echo $query->toSQL(); +echo $query->toSql(); // SELECT * FROM products WHERE metadata @> '{"category": "electronics"}' // JSONB is contained by (<@) @@ -371,35 +371,35 @@ $query = select(star()) ->from(table('products')) ->where(json_contained_by(col('metadata'), literal('{"category": "electronics", "price": 100}'))); -echo $query->toSQL(); +echo $query->toSql(); // SELECT * FROM products WHERE metadata <@ '{"category": "electronics", "price": 100}' // JSON field access (->) - returns JSON $query = select(json_get(col('metadata'), literal('category'))->as('category')) ->from(table('products')); -echo $query->toSQL(); +echo $query->toSql(); // SELECT metadata -> 'category' AS category FROM products // JSON field access (->>) - returns text $query = select(json_get_text(col('metadata'), literal('name'))->as('product_name')) ->from(table('products')); -echo $query->toSQL(); +echo $query->toSql(); // SELECT metadata ->> 'name' AS product_name FROM products // JSON path access (#>) - returns JSON $query = select(json_path(col('metadata'), literal('{category,name}'))->as('nested')) ->from(table('products')); -echo $query->toSQL(); +echo $query->toSql(); // SELECT metadata #> '{category,name}' AS nested FROM products // JSON path access (#>>) - returns text $query = select(json_path_text(col('metadata'), literal('{category,name}'))->as('nested_text')) ->from(table('products')); -echo $query->toSQL(); +echo $query->toSql(); // SELECT metadata #>> '{category,name}' AS nested_text FROM products // Key exists (?) @@ -407,23 +407,23 @@ $query = select(star()) ->from(table('products')) ->where(json_exists(col('metadata'), literal('category'))); -echo $query->toSQL(); +echo $query->toSql(); // SELECT * FROM products WHERE metadata ? 'category' // Any key exists (?|) $query = select(star()) ->from(table('products')) - ->where(json_exists_any(col('metadata'), raw_expr("array['category', 'name']"))); + ->where(json_exists_any(col('metadata'), array_expr([literal('category'), literal('name')]))); -echo $query->toSQL(); +echo $query->toSql(); // SELECT * FROM products WHERE metadata ?| array['category', 'name'] // All keys exist (?&) $query = select(star()) ->from(table('products')) - ->where(json_exists_all(col('metadata'), raw_expr("array['category', 'name']"))); + ->where(json_exists_all(col('metadata'), array_expr([literal('category'), literal('name')]))); -echo $query->toSQL(); +echo $query->toSql(); // SELECT * FROM products WHERE metadata ?& array['category', 'name'] ``` @@ -435,32 +435,32 @@ PostgreSQL array operators are also supported: ) $query = select(star()) ->from(table('products')) - ->where(array_contains(col('tags'), raw_expr("ARRAY['sale']"))); + ->where(array_contains(col('tags'), array_expr([literal('sale')]))); -echo $query->toSQL(); +echo $query->toSql(); // SELECT * FROM products WHERE tags @> ARRAY['sale'] // Array is contained by (<@) $query = select(star()) ->from(table('products')) - ->where(array_contained_by(col('tags'), raw_expr("ARRAY['sale', 'featured', 'new']"))); + ->where(array_contained_by(col('tags'), array_expr([literal('sale'), literal('featured'), literal('new')]))); -echo $query->toSQL(); +echo $query->toSql(); // SELECT * FROM products WHERE tags <@ ARRAY['sale', 'featured', 'new'] // Array overlap (&&) $query = select(star()) ->from(table('products')) - ->where(array_overlap(col('tags'), raw_expr("ARRAY['sale', 'featured']"))); + ->where(array_overlap(col('tags'), array_expr([literal('sale'), literal('featured')]))); -echo $query->toSQL(); +echo $query->toSql(); // SELECT * FROM products WHERE tags && ARRAY['sale', 'featured'] ``` @@ -481,7 +481,7 @@ $query = select(star()) ->from(table('users')) ->where(regex_match(col('email'), literal('.*@gmail\\.com'))); -echo $query->toSQL(); +echo $query->toSql(); // SELECT * FROM users WHERE email ~ '.*@gmail\.com' // Case-insensitive regex match (~*) @@ -489,7 +489,7 @@ $query = select(star()) ->from(table('users')) ->where(regex_imatch(col('email'), literal('.*@gmail\\.com'))); -echo $query->toSQL(); +echo $query->toSql(); // SELECT * FROM users WHERE email ~* '.*@gmail\.com' // Does not match (!~) @@ -497,7 +497,7 @@ $query = select(star()) ->from(table('users')) ->where(not_regex_match(col('email'), literal('.*@spam\\.com'))); -echo $query->toSQL(); +echo $query->toSql(); // SELECT * FROM users WHERE email !~ '.*@spam\.com' // Does not match case-insensitive (!~*) @@ -505,10 +505,80 @@ $query = select(star()) ->from(table('users')) ->where(not_regex_imatch(col('email'), literal('.*@spam\\.com'))); -echo $query->toSQL(); +echo $query->toSql(); // SELECT * FROM users WHERE email !~* '.*@spam\.com' ``` +## SIMILAR TO + +SQL-standard pattern matching (like LIKE but supports full regex character classes): + +```php +from(table('users')) + ->where(similar_to(col('email'), literal('%@(gmail|yahoo)\\.com'))); + +echo $query->toSql(); +// SELECT * FROM users WHERE email SIMILAR TO '%@(gmail|yahoo)\.com' +``` + +## NOT LIKE + +```php +from(table('users')) + ->where(not_like(col('name'), literal('pg_%'))); + +echo $query->toSql(); +// SELECT * FROM users WHERE name NOT LIKE 'pg_%' +``` + +## IS DISTINCT FROM + +NULL-safe comparison (treats NULL as a known value): + +```php +from(table('users')) + ->where(distinct_from(col('email'), literal('test@example.com'))); + +echo $query->toSql(); +// SELECT * FROM users WHERE email IS DISTINCT FROM 'test@example.com' +``` + +## ALL Condition + +Compare against all values from a subquery or array: + +```php +from(table('products')) + ->where(all_(col('price'), ComparisonOperator::GT, col('thresholds'))); + +echo $query->toSql(); +// SELECT * FROM products WHERE price > ALL(thresholds) +``` + ## Full-Text Search PostgreSQL full-text search operator: @@ -517,14 +587,14 @@ PostgreSQL full-text search operator: from(table('documents')) - ->where(text_search_match(col('content'), raw_expr("to_tsquery('english', 'hello & world')"))); + ->where(text_search_match(col('content'), func('to_tsquery', [literal('english'), literal('hello & world')]))); -echo $query->toSQL(); +echo $query->toSql(); // SELECT * FROM documents WHERE content @@ to_tsquery('english', 'hello & world') ``` @@ -550,7 +620,7 @@ $query = select( ->from(table('orders')) ->groupBy(col('category')); -echo $query->toSQL(); +echo $query->toSql(); // SELECT category, count(*), sum(amount), avg(price), min(created_at), max(updated_at) FROM orders GROUP BY category // GROUP BY with HAVING @@ -559,14 +629,14 @@ $query = select(col('category'), agg_count()->as('cnt')) ->groupBy(col('category')) ->having(gt(agg_count(), literal(5))); -echo $query->toSQL(); +echo $query->toSql(); // SELECT category, count(*) AS cnt FROM products GROUP BY category HAVING count(*) > 5 // COUNT DISTINCT $query = select(agg_count(col('user_id'), true)->as('unique_users')) ->from(table('orders')); -echo $query->toSQL(); +echo $query->toSql(); // SELECT count(DISTINCT user_id) AS unique_users FROM orders ``` @@ -586,25 +656,25 @@ $query2 = select(col('name')) // UNION $query = $query1->union($query2); -echo $query->toSQL(); +echo $query->toSql(); // SELECT name FROM users UNION SELECT name FROM admins // UNION ALL $query = $query1->unionAll($query2); -echo $query->toSQL(); +echo $query->toSql(); // SELECT name FROM users UNION ALL SELECT name FROM admins // INTERSECT $query = $query1->intersect($query2); -echo $query->toSQL(); +echo $query->toSql(); // SELECT name FROM users INTERSECT SELECT name FROM admins // EXCEPT $query = $query1->except($query2); -echo $query->toSQL(); +echo $query->toSql(); // SELECT name FROM users EXCEPT SELECT name FROM admins ``` @@ -629,7 +699,7 @@ $query = select( ) ->from(table('users')); -echo $query->toSQL(); +echo $query->toSql(); // SELECT name, (SELECT count(*) FROM orders WHERE orders.user_id = users.id) AS order_count FROM users // EXISTS subquery @@ -641,7 +711,7 @@ $query = select(star()) ->from(table('users')) ->where(exists($subquery)); -echo $query->toSQL(); +echo $query->toSql(); // SELECT * FROM users WHERE EXISTS (SELECT 1 FROM orders WHERE orders.user_id = users.id) ``` @@ -658,7 +728,7 @@ $query = select(star()) ->from(table('users')) ->where(eq(col('id'), param(1))); -echo $query->toSQL(); +echo $query->toSql(); // SELECT * FROM users WHERE id = $1 ``` @@ -674,7 +744,7 @@ $query = select(star()) ->where(eq(col('id'), literal(1))) ->forUpdate(); -echo $query->toSQL(); +echo $query->toSql(); // SELECT * FROM accounts WHERE id = 1 FOR UPDATE $query = select(star()) @@ -682,7 +752,7 @@ $query = select(star()) ->where(eq(col('id'), literal(1))) ->forShare(); -echo $query->toSQL(); +echo $query->toSql(); // SELECT * FROM accounts WHERE id = 1 FOR SHARE ``` @@ -699,7 +769,7 @@ $query = select( ) ->from(table('users')); -echo $query->toSQL(); +echo $query->toSql(); // SELECT first_name AS fname, last_name AS lname FROM users ``` @@ -715,7 +785,7 @@ $query = select() ->selectDistinct(col('city')) ->from(table('users')); -echo $query->toSQL(); +echo $query->toSql(); // SELECT DISTINCT city FROM users // DISTINCT ON @@ -728,7 +798,7 @@ $query = select() ->from(table('employees')) ->orderBy(asc(col('department')), desc(col('salary'))); -echo $query->toSQL(); +echo $query->toSql(); // SELECT DISTINCT ON (department) name, salary FROM employees ORDER BY department ASC, salary DESC ``` diff --git a/documentation/components/libs/postgresql/sequence-query-builder.md b/documentation/components/libs/postgresql/sequence-query-builder.md index b8ab96e563..394a483bd2 100644 --- a/documentation/components/libs/postgresql/sequence-query-builder.md +++ b/documentation/components/libs/postgresql/sequence-query-builder.md @@ -18,7 +18,7 @@ use function Flow\PostgreSql\DSL\create; $query = create()->sequence('user_id_seq'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE SEQUENCE user_id_seq ``` @@ -31,7 +31,7 @@ use function Flow\PostgreSql\DSL\create; $query = create()->sequence('user_id_seq', 'public'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE SEQUENCE public.user_id_seq ``` @@ -44,7 +44,7 @@ use function Flow\PostgreSql\DSL\create; $query = create()->sequence('user_id_seq')->ifNotExists(); -echo $query->toSQL(); +echo $query->toSql(); // CREATE SEQUENCE IF NOT EXISTS user_id_seq ``` @@ -59,7 +59,7 @@ use function Flow\PostgreSql\DSL\create; $query = create()->sequence('temp_seq')->temporary(); -echo $query->toSQL(); +echo $query->toSql(); // CREATE TEMPORARY SEQUENCE temp_seq ``` @@ -74,7 +74,7 @@ use function Flow\PostgreSql\DSL\create; $query = create()->sequence('fast_seq')->unlogged(); -echo $query->toSQL(); +echo $query->toSql(); // CREATE UNLOGGED SEQUENCE fast_seq ``` @@ -90,7 +90,7 @@ use function Flow\PostgreSql\DSL\create; $query = create()->sequence('user_id_seq') ->startWith(100); -echo $query->toSQL(); +echo $query->toSql(); // CREATE SEQUENCE user_id_seq START 100 ``` @@ -106,7 +106,7 @@ use function Flow\PostgreSql\DSL\create; $query = create()->sequence('user_id_seq') ->incrementBy(10); -echo $query->toSQL(); +echo $query->toSql(); // CREATE SEQUENCE user_id_seq INCREMENT 10 ``` @@ -123,14 +123,14 @@ use function Flow\PostgreSql\DSL\create; $query = create()->sequence('user_id_seq') ->minValue(1); -echo $query->toSQL(); +echo $query->toSql(); // CREATE SEQUENCE user_id_seq MINVALUE 1 // Remove minimum bound $query = create()->sequence('user_id_seq') ->noMinValue(); -echo $query->toSQL(); +echo $query->toSql(); // CREATE SEQUENCE user_id_seq NO MINVALUE ``` @@ -147,14 +147,14 @@ use function Flow\PostgreSql\DSL\create; $query = create()->sequence('user_id_seq') ->maxValue(9999999); -echo $query->toSQL(); +echo $query->toSql(); // CREATE SEQUENCE user_id_seq MAXVALUE 9999999 // Remove maximum bound $query = create()->sequence('user_id_seq') ->noMaxValue(); -echo $query->toSQL(); +echo $query->toSql(); // CREATE SEQUENCE user_id_seq NO MAXVALUE ``` @@ -170,7 +170,7 @@ use function Flow\PostgreSql\DSL\create; $query = create()->sequence('user_id_seq') ->cache(20); -echo $query->toSQL(); +echo $query->toSql(); // CREATE SEQUENCE user_id_seq CACHE 20 ``` @@ -187,14 +187,14 @@ use function Flow\PostgreSql\DSL\create; $query = create()->sequence('user_id_seq') ->cycle(); -echo $query->toSQL(); +echo $query->toSql(); // CREATE SEQUENCE user_id_seq CYCLE // Disable cycling (explicit) $query = create()->sequence('user_id_seq') ->noCycle(); -echo $query->toSQL(); +echo $query->toSql(); // CREATE SEQUENCE user_id_seq NO CYCLE ``` @@ -210,7 +210,7 @@ use function Flow\PostgreSql\DSL\create; $query = create()->sequence('user_id_seq') ->asType('bigint'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE SEQUENCE user_id_seq AS bigint ``` @@ -227,21 +227,21 @@ use function Flow\PostgreSql\DSL\create; $query = create()->sequence('user_id_seq') ->ownedBy('users', 'id'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE SEQUENCE user_id_seq OWNED BY users.id // With schema-qualified table $query = create()->sequence('user_id_seq') ->ownedBy('public.users', 'id'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE SEQUENCE user_id_seq OWNED BY public.users.id // Remove ownership $query = create()->sequence('user_id_seq') ->ownedByNone(); -echo $query->toSQL(); +echo $query->toSql(); // CREATE SEQUENCE user_id_seq OWNED BY "none" ``` @@ -261,7 +261,7 @@ $query = create()->sequence('user_id_seq') ->cache(1) ->noCycle(); -echo $query->toSQL(); +echo $query->toSql(); // CREATE SEQUENCE user_id_seq AS bigint START 1 INCREMENT 1 MINVALUE 1 MAXVALUE 1000000 CACHE 1 NO CYCLE ``` @@ -280,14 +280,14 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->sequence('user_id_seq') ->restart(); -echo $query->toSQL(); +echo $query->toSql(); // ALTER SEQUENCE user_id_seq RESTART // Restart at specific value $query = alter()->sequence('user_id_seq') ->restartWith(1000); -echo $query->toSQL(); +echo $query->toSql(); // ALTER SEQUENCE user_id_seq RESTART 1000 ``` @@ -304,7 +304,7 @@ $query = alter()->sequence('user_id_seq') ->ifExists() ->incrementBy(10); -echo $query->toSQL(); +echo $query->toSql(); // ALTER SEQUENCE IF EXISTS user_id_seq INCREMENT 10 ``` @@ -318,7 +318,7 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->sequence('user_id_seq', 'public') ->incrementBy(10); -echo $query->toSQL(); +echo $query->toSql(); // ALTER SEQUENCE public.user_id_seq INCREMENT 10 ``` @@ -337,7 +337,7 @@ $query = alter()->sequence('user_id_seq') ->maxValue(1000000) ->cache(5); -echo $query->toSQL(); +echo $query->toSql(); // ALTER SEQUENCE user_id_seq INCREMENT 10 MINVALUE 1 MAXVALUE 1000000 CACHE 5 ``` @@ -353,7 +353,7 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->sequence('old_seq') ->renameTo('new_seq'); -echo $query->toSQL(); +echo $query->toSql(); // ALTER SEQUENCE old_seq RENAME TO new_seq ``` @@ -369,7 +369,7 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->sequence('user_id_seq') ->setSchema('new_schema'); -echo $query->toSQL(); +echo $query->toSql(); // ALTER SEQUENCE user_id_seq SET SCHEMA new_schema ``` @@ -385,7 +385,7 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->sequence('user_id_seq') ->ownerTo('new_owner'); -echo $query->toSQL(); +echo $query->toSql(); // ALTER SEQUENCE user_id_seq OWNER TO new_owner ``` @@ -402,14 +402,14 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->sequence('user_id_seq') ->setLogged(); -echo $query->toSQL(); +echo $query->toSql(); // ALTER SEQUENCE user_id_seq SET LOGGED // Make the sequence unlogged $query = alter()->sequence('user_id_seq') ->setUnlogged(); -echo $query->toSQL(); +echo $query->toSql(); // ALTER SEQUENCE user_id_seq SET UNLOGGED ``` @@ -424,7 +424,7 @@ use function Flow\PostgreSql\DSL\drop; $query = drop()->sequence('user_id_seq'); -echo $query->toSQL(); +echo $query->toSql(); // DROP SEQUENCE user_id_seq ``` @@ -437,7 +437,7 @@ use function Flow\PostgreSql\DSL\drop; $query = drop()->sequence('public.user_id_seq'); -echo $query->toSQL(); +echo $query->toSql(); // DROP SEQUENCE public.user_id_seq ``` @@ -450,7 +450,7 @@ use function Flow\PostgreSql\DSL\drop; $query = drop()->sequence('user_id_seq')->ifExists(); -echo $query->toSQL(); +echo $query->toSql(); // DROP SEQUENCE IF EXISTS user_id_seq ``` @@ -463,7 +463,7 @@ use function Flow\PostgreSql\DSL\drop; $query = drop()->sequence('user_id_seq', 'order_id_seq', 'product_id_seq'); -echo $query->toSQL(); +echo $query->toSql(); // DROP SEQUENCE user_id_seq, order_id_seq, product_id_seq ``` @@ -479,7 +479,7 @@ use function Flow\PostgreSql\DSL\drop; $query = drop()->sequence('user_id_seq') ->cascade(); -echo $query->toSQL(); +echo $query->toSql(); // DROP SEQUENCE user_id_seq CASCADE ``` @@ -495,7 +495,7 @@ use function Flow\PostgreSql\DSL\drop; $query = drop()->sequence('user_id_seq') ->restrict(); -echo $query->toSQL(); +echo $query->toSql(); // DROP SEQUENCE user_id_seq ``` @@ -510,7 +510,7 @@ $query = drop()->sequence('user_id_seq') ->ifExists() ->cascade(); -echo $query->toSQL(); +echo $query->toSql(); // DROP SEQUENCE IF EXISTS user_id_seq CASCADE ``` diff --git a/documentation/components/libs/postgresql/table-query-builder.md b/documentation/components/libs/postgresql/table-query-builder.md index 2773cfc469..f4c18bbe6f 100644 --- a/documentation/components/libs/postgresql/table-query-builder.md +++ b/documentation/components/libs/postgresql/table-query-builder.md @@ -13,13 +13,13 @@ The Table Query Builder provides a fluent, type-safe interface for constructing ```php table('users') - ->column(column('id', sql_type_serial())->primaryKey()) - ->column(column('name', sql_type_varchar(100))->notNull()); + ->column(column('id', column_type_serial())->primaryKey()) + ->column(column('name', column_type_varchar(100))->notNull()); -echo $query->toSQL(); +echo $query->toSql(); // CREATE TABLE users (id serial PRIMARY KEY, name varchar(100) NOT NULL) ``` @@ -28,12 +28,12 @@ echo $query->toSQL(); ```php table('users', 'public') - ->column(column('id', sql_type_serial())->primaryKey()); + ->column(column('id', column_type_serial())->primaryKey()); -echo $query->toSQL(); +echo $query->toSql(); // CREATE TABLE public.users (id serial PRIMARY KEY) ``` @@ -42,13 +42,13 @@ echo $query->toSQL(); ```php table('users') ->ifNotExists() - ->column(column('id', sql_type_serial())->primaryKey()); + ->column(column('id', column_type_serial())->primaryKey()); -echo $query->toSQL(); +echo $query->toSql(); // CREATE TABLE IF NOT EXISTS users (id serial PRIMARY KEY) ``` @@ -59,15 +59,15 @@ Columns support various constraints and options: ```php table('users') - ->column(column('id', sql_type_integer())->identity('ALWAYS')) - ->column(column('email', sql_type_varchar(255))->notNull()->unique()) - ->column(column('active', sql_type_boolean())->default(true)) - ->column(column('created_at', sql_type_timestamp())->defaultRaw('CURRENT_TIMESTAMP')); + ->column(column('id', column_type_integer())->identity('ALWAYS')) + ->column(column('email', column_type_varchar(255))->notNull()->unique()) + ->column(column('active', column_type_boolean())->default(true)) + ->column(column('created_at', column_type_timestamp())->defaultRaw('CURRENT_TIMESTAMP')); -echo $query->toSQL(); +echo $query->toSql(); // CREATE TABLE users ( // id int GENERATED ALWAYS AS IDENTITY, // email varchar(255) NOT NULL UNIQUE, @@ -81,13 +81,13 @@ echo $query->toSQL(); ```php table('orders') - ->column(column('id', sql_type_serial())->primaryKey()) - ->column(column('user_id', sql_type_integer())->notNull()->references('users', 'id')); + ->column(column('id', column_type_serial())->primaryKey()) + ->column(column('user_id', column_type_integer())->notNull()->references('users', 'id')); -echo $query->toSQL(); +echo $query->toSql(); // CREATE TABLE orders (id serial PRIMARY KEY, user_id int NOT NULL REFERENCES users(id)) ``` @@ -96,14 +96,14 @@ echo $query->toSQL(); ```php table('users') - ->column(column('first_name', sql_type_varchar(50))) - ->column(column('last_name', sql_type_varchar(50))) - ->column(column('full_name', sql_type_text())->generatedAs("first_name || ' ' || last_name")); + ->column(column('first_name', column_type_varchar(50))) + ->column(column('last_name', column_type_varchar(50))) + ->column(column('full_name', column_type_text())->generatedAs("first_name || ' ' || last_name")); -echo $query->toSQL(); +echo $query->toSql(); // CREATE TABLE users (first_name varchar(50), last_name varchar(50), full_name pg_catalog.text GENERATED ALWAYS AS (first_name || ' ' || last_name) STORED) ``` @@ -114,14 +114,14 @@ echo $query->toSQL(); ```php table('order_items') - ->column(column('order_id', sql_type_integer())->notNull()) - ->column(column('product_id', sql_type_integer())->notNull()) + ->column(column('order_id', column_type_integer())->notNull()) + ->column(column('product_id', column_type_integer())->notNull()) ->constraint(primary_key('order_id', 'product_id')); -echo $query->toSQL(); +echo $query->toSql(); // CREATE TABLE order_items (order_id int NOT NULL, product_id int NOT NULL, PRIMARY KEY (order_id, product_id)) ``` @@ -130,14 +130,14 @@ echo $query->toSQL(); ```php table('users') - ->column(column('id', sql_type_serial())->primaryKey()) - ->column(column('email', sql_type_varchar(255))->notNull()) + ->column(column('id', column_type_serial())->primaryKey()) + ->column(column('email', column_type_varchar(255))->notNull()) ->constraint(unique_constraint('email')); -echo $query->toSQL(); +echo $query->toSql(); // CREATE TABLE users (id serial PRIMARY KEY, email varchar(255) NOT NULL, UNIQUE (email)) ``` @@ -146,14 +146,14 @@ echo $query->toSQL(); ```php table('products') - ->column(column('id', sql_type_serial())->primaryKey()) - ->column(column('price', sql_type_integer())) + ->column(column('id', column_type_serial())->primaryKey()) + ->column(column('price', column_type_integer())) ->constraint(check_constraint('price > 0')->name('positive_price')); -echo $query->toSQL(); +echo $query->toSql(); // CREATE TABLE products (id serial PRIMARY KEY, price int, CONSTRAINT positive_price CHECK (price > 0)) ``` @@ -162,18 +162,18 @@ echo $query->toSQL(); ```php table('orders') - ->column(column('id', sql_type_serial())->primaryKey()) - ->column(column('user_id', sql_type_integer())->notNull()) + ->column(column('id', column_type_serial())->primaryKey()) + ->column(column('user_id', column_type_integer())->notNull()) ->constraint( foreign_key(['user_id'], 'users', ['id']) ->onDelete(ref_action_cascade()) ->onUpdate(ref_action_restrict()) ); -echo $query->toSQL(); +echo $query->toSql(); // CREATE TABLE orders (id serial PRIMARY KEY, user_id int NOT NULL, FOREIGN KEY (user_id) REFERENCES ONLY users (id) ON UPDATE RESTRICT ON DELETE CASCADE) ``` @@ -182,13 +182,13 @@ echo $query->toSQL(); ```php table('temp_results') ->temporary() - ->column(column('id', sql_type_integer())); + ->column(column('id', column_type_integer())); -echo $query->toSQL(); +echo $query->toSql(); // CREATE TEMPORARY TABLE temp_results (id int) ON COMMIT DROP ``` @@ -197,13 +197,13 @@ echo $query->toSQL(); ```php table('cache_data') ->unlogged() - ->column(column('id', sql_type_integer())); + ->column(column('id', column_type_integer())); -echo $query->toSQL(); +echo $query->toSql(); // CREATE UNLOGGED TABLE cache_data (id int) ``` @@ -212,13 +212,13 @@ echo $query->toSQL(); ```php table('employees') - ->column(column('department', sql_type_varchar(100))) + ->column(column('department', column_type_varchar(100))) ->inherits('persons'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE TABLE employees (department varchar(100)) INHERITS (persons) ``` @@ -227,25 +227,25 @@ echo $query->toSQL(); ```php table('logs') - ->column(column('id', sql_type_integer())) - ->column(column('created_at', sql_type_timestamp())) + ->column(column('id', column_type_integer())) + ->column(column('created_at', column_type_timestamp())) ->partitionByRange('created_at'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE TABLE logs (id int, created_at timestamp) PARTITION BY RANGE (created_at) // List partitioning $query = create()->table('sales') - ->column(column('region', sql_type_varchar(50))) + ->column(column('region', column_type_varchar(50))) ->partitionByList('region'); // Hash partitioning $query = create()->table('data') - ->column(column('id', sql_type_integer())) + ->column(column('id', column_type_integer())) ->partitionByHash('id'); ``` @@ -264,7 +264,7 @@ $selectQuery = select() $query = create()->tableAs('users_backup', $selectQuery); -echo $query->toSQL(); +echo $query->toSql(); // CREATE TABLE users_backup AS SELECT id, name FROM users ``` @@ -282,7 +282,7 @@ $selectQuery = select() $query = create()->tableAs('users_backup', $selectQuery) ->ifNotExists(); -echo $query->toSQL(); +echo $query->toSql(); // CREATE TABLE IF NOT EXISTS users_backup AS SELECT id, name FROM users ``` @@ -300,7 +300,7 @@ $selectQuery = select() $query = create()->tableAs('users_backup', $selectQuery) ->columnNames('user_id', 'user_name'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE TABLE users_backup(user_id, user_name) AS SELECT id, name FROM users ``` @@ -318,7 +318,7 @@ $selectQuery = select() $query = create()->tableAs('users_backup', $selectQuery) ->withNoData(); -echo $query->toSQL(); +echo $query->toSql(); // CREATE TABLE users_backup AS SELECT id, name FROM users WITH NO DATA ``` @@ -329,12 +329,12 @@ echo $query->toSQL(); ```php table('users') - ->addColumn(column('email', sql_type_varchar(255))->notNull()); + ->addColumn(column('email', column_type_varchar(255))->notNull()); -echo $query->toSQL(); +echo $query->toSql(); // ALTER TABLE users ADD COLUMN email varchar(255) NOT NULL ``` @@ -348,14 +348,14 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->table('users') ->dropColumn('temp_column'); -echo $query->toSQL(); +echo $query->toSql(); // ALTER TABLE users DROP temp_column // With CASCADE $query = alter()->table('users') ->dropColumn('temp_column', cascade: true); -echo $query->toSQL(); +echo $query->toSql(); // ALTER TABLE users DROP temp_column CASCADE ``` @@ -364,12 +364,12 @@ echo $query->toSQL(); ```php table('users') - ->alterColumnType('name', sql_type_text()); + ->alterColumnType('name', column_type_text()); -echo $query->toSQL(); +echo $query->toSql(); // ALTER TABLE users ALTER COLUMN name TYPE pg_catalog.text ``` @@ -384,14 +384,14 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->table('users') ->alterColumnSetNotNull('email'); -echo $query->toSQL(); +echo $query->toSql(); // ALTER TABLE users ALTER COLUMN email SET NOT NULL // Drop NOT NULL $query = alter()->table('users') ->alterColumnDropNotNull('email'); -echo $query->toSQL(); +echo $query->toSql(); // ALTER TABLE users ALTER COLUMN email DROP NOT NULL ``` @@ -406,14 +406,14 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->table('users') ->alterColumnSetDefault('status', "'active'"); -echo $query->toSQL(); +echo $query->toSql(); // ALTER TABLE users ALTER COLUMN status SET DEFAULT 'active' // Drop default $query = alter()->table('users') ->alterColumnDropDefault('status'); -echo $query->toSQL(); +echo $query->toSql(); // ALTER TABLE users ALTER COLUMN status DROP DEFAULT ``` @@ -427,7 +427,7 @@ use function Flow\PostgreSql\DSL\{alter, unique_constraint}; $query = alter()->table('users') ->addConstraint(unique_constraint('email')->name('users_email_unique')); -echo $query->toSQL(); +echo $query->toSql(); // ALTER TABLE users ADD CONSTRAINT users_email_unique UNIQUE (email) ``` @@ -441,7 +441,7 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->table('users') ->dropConstraint('users_email_unique'); -echo $query->toSQL(); +echo $query->toSql(); // ALTER TABLE users DROP CONSTRAINT users_email_unique ``` @@ -450,14 +450,14 @@ echo $query->toSQL(); ```php table('users') - ->addColumn(column('phone', sql_type_varchar(20))) + ->addColumn(column('phone', column_type_varchar(20))) ->dropColumn('fax') ->alterColumnSetNotNull('email'); -echo $query->toSQL(); +echo $query->toSql(); // ALTER TABLE users ADD COLUMN phone varchar(20), DROP fax, ALTER COLUMN email SET NOT NULL ``` @@ -466,13 +466,13 @@ echo $query->toSQL(); ```php table('users') ->ifExists() - ->addColumn(column('email', sql_type_varchar(255))); + ->addColumn(column('email', column_type_varchar(255))); -echo $query->toSQL(); +echo $query->toSql(); // ALTER TABLE IF EXISTS users ADD COLUMN email varchar(255) ``` @@ -486,7 +486,7 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->table('users') ->renameColumn('old_name', 'new_name'); -echo $query->toSQL(); +echo $query->toSql(); // ALTER TABLE users RENAME COLUMN old_name TO new_name ``` @@ -500,7 +500,7 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->table('users') ->renameConstraint('old_constraint', 'new_constraint'); -echo $query->toSQL(); +echo $query->toSql(); // ALTER TABLE users RENAME CONSTRAINT old_constraint TO new_constraint ``` @@ -514,7 +514,7 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->table('users') ->renameTo('users_archive'); -echo $query->toSQL(); +echo $query->toSql(); // ALTER TABLE users RENAME TO users_archive ``` @@ -528,7 +528,7 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->table('users') ->setSchema('archive'); -echo $query->toSQL(); +echo $query->toSql(); // ALTER TABLE users SET SCHEMA archive ``` @@ -543,7 +543,7 @@ use function Flow\PostgreSql\DSL\drop; $query = drop()->table('users'); -echo $query->toSQL(); +echo $query->toSql(); // DROP TABLE users ``` @@ -557,7 +557,7 @@ use function Flow\PostgreSql\DSL\drop; $query = drop()->table('users') ->ifExists(); -echo $query->toSQL(); +echo $query->toSql(); // DROP TABLE IF EXISTS users ``` @@ -571,7 +571,7 @@ use function Flow\PostgreSql\DSL\drop; $query = drop()->table('users') ->cascade(); -echo $query->toSQL(); +echo $query->toSql(); // DROP TABLE users CASCADE ``` @@ -584,7 +584,7 @@ use function Flow\PostgreSql\DSL\drop; $query = drop()->table('users', 'orders', 'products'); -echo $query->toSQL(); +echo $query->toSql(); // DROP TABLE users, orders, products ``` @@ -599,7 +599,7 @@ use function Flow\PostgreSql\DSL\truncate_table; $query = truncate_table('users'); -echo $query->toSQL(); +echo $query->toSql(); // TRUNCATE users ``` @@ -612,7 +612,7 @@ use function Flow\PostgreSql\DSL\truncate_table; $query = truncate_table('users', 'orders', 'products'); -echo $query->toSQL(); +echo $query->toSql(); // TRUNCATE users, orders, products ``` @@ -626,7 +626,7 @@ use function Flow\PostgreSql\DSL\truncate_table; $query = truncate_table('users') ->restartIdentity(); -echo $query->toSQL(); +echo $query->toSql(); // TRUNCATE users RESTART IDENTITY ``` @@ -640,7 +640,7 @@ use function Flow\PostgreSql\DSL\truncate_table; $query = truncate_table('users') ->cascade(); -echo $query->toSQL(); +echo $query->toSql(); // TRUNCATE users CASCADE ``` @@ -652,47 +652,47 @@ The following SQL type functions are available: | Function | PostgreSQL Type | |----------|-----------------| -| `sql_type_integer()` | int | -| `sql_type_bigint()` | bigint | -| `sql_type_smallint()` | smallint | -| `sql_type_serial()` | serial | -| `sql_type_bigserial()` | bigserial | -| `sql_type_numeric($precision, $scale)` | numeric(p,s) | -| `sql_type_decimal($precision, $scale)` | decimal(p,s) | -| `sql_type_real()` | real | -| `sql_type_double()` | double precision | +| `column_type_integer()` | int | +| `column_type_bigint()` | bigint | +| `column_type_smallint()` | smallint | +| `column_type_serial()` | serial | +| `column_type_bigserial()` | bigserial | +| `column_type_numeric($precision, $scale)` | numeric(p,s) | +| `column_type_decimal($precision, $scale)` | decimal(p,s) | +| `column_type_real()` | real | +| `column_type_double()` | double precision | ### String Types | Function | PostgreSQL Type | |----------|-----------------| -| `sql_type_text()` | text | -| `sql_type_varchar($length)` | varchar(n) | -| `sql_type_char($length)` | char(n) | +| `column_type_text()` | text | +| `column_type_varchar($length)` | varchar(n) | +| `column_type_char($length)` | char(n) | ### Date/Time Types | Function | PostgreSQL Type | |----------|-----------------| -| `sql_type_date()` | date | -| `sql_type_time($precision)` | time | -| `sql_type_timestamp($precision)` | timestamp | -| `sql_type_timestamptz($precision)` | timestamptz | -| `sql_type_interval()` | interval | +| `column_type_date()` | date | +| `column_type_time($precision)` | time | +| `column_type_timestamp($precision)` | timestamp | +| `column_type_timestamptz($precision)` | timestamptz | +| `column_type_interval()` | interval | ### Other Types | Function | PostgreSQL Type | |----------|-----------------| -| `sql_type_boolean()` | boolean | -| `sql_type_uuid()` | uuid | -| `sql_type_json()` | json | -| `sql_type_jsonb()` | jsonb | -| `sql_type_bytea()` | bytea | -| `sql_type_inet()` | inet | -| `sql_type_cidr()` | cidr | -| `sql_type_macaddr()` | macaddr | -| `sql_type_array($elementType)` | type[] | +| `column_type_boolean()` | boolean | +| `column_type_uuid()` | uuid | +| `column_type_json()` | json | +| `column_type_jsonb()` | jsonb | +| `column_type_bytea()` | bytea | +| `column_type_inet()` | inet | +| `column_type_cidr()` | cidr | +| `column_type_macaddr()` | macaddr | +| `column_type_array($elementType)` | type[] | ## Referential Actions diff --git a/documentation/components/libs/postgresql/transaction-query-builder.md b/documentation/components/libs/postgresql/transaction-query-builder.md index 61102841af..b4bf6b6b86 100644 --- a/documentation/components/libs/postgresql/transaction-query-builder.md +++ b/documentation/components/libs/postgresql/transaction-query-builder.md @@ -17,7 +17,7 @@ use function Flow\PostgreSql\DSL\begin; $query = begin(); -echo $query->toSQL(); +echo $query->toSql(); // BEGIN ``` @@ -32,7 +32,7 @@ use Flow\PostgreSql\QueryBuilder\Transaction\IsolationLevel; $query = begin() ->isolationLevel(IsolationLevel::SERIALIZABLE); -echo $query->toSQL(); +echo $query->toSql(); // BEGIN ISOLATION LEVEL SERIALIZABLE ``` @@ -47,14 +47,14 @@ use function Flow\PostgreSql\DSL\begin; $query = begin() ->readOnly(); -echo $query->toSQL(); +echo $query->toSql(); // BEGIN READ ONLY // Read-write transaction (explicit) $query = begin() ->readWrite(); -echo $query->toSQL(); +echo $query->toSql(); // BEGIN READ WRITE ``` @@ -73,7 +73,7 @@ $query = begin() ->readOnly() ->deferrable(); -echo $query->toSQL(); +echo $query->toSql(); // BEGIN ISOLATION LEVEL SERIALIZABLE, READ ONLY, DEFERRABLE ``` @@ -88,7 +88,7 @@ use function Flow\PostgreSql\DSL\commit; $query = commit(); -echo $query->toSQL(); +echo $query->toSql(); // COMMIT ``` @@ -104,7 +104,7 @@ use function Flow\PostgreSql\DSL\commit; $query = commit() ->andChain(); -echo $query->toSQL(); +echo $query->toSql(); // COMMIT AND CHAIN ``` @@ -119,7 +119,7 @@ use function Flow\PostgreSql\DSL\rollback; $query = rollback(); -echo $query->toSQL(); +echo $query->toSql(); // ROLLBACK ``` @@ -135,7 +135,7 @@ use function Flow\PostgreSql\DSL\rollback; $query = rollback() ->toSavepoint('my_savepoint'); -echo $query->toSQL(); +echo $query->toSql(); // ROLLBACK TO SAVEPOINT my_savepoint ``` @@ -149,7 +149,7 @@ use function Flow\PostgreSql\DSL\rollback; $query = rollback() ->andChain(); -echo $query->toSQL(); +echo $query->toSql(); // ROLLBACK AND CHAIN ``` @@ -164,7 +164,7 @@ use function Flow\PostgreSql\DSL\savepoint; $query = savepoint('my_savepoint'); -echo $query->toSQL(); +echo $query->toSql(); // SAVEPOINT my_savepoint ``` @@ -177,7 +177,7 @@ use function Flow\PostgreSql\DSL\release_savepoint; $query = release_savepoint('my_savepoint'); -echo $query->toSQL(); +echo $query->toSql(); // RELEASE my_savepoint ``` @@ -194,7 +194,7 @@ use Flow\PostgreSql\QueryBuilder\Transaction\IsolationLevel; $query = set_transaction() ->isolationLevel(IsolationLevel::SERIALIZABLE); -echo $query->toSQL(); +echo $query->toSql(); // SET TRANSACTION ISOLATION LEVEL SERIALIZABLE ``` @@ -208,7 +208,7 @@ use function Flow\PostgreSql\DSL\set_transaction; $query = set_transaction() ->readOnly(); -echo $query->toSQL(); +echo $query->toSql(); // SET TRANSACTION READ ONLY ``` @@ -225,7 +225,7 @@ $query = set_transaction() ->readOnly() ->deferrable(); -echo $query->toSQL(); +echo $query->toSql(); // SET TRANSACTION ISOLATION LEVEL SERIALIZABLE, READ ONLY, DEFERRABLE ``` @@ -242,7 +242,7 @@ use Flow\PostgreSql\QueryBuilder\Transaction\IsolationLevel; $query = set_session_transaction() ->isolationLevel(IsolationLevel::SERIALIZABLE); -echo $query->toSQL(); +echo $query->toSql(); // SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE ``` @@ -257,7 +257,7 @@ use function Flow\PostgreSql\DSL\transaction_snapshot; $query = transaction_snapshot('00000003-0000001A-1'); -echo $query->toSQL(); +echo $query->toSql(); // SET TRANSACTION SNAPSHOT '00000003-0000001A-1' ``` @@ -274,7 +274,7 @@ use function Flow\PostgreSql\DSL\prepare_transaction; $query = prepare_transaction('my_transaction'); -echo $query->toSQL(); +echo $query->toSql(); // PREPARE TRANSACTION 'my_transaction' ``` @@ -287,7 +287,7 @@ use function Flow\PostgreSql\DSL\commit_prepared; $query = commit_prepared('my_transaction'); -echo $query->toSQL(); +echo $query->toSql(); // COMMIT PREPARED 'my_transaction' ``` @@ -300,7 +300,7 @@ use function Flow\PostgreSql\DSL\rollback_prepared; $query = rollback_prepared('my_transaction'); -echo $query->toSQL(); +echo $query->toSql(); // ROLLBACK PREPARED 'my_transaction' ``` diff --git a/documentation/components/libs/postgresql/trigger-rule-query-builder.md b/documentation/components/libs/postgresql/trigger-rule-query-builder.md index b78b850df2..ff047e15b5 100644 --- a/documentation/components/libs/postgresql/trigger-rule-query-builder.md +++ b/documentation/components/libs/postgresql/trigger-rule-query-builder.md @@ -6,10 +6,10 @@ This document describes the PostgreSQL Trigger and Rule Query Builder components ### CREATE TRIGGER -Create triggers using the `create_trigger()` DSL function: +Create triggers using the `create()->trigger()` builder method: ```php -use function Flow\PostgreSql\DSL\create; +use function Flow\PostgreSql\DSL\{create, col, eq, literal}; use Flow\PostgreSql\QueryBuilder\Schema\Trigger\TriggerEvent; // Basic AFTER INSERT trigger @@ -48,7 +48,7 @@ $builder = create()->trigger('protect_admin') ->before(TriggerEvent::DELETE) ->on('users') ->forEachRow() - ->when(raw_cond('OLD.role = \'admin\'')) + ->when(eq(col('role', 'OLD'), literal('admin'))) ->execute('raise_error'); // CREATE TRIGGER protect_admin BEFORE DELETE ON users FOR EACH ROW WHEN (old.role = 'admin') EXECUTE FUNCTION raise_error() @@ -183,7 +183,7 @@ $builder = alter()->table('users')->disableTriggerUser(); ### CREATE RULE -Create rules using the `create_rule()` DSL function: +Create rules using the `create()->rule()` builder method: ```php use function Flow\PostgreSql\DSL\create; diff --git a/documentation/components/libs/postgresql/type-query-builder.md b/documentation/components/libs/postgresql/type-query-builder.md index e1f02cf429..9e48edf528 100644 --- a/documentation/components/libs/postgresql/type-query-builder.md +++ b/documentation/components/libs/postgresql/type-query-builder.md @@ -23,7 +23,7 @@ $query = create()->compositeType('address') type_attr('zip', 'text') ); -echo $query->toSQL(); +echo $query->toSql(); // CREATE TYPE address AS (street text, city text, zip text) ``` @@ -39,7 +39,7 @@ $query = create()->compositeType('public.address') type_attr('street', 'text') ); -echo $query->toSQL(); +echo $query->toSql(); // CREATE TYPE public.address AS (street text) ``` @@ -55,7 +55,7 @@ $query = create()->compositeType('person') type_attr('name', 'text')->collate('en_US') ); -echo $query->toSQL(); +echo $query->toSql(); // CREATE TYPE person AS (name text COLLATE "en_US") ``` @@ -71,7 +71,7 @@ use function Flow\PostgreSql\DSL\create; $query = create()->enumType('status') ->labels('pending', 'active', 'closed'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE TYPE status AS ENUM ('pending', 'active', 'closed') ``` @@ -85,7 +85,7 @@ use function Flow\PostgreSql\DSL\create; $query = create()->enumType('public.status') ->labels('pending', 'active'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE TYPE public.status AS ENUM ('pending', 'active') ``` @@ -101,7 +101,7 @@ use function Flow\PostgreSql\DSL\create; $query = create()->rangeType('floatrange') ->subtype('float8'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE TYPE floatrange AS RANGE (subtype = float8) ``` @@ -115,7 +115,7 @@ use function Flow\PostgreSql\DSL\create; $query = create()->rangeType('public.floatrange') ->subtype('float8'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE TYPE public.floatrange AS RANGE (subtype = float8) ``` @@ -130,7 +130,7 @@ $query = create()->rangeType('floatrange') ->subtype('float8') ->subtypeOpclass('float8_ops'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE TYPE floatrange AS RANGE (subtype = float8, subtype_opclass = 'float8_ops') ``` @@ -145,7 +145,7 @@ $query = create()->rangeType('textrange') ->subtype('text') ->collation('en_US'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE TYPE textrange AS RANGE (subtype = text, "collation" = 'en_US') ``` @@ -160,7 +160,7 @@ $query = create()->rangeType('daterange') ->subtype('date') ->canonical('daterange_canonical'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE TYPE daterange AS RANGE (subtype = date, canonical = 'daterange_canonical') ``` @@ -175,7 +175,7 @@ $query = create()->rangeType('floatrange') ->subtype('float8') ->subtypeDiff('float8mi'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE TYPE floatrange AS RANGE (subtype = float8, subtype_diff = 'float8mi') ``` @@ -191,7 +191,7 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->enumType('status') ->addValue('archived'); -echo $query->toSQL(); +echo $query->toSql(); // ALTER TYPE status ADD VALUE 'archived' ``` @@ -206,7 +206,7 @@ $query = alter()->enumType('status') ->addValue('archived') ->ifNotExists(); -echo $query->toSQL(); +echo $query->toSql(); // ALTER TYPE status ADD VALUE IF NOT EXISTS 'archived' ``` @@ -220,7 +220,7 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->enumType('status') ->addValueBefore('pending', 'active'); -echo $query->toSQL(); +echo $query->toSql(); // ALTER TYPE status ADD VALUE 'pending' BEFORE 'active' ``` @@ -234,7 +234,7 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->enumType('status') ->addValueAfter('archived', 'closed'); -echo $query->toSQL(); +echo $query->toSql(); // ALTER TYPE status ADD VALUE 'archived' AFTER 'closed' ``` @@ -248,7 +248,7 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->enumType('status') ->renameValue('old_name', 'new_name'); -echo $query->toSQL(); +echo $query->toSql(); // ALTER TYPE status RENAME VALUE 'old_name' TO 'new_name' ``` @@ -263,7 +263,7 @@ use function Flow\PostgreSql\DSL\drop; $query = drop()->type('address'); -echo $query->toSQL(); +echo $query->toSql(); // DROP TYPE address ``` @@ -277,7 +277,7 @@ use function Flow\PostgreSql\DSL\drop; $query = drop()->type('address') ->ifExists(); -echo $query->toSQL(); +echo $query->toSql(); // DROP TYPE IF EXISTS address ``` @@ -293,7 +293,7 @@ use function Flow\PostgreSql\DSL\drop; $query = drop()->type('address') ->cascade(); -echo $query->toSQL(); +echo $query->toSql(); // DROP TYPE address CASCADE ``` @@ -309,7 +309,7 @@ use function Flow\PostgreSql\DSL\drop; $query = drop()->type('address') ->restrict(); -echo $query->toSQL(); +echo $query->toSql(); // DROP TYPE address ``` @@ -322,7 +322,7 @@ use function Flow\PostgreSql\DSL\drop; $query = drop()->type('address', 'status', 'floatrange'); -echo $query->toSQL(); +echo $query->toSql(); // DROP TYPE address, status, floatrange ``` @@ -337,7 +337,7 @@ $query = drop()->type('address') ->ifExists() ->cascade(); -echo $query->toSQL(); +echo $query->toSql(); // DROP TYPE IF EXISTS address CASCADE ``` diff --git a/documentation/components/libs/postgresql/update-query-builder.md b/documentation/components/libs/postgresql/update-query-builder.md index d3ca6055c6..7a75f7ad4b 100644 --- a/documentation/components/libs/postgresql/update-query-builder.md +++ b/documentation/components/libs/postgresql/update-query-builder.md @@ -18,7 +18,7 @@ $query = update() ->set('name', literal('John')) ->where(eq(col('id'), literal(1))); -echo $query->toSQL(); +echo $query->toSql(); // UPDATE users SET name = 'John' WHERE id = 1 ``` @@ -36,7 +36,7 @@ $query = update() ->set('name', param(1)) ->where(eq(col('id'), param(2))); -echo $query->toSQL(); +echo $query->toSql(); // UPDATE users SET name = $1 WHERE id = $2 ``` @@ -54,7 +54,7 @@ $query = update() ->set('email', literal('john@example.com')) ->where(eq(col('id'), literal(1))); -echo $query->toSQL(); +echo $query->toSql(); // UPDATE users SET name = 'John', email = 'john@example.com' WHERE id = 1 // Or use setAll() for multiple columns at once @@ -66,7 +66,7 @@ $query = update() ]) ->where(eq(col('id'), literal(1))); -echo $query->toSQL(); +echo $query->toSql(); // UPDATE users SET name = 'John', email = 'john@example.com' WHERE id = 1 ``` @@ -82,7 +82,7 @@ $query = update() ->set('name', literal('John')) ->where(eq(col('u.id'), literal(1))); -echo $query->toSQL(); +echo $query->toSql(); // UPDATE users u SET name = 'John' WHERE u.id = 1 ``` @@ -101,7 +101,7 @@ $query = update() ->from(table('users')) ->where(eq(col('orders.user_id'), col('users.id'))); -echo $query->toSQL(); +echo $query->toSql(); // UPDATE orders SET status = 'completed' FROM users WHERE orders.user_id = users.id ``` @@ -124,7 +124,7 @@ $query = update() ->set('price', sub_select($subquery)) ->where(eq(col('id'), literal(1))); -echo $query->toSQL(); +echo $query->toSql(); // UPDATE products SET price = (SELECT avg_price FROM price_stats WHERE category = products.category) WHERE id = 1 ``` @@ -140,7 +140,7 @@ $query = update() ->set('price', col('original_price')) ->where(eq(col('id'), literal(1))); -echo $query->toSQL(); +echo $query->toSql(); // UPDATE products SET price = original_price WHERE id = 1 ``` @@ -158,7 +158,7 @@ $query = update() ->where(eq(col('id'), literal(1))) ->returning(col('id'), col('name')); -echo $query->toSQL(); +echo $query->toSql(); // UPDATE users SET name = 'John' WHERE id = 1 RETURNING id, name // Return all columns @@ -168,7 +168,7 @@ $query = update() ->where(eq(col('id'), literal(1))) ->returningAll(); -echo $query->toSQL(); +echo $query->toSql(); // UPDATE users SET name = 'John' WHERE id = 1 RETURNING * ``` @@ -179,20 +179,20 @@ echo $query->toSQL(); use function Flow\PostgreSql\DSL\{ update, literal, literal, - col, eq, gt, cond_and + col, eq, gt, and_ }; $query = update() ->update('users') ->set('status', literal('premium')) ->where( - cond_and( + and_( eq(col('active'), literal(true)), gt(col('orders_count'), literal(100)) ) ); -echo $query->toSQL(); +echo $query->toSql(); // UPDATE users SET status = 'premium' WHERE active = true AND orders_count > 100 ``` diff --git a/documentation/components/libs/postgresql/utility-query-builder.md b/documentation/components/libs/postgresql/utility-query-builder.md index a4fd6e021e..0663fdc58b 100644 --- a/documentation/components/libs/postgresql/utility-query-builder.md +++ b/documentation/components/libs/postgresql/utility-query-builder.md @@ -19,7 +19,7 @@ use function Flow\PostgreSql\DSL\vacuum; $query = vacuum(); -echo $query->toSQL(); +echo $query->toSql(); // VACUUM ``` @@ -32,7 +32,7 @@ use function Flow\PostgreSql\DSL\vacuum; $query = vacuum()->table('users'); -echo $query->toSQL(); +echo $query->toSql(); // VACUUM users ``` @@ -45,7 +45,7 @@ use function Flow\PostgreSql\DSL\vacuum; $query = vacuum()->tables('users', 'orders', 'products'); -echo $query->toSQL(); +echo $query->toSql(); // VACUUM users, orders, products ``` @@ -58,7 +58,7 @@ use function Flow\PostgreSql\DSL\vacuum; $query = vacuum()->table('public.users'); -echo $query->toSQL(); +echo $query->toSql(); // VACUUM public.users ``` @@ -71,7 +71,7 @@ use function Flow\PostgreSql\DSL\vacuum; $query = vacuum()->table('users', 'email', 'name'); -echo $query->toSQL(); +echo $query->toSql(); // VACUUM users (email, name) ``` @@ -86,7 +86,7 @@ use function Flow\PostgreSql\DSL\vacuum; $query = vacuum()->full()->tables('users'); -echo $query->toSQL(); +echo $query->toSql(); // VACUUM (FULL) users ``` @@ -101,7 +101,7 @@ use function Flow\PostgreSql\DSL\vacuum; $query = vacuum()->analyze()->tables('users'); -echo $query->toSQL(); +echo $query->toSql(); // VACUUM (ANALYZE) users ``` @@ -120,7 +120,7 @@ $query = vacuum() ->verbose() ->table('users'); -echo $query->toSQL(); +echo $query->toSql(); // VACUUM (FULL, FREEZE, VERBOSE, ANALYZE) users // Skip locked tables @@ -128,7 +128,7 @@ $query = vacuum() ->skipLocked() ->table('users'); -echo $query->toSQL(); +echo $query->toSql(); // VACUUM (SKIP_LOCKED) users // Parallel vacuum @@ -136,7 +136,7 @@ $query = vacuum() ->parallel(4) ->table('users'); -echo $query->toSQL(); +echo $query->toSql(); // VACUUM (PARALLEL 4) users // Index cleanup options @@ -144,7 +144,7 @@ $query = vacuum() ->indexCleanup(IndexCleanup::OFF) ->table('users'); -echo $query->toSQL(); +echo $query->toSql(); // VACUUM (INDEX_CLEANUP off) users // Process options @@ -153,7 +153,7 @@ $query = vacuum() ->processToast(false) ->table('users'); -echo $query->toSQL(); +echo $query->toSql(); // VACUUM (PROCESS_MAIN true, PROCESS_TOAST false) users // Truncate option @@ -161,7 +161,7 @@ $query = vacuum() ->truncate(true) ->table('users'); -echo $query->toSQL(); +echo $query->toSql(); // VACUUM (TRUNCATE true) users // Freeze option @@ -169,7 +169,7 @@ $query = vacuum() ->freeze() ->table('users'); -echo $query->toSQL(); +echo $query->toSql(); // VACUUM (FREEZE) users // Disable page skipping @@ -177,7 +177,7 @@ $query = vacuum() ->disablePageSkipping() ->table('users'); -echo $query->toSQL(); +echo $query->toSql(); // VACUUM (DISABLE_PAGE_SKIPPING) users ``` @@ -194,7 +194,7 @@ use function Flow\PostgreSql\DSL\analyze; $query = analyze(); -echo $query->toSQL(); +echo $query->toSql(); // ANALYZE ``` @@ -207,7 +207,7 @@ use function Flow\PostgreSql\DSL\analyze; $query = analyze()->table('users'); -echo $query->toSQL(); +echo $query->toSql(); // ANALYZE users ``` @@ -220,7 +220,7 @@ use function Flow\PostgreSql\DSL\analyze; $query = analyze()->table('users', 'email', 'name'); -echo $query->toSQL(); +echo $query->toSql(); // ANALYZE users (email, name) ``` @@ -233,7 +233,7 @@ use function Flow\PostgreSql\DSL\analyze; $query = analyze()->tables('users', 'orders', 'products'); -echo $query->toSQL(); +echo $query->toSql(); // ANALYZE users, orders, products ``` @@ -249,7 +249,7 @@ $query = analyze() ->verbose() ->table('users'); -echo $query->toSQL(); +echo $query->toSql(); // ANALYZE (VERBOSE) users // Skip locked tables @@ -257,7 +257,7 @@ $query = analyze() ->skipLocked() ->table('users'); -echo $query->toSQL(); +echo $query->toSql(); // ANALYZE (SKIP_LOCKED) users ``` @@ -274,7 +274,7 @@ use function Flow\PostgreSql\DSL\{explain, select}; $query = explain(select()->from('users')); -echo $query->toSQL(); +echo $query->toSql(); // EXPLAIN SELECT * FROM users ``` @@ -289,7 +289,7 @@ use function Flow\PostgreSql\DSL\{explain, select}; $query = explain(select()->from('users'))->analyze(); -echo $query->toSQL(); +echo $query->toSql(); // EXPLAIN (ANALYZE) SELECT * FROM users ``` @@ -303,7 +303,7 @@ use function Flow\PostgreSql\DSL\{explain, select}; $query = explain(select()->from('users')) ->verbose(); -echo $query->toSQL(); +echo $query->toSql(); // EXPLAIN (VERBOSE) SELECT * FROM users ``` @@ -319,21 +319,21 @@ use Flow\PostgreSql\QueryBuilder\Utility\ExplainFormat; $query = explain(select()->from('users')) ->format(ExplainFormat::JSON); -echo $query->toSQL(); +echo $query->toSql(); // EXPLAIN (FORMAT json) SELECT * FROM users // XML format $query = explain(select()->from('users')) ->format(ExplainFormat::XML); -echo $query->toSQL(); +echo $query->toSql(); // EXPLAIN (FORMAT xml) SELECT * FROM users // YAML format $query = explain(select()->from('users')) ->format(ExplainFormat::YAML); -echo $query->toSQL(); +echo $query->toSql(); // EXPLAIN (FORMAT yaml) SELECT * FROM users ``` @@ -353,7 +353,7 @@ $query = explain(select()->from('users')) ->costs(true) ->format(ExplainFormat::JSON); -echo $query->toSQL(); +echo $query->toSql(); // EXPLAIN (ANALYZE, VERBOSE, BUFFERS true, TIMING true, COSTS true, FORMAT json) SELECT * FROM users ``` @@ -368,14 +368,14 @@ use function Flow\PostgreSql\DSL\{explain, select}; $query = explain(select()->from('users')) ->costs(true); -echo $query->toSQL(); +echo $query->toSql(); // EXPLAIN (COSTS true) SELECT * FROM users // Without costs $query = explain(select()->from('users')) ->costs(false); -echo $query->toSQL(); +echo $query->toSql(); // EXPLAIN (COSTS false) SELECT * FROM users ``` @@ -392,7 +392,7 @@ use function Flow\PostgreSql\DSL\lock_table; $query = lock_table('users'); -echo $query->toSQL(); +echo $query->toSql(); // LOCK TABLE users ``` @@ -406,40 +406,40 @@ use Flow\PostgreSql\QueryBuilder\Utility\LockMode; // Using mode shortcuts $query = lock_table('users')->accessShare(); -echo $query->toSQL(); +echo $query->toSql(); // LOCK TABLE users IN ACCESS SHARE MODE $query = lock_table('users')->rowShare(); -echo $query->toSQL(); +echo $query->toSql(); // LOCK TABLE users IN ROW SHARE MODE $query = lock_table('users')->rowExclusive(); -echo $query->toSQL(); +echo $query->toSql(); // LOCK TABLE users IN ROW EXCLUSIVE MODE $query = lock_table('users')->shareUpdateExclusive(); -echo $query->toSQL(); +echo $query->toSql(); // LOCK TABLE users IN SHARE UPDATE EXCLUSIVE MODE $query = lock_table('users')->share(); -echo $query->toSQL(); +echo $query->toSql(); // LOCK TABLE users IN SHARE MODE $query = lock_table('users')->shareRowExclusive(); -echo $query->toSQL(); +echo $query->toSql(); // LOCK TABLE users IN SHARE ROW EXCLUSIVE MODE $query = lock_table('users')->exclusive(); -echo $query->toSQL(); +echo $query->toSql(); // LOCK TABLE users IN EXCLUSIVE MODE $query = lock_table('users')->accessExclusive(); -echo $query->toSQL(); +echo $query->toSql(); // LOCK TABLE users IN ACCESS EXCLUSIVE MODE // Using enum $query = lock_table('users')->inMode(LockMode::EXCLUSIVE); -echo $query->toSQL(); +echo $query->toSql(); // LOCK TABLE users IN EXCLUSIVE MODE ``` @@ -453,7 +453,7 @@ use function Flow\PostgreSql\DSL\lock_table; $query = lock_table('users', 'orders') ->exclusive(); -echo $query->toSQL(); +echo $query->toSql(); // LOCK TABLE users, orders IN EXCLUSIVE MODE ``` @@ -468,7 +468,7 @@ $query = lock_table('users') ->exclusive() ->nowait(); -echo $query->toSQL(); +echo $query->toSql(); // LOCK TABLE users IN EXCLUSIVE MODE NOWAIT ``` @@ -500,7 +500,7 @@ use Flow\PostgreSql\QueryBuilder\Utility\CommentTarget; $query = comment(CommentTarget::TABLE, 'users') ->is('User accounts table'); -echo $query->toSQL(); +echo $query->toSql(); // COMMENT ON TABLE users IS 'User accounts table' ``` @@ -515,7 +515,7 @@ use Flow\PostgreSql\QueryBuilder\Utility\CommentTarget; $query = comment(CommentTarget::COLUMN, 'users.email') ->is('User email address'); -echo $query->toSQL(); +echo $query->toSql(); // COMMENT ON COLUMN users.email IS 'User email address' ``` @@ -530,7 +530,7 @@ use Flow\PostgreSql\QueryBuilder\Utility\CommentTarget; $query = comment(CommentTarget::INDEX, 'idx_users_email') ->is('Email lookup index'); -echo $query->toSQL(); +echo $query->toSql(); // COMMENT ON INDEX idx_users_email IS 'Email lookup index' ``` @@ -545,7 +545,7 @@ use Flow\PostgreSql\QueryBuilder\Utility\CommentTarget; $query = comment(CommentTarget::SCHEMA, 'public') ->is('Default schema'); -echo $query->toSQL(); +echo $query->toSql(); // COMMENT ON SCHEMA public IS 'Default schema' ``` @@ -560,7 +560,7 @@ use Flow\PostgreSql\QueryBuilder\Utility\CommentTarget; $query = comment(CommentTarget::TABLE, 'users') ->isNull(); -echo $query->toSQL(); +echo $query->toSql(); // COMMENT ON TABLE users IS NULL ``` @@ -598,7 +598,7 @@ use function Flow\PostgreSql\DSL\cluster; $query = cluster(); -echo $query->toSQL(); +echo $query->toSql(); // CLUSTER ``` @@ -611,7 +611,7 @@ use function Flow\PostgreSql\DSL\cluster; $query = cluster()->table('users'); -echo $query->toSQL(); +echo $query->toSql(); // CLUSTER users ``` @@ -625,7 +625,7 @@ use function Flow\PostgreSql\DSL\cluster; $query = cluster()->table('users') ->using('idx_users_pkey'); -echo $query->toSQL(); +echo $query->toSql(); // CLUSTER users USING idx_users_pkey ``` @@ -638,7 +638,7 @@ use function Flow\PostgreSql\DSL\cluster; $query = cluster()->table('public.users'); -echo $query->toSQL(); +echo $query->toSql(); // CLUSTER public.users ``` @@ -653,7 +653,7 @@ $query = cluster() ->verbose() ->table('users'); -echo $query->toSQL(); +echo $query->toSql(); // CLUSTER (VERBOSE) users ``` @@ -671,7 +671,7 @@ use Flow\PostgreSql\QueryBuilder\Utility\DiscardType; $query = discard(DiscardType::ALL); -echo $query->toSQL(); +echo $query->toSql(); // DISCARD ALL ``` @@ -685,7 +685,7 @@ use Flow\PostgreSql\QueryBuilder\Utility\DiscardType; $query = discard(DiscardType::PLANS); -echo $query->toSQL(); +echo $query->toSql(); // DISCARD PLANS ``` @@ -699,7 +699,7 @@ use Flow\PostgreSql\QueryBuilder\Utility\DiscardType; $query = discard(DiscardType::SEQUENCES); -echo $query->toSQL(); +echo $query->toSql(); // DISCARD SEQUENCES ``` @@ -713,7 +713,7 @@ use Flow\PostgreSql\QueryBuilder\Utility\DiscardType; $query = discard(DiscardType::TEMP); -echo $query->toSQL(); +echo $query->toSql(); // DISCARD TEMP ``` diff --git a/documentation/components/libs/postgresql/view-query-builder.md b/documentation/components/libs/postgresql/view-query-builder.md index 91b96d0624..1037db712a 100644 --- a/documentation/components/libs/postgresql/view-query-builder.md +++ b/documentation/components/libs/postgresql/view-query-builder.md @@ -19,7 +19,7 @@ use function Flow\PostgreSql\DSL\{create, select}; $query = create()->view('active_users') ->as(select()->from('users')); -echo $query->toSQL(); +echo $query->toSql(); // CREATE VIEW active_users AS SELECT * FROM users ``` @@ -36,14 +36,14 @@ use function Flow\PostgreSql\DSL\{create, select}; $query = create()->view('public.active_users') ->as(select()->from('users')); -echo $query->toSQL(); +echo $query->toSql(); // CREATE VIEW public.active_users AS SELECT * FROM users // Using separate schema parameter $query = create()->view('active_users', 'public') ->as(select()->from('users')); -echo $query->toSQL(); +echo $query->toSql(); // CREATE VIEW public.active_users AS SELECT * FROM users ``` @@ -60,7 +60,7 @@ $query = create()->view('active_users') ->orReplace() ->as(select()->from('users')); -echo $query->toSQL(); +echo $query->toSql(); // CREATE OR REPLACE VIEW active_users AS SELECT * FROM users ``` @@ -77,7 +77,7 @@ $query = create()->view('temp_users') ->temporary() ->as(select()->from('users')); -echo $query->toSQL(); +echo $query->toSql(); // CREATE TEMPORARY VIEW temp_users AS SELECT * FROM users ``` @@ -95,7 +95,7 @@ $query = create()->view('subordinates') ->columns('id', 'name', 'manager_id') ->as(select('id', 'name', 'manager_id')->from('employees')); -echo $query->toSQL(); +echo $query->toSql(); // CREATE RECURSIVE VIEW subordinates (id, name, manager_id) AS SELECT id, name, manager_id FROM employees ``` @@ -112,7 +112,7 @@ $query = create()->view('user_info') ->columns('user_id', 'user_name', 'email_address') ->as(select('id', 'name', 'email')->from('users')); -echo $query->toSQL(); +echo $query->toSql(); // CREATE VIEW user_info (user_id, user_name, email_address) AS SELECT id, name, email FROM users ``` @@ -130,7 +130,7 @@ $query = create()->view('active_users') ->as(select()->from('users')->where(eq(col('active'), literal(true)))) ->withCheckOption(); -echo $query->toSQL(); +echo $query->toSql(); // CREATE VIEW active_users AS SELECT * FROM users WHERE active = true WITH CHECK OPTION // WITH CASCADED CHECK OPTION @@ -138,7 +138,7 @@ $query = create()->view('active_users') ->as(select()->from('users')) ->withCascadedCheckOption(); -echo $query->toSQL(); +echo $query->toSql(); // CREATE VIEW active_users AS SELECT * FROM users WITH CASCADED CHECK OPTION // WITH LOCAL CHECK OPTION @@ -146,7 +146,7 @@ $query = create()->view('active_users') ->as(select()->from('users')) ->withLocalCheckOption(); -echo $query->toSQL(); +echo $query->toSql(); // CREATE VIEW active_users AS SELECT * FROM users WITH LOCAL CHECK OPTION ``` @@ -162,7 +162,7 @@ use function Flow\PostgreSql\DSL\{create, select}; $query = create()->materializedView('user_stats') ->as(select()->from('users')); -echo $query->toSQL(); +echo $query->toSql(); // CREATE MATERIALIZED VIEW user_stats AS SELECT * FROM users ``` @@ -177,7 +177,7 @@ $query = create()->materializedView('user_stats') ->ifNotExists() ->as(select()->from('users')); -echo $query->toSQL(); +echo $query->toSql(); // CREATE MATERIALIZED VIEW IF NOT EXISTS user_stats AS SELECT * FROM users ``` @@ -192,7 +192,7 @@ $query = create()->materializedView('user_stats') ->columns('user_id', 'order_count') ->as(select('id', 'count(*)')->from('users')); -echo $query->toSQL(); +echo $query->toSql(); // CREATE MATERIALIZED VIEW user_stats (user_id, order_count) AS SELECT id, count(*) FROM users ``` @@ -209,7 +209,7 @@ $query = create()->materializedView('user_stats') ->using('heap') ->as(select()->from('users')); -echo $query->toSQL(); +echo $query->toSql(); // CREATE MATERIALIZED VIEW user_stats USING heap AS SELECT * FROM users ``` @@ -226,7 +226,7 @@ $query = create()->materializedView('user_stats') ->as(select()->from('users')) ->tablespace('fast_storage'); -echo $query->toSQL(); +echo $query->toSql(); // CREATE MATERIALIZED VIEW user_stats TABLESPACE fast_storage AS SELECT * FROM users ``` @@ -244,7 +244,7 @@ $query = create()->materializedView('user_stats') ->as(select()->from('users')) ->withData(); -echo $query->toSQL(); +echo $query->toSql(); // CREATE MATERIALIZED VIEW user_stats AS SELECT * FROM users WITH DATA // Create empty, populate later with REFRESH @@ -252,7 +252,7 @@ $query = create()->materializedView('user_stats') ->as(select()->from('users')) ->withNoData(); -echo $query->toSQL(); +echo $query->toSql(); // CREATE MATERIALIZED VIEW user_stats AS SELECT * FROM users WITH NO DATA ``` @@ -271,7 +271,7 @@ $query = create()->materializedView('analytics.user_stats') ->tablespace('analytics_ts') ->withNoData(); -echo $query->toSQL(); +echo $query->toSql(); // CREATE MATERIALIZED VIEW IF NOT EXISTS analytics.user_stats (user_id, order_count, total_spent) // USING heap TABLESPACE analytics_ts AS SELECT id, count(*), sum(total) FROM users WITH NO DATA ``` @@ -290,7 +290,7 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->view('old_view') ->renameTo('new_view'); -echo $query->toSQL(); +echo $query->toSql(); // ALTER VIEW old_view RENAME TO new_view ``` @@ -307,7 +307,7 @@ $query = alter()->view('old_view') ->ifExists() ->renameTo('new_view'); -echo $query->toSQL(); +echo $query->toSql(); // ALTER VIEW IF EXISTS old_view RENAME TO new_view ``` @@ -323,7 +323,7 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->view('my_view') ->setSchema('archive'); -echo $query->toSQL(); +echo $query->toSql(); // ALTER VIEW my_view SET SCHEMA archive ``` @@ -339,7 +339,7 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->view('my_view') ->ownerTo('new_owner'); -echo $query->toSQL(); +echo $query->toSql(); // ALTER VIEW my_view OWNER TO new_owner ``` @@ -355,7 +355,7 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->materializedView('old_matview') ->renameTo('new_matview'); -echo $query->toSQL(); +echo $query->toSql(); // ALTER MATERIALIZED VIEW old_matview RENAME TO new_matview ``` @@ -370,7 +370,7 @@ $query = alter()->materializedView('old_matview') ->ifExists() ->renameTo('new_matview'); -echo $query->toSQL(); +echo $query->toSql(); // ALTER MATERIALIZED VIEW IF EXISTS old_matview RENAME TO new_matview ``` @@ -384,7 +384,7 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->materializedView('my_matview') ->setSchema('archive'); -echo $query->toSQL(); +echo $query->toSql(); // ALTER MATERIALIZED VIEW my_matview SET SCHEMA archive ``` @@ -398,7 +398,7 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->materializedView('my_matview') ->ownerTo('new_owner'); -echo $query->toSQL(); +echo $query->toSql(); // ALTER MATERIALIZED VIEW my_matview OWNER TO new_owner ``` @@ -414,7 +414,7 @@ use function Flow\PostgreSql\DSL\alter; $query = alter()->materializedView('my_matview') ->setTablespace('fast_storage'); -echo $query->toSQL(); +echo $query->toSql(); // ALTER MATERIALIZED VIEW my_matview SET TABLESPACE fast_storage // With IF EXISTS @@ -422,7 +422,7 @@ $query = alter()->materializedView('my_matview') ->ifExists() ->setTablespace('fast_storage'); -echo $query->toSQL(); +echo $query->toSql(); // ALTER MATERIALIZED VIEW IF EXISTS my_matview SET TABLESPACE fast_storage ``` @@ -437,7 +437,7 @@ use function Flow\PostgreSql\DSL\drop; $query = drop()->view('active_users'); -echo $query->toSQL(); +echo $query->toSql(); // DROP VIEW active_users ``` @@ -450,7 +450,7 @@ use function Flow\PostgreSql\DSL\drop; $query = drop()->view('view1', 'view2', 'view3'); -echo $query->toSQL(); +echo $query->toSql(); // DROP VIEW view1, view2, view3 ``` @@ -464,7 +464,7 @@ use function Flow\PostgreSql\DSL\drop; $query = drop()->view('active_users') ->ifExists(); -echo $query->toSQL(); +echo $query->toSql(); // DROP VIEW IF EXISTS active_users ``` @@ -480,7 +480,7 @@ use function Flow\PostgreSql\DSL\drop; $query = drop()->view('active_users') ->cascade(); -echo $query->toSQL(); +echo $query->toSql(); // DROP VIEW active_users CASCADE ``` @@ -495,7 +495,7 @@ $query = drop()->view('active_users') ->ifExists() ->cascade(); -echo $query->toSQL(); +echo $query->toSql(); // DROP VIEW IF EXISTS active_users CASCADE ``` @@ -510,7 +510,7 @@ use function Flow\PostgreSql\DSL\drop; $query = drop()->materializedView('user_stats'); -echo $query->toSQL(); +echo $query->toSql(); // DROP MATERIALIZED VIEW user_stats ``` @@ -525,7 +525,7 @@ $query = drop()->materializedView('user_stats') ->ifExists() ->cascade(); -echo $query->toSQL(); +echo $query->toSql(); // DROP MATERIALIZED VIEW IF EXISTS user_stats CASCADE ``` @@ -542,7 +542,7 @@ use function Flow\PostgreSql\DSL\refresh_materialized_view; $query = refresh_materialized_view('user_stats'); -echo $query->toSQL(); +echo $query->toSql(); // REFRESH MATERIALIZED VIEW user_stats ``` @@ -555,7 +555,7 @@ use function Flow\PostgreSql\DSL\refresh_materialized_view; $query = refresh_materialized_view('analytics.user_stats'); -echo $query->toSQL(); +echo $query->toSql(); // REFRESH MATERIALIZED VIEW analytics.user_stats ``` @@ -571,7 +571,7 @@ use function Flow\PostgreSql\DSL\refresh_materialized_view; $query = refresh_materialized_view('user_stats') ->concurrently(); -echo $query->toSQL(); +echo $query->toSql(); // REFRESH MATERIALIZED VIEW CONCURRENTLY user_stats ``` @@ -586,14 +586,14 @@ use function Flow\PostgreSql\DSL\refresh_materialized_view; $query = refresh_materialized_view('user_stats') ->withData(); -echo $query->toSQL(); +echo $query->toSql(); // REFRESH MATERIALIZED VIEW user_stats WITH DATA // Empty the view $query = refresh_materialized_view('user_stats') ->withNoData(); -echo $query->toSQL(); +echo $query->toSql(); // REFRESH MATERIALIZED VIEW user_stats WITH NO DATA ``` @@ -608,7 +608,7 @@ $query = refresh_materialized_view('user_stats') ->concurrently() ->withData(); -echo $query->toSQL(); +echo $query->toSql(); // REFRESH MATERIALIZED VIEW CONCURRENTLY user_stats WITH DATA ``` diff --git a/documentation/installation/packages/symfony-postgresql-bundle.md b/documentation/installation/packages/symfony-postgresql-bundle.md new file mode 100644 index 0000000000..ed9f7c274e --- /dev/null +++ b/documentation/installation/packages/symfony-postgresql-bundle.md @@ -0,0 +1,39 @@ +--- +seo_title: "Installing Symfony PostgreSQL Bundle" +seo_description: > + How to install flow-php/symfony-postgresql-bundle in your PHP project using Composer. +--- + +# Symfony PostgreSQL Bundle + +- [Back](/documentation/installation.md) +- [Documentation](/documentation/components/bridges/symfony-postgresql-bundle.md) +- [Packagist](https://packagist.org/packages/flow-php/symfony-postgresql-bundle) + +[TOC] + +## Composer + +```bash +composer require flow-php/symfony-postgresql-bundle:~--FLOW_PHP_VERSION-- +``` + +## Core Dependencies + +- [flow-php/postgresql](/documentation/installation/packages/postgresql.md) +- [flow-php/filesystem](/documentation/installation/packages/filesystem.md) +- [symfony/config](https://packagist.org/packages/symfony/config) +- [symfony/console](https://packagist.org/packages/symfony/console) +- [symfony/dependency-injection](https://packagist.org/packages/symfony/dependency-injection) +- [symfony/http-kernel](https://packagist.org/packages/symfony/http-kernel) +- [twig/twig](https://packagist.org/packages/twig/twig) + +## Recommended Extensions + +- `ext-pgsql` — required for database connections and query execution +- [`ext-pg_query`](/documentation/components/extensions/pg-query-ext.md) — required for schema diffing (`migrations:diff`), SQL parsing and AST manipulation +- `ext-protobuf` — significantly faster protobuf deserialization for `ext-pg_query` AST parsing (without it, the slower userland `google/protobuf` package is used) + +## Suggested Dependencies + +- [flow-php/symfony-telemetry-bundle](/documentation/installation/packages/symfony-telemetry-bundle.md) — for telemetry integration (distributed tracing, metrics, logging) diff --git a/documentation/installation/packages/symfony-telemetry-bundle.md b/documentation/installation/packages/symfony-telemetry-bundle.md index 01fdb52de2..1d473bca48 100644 --- a/documentation/installation/packages/symfony-telemetry-bundle.md +++ b/documentation/installation/packages/symfony-telemetry-bundle.md @@ -20,6 +20,8 @@ composer require flow-php/symfony-telemetry-bundle:~--FLOW_PHP_VERSION-- ## Core Dependencies +- [flow-php/telemetry](/documentation/installation/packages/telemetry.md) +- [flow-php/symfony-http-foundation-telemetry-bridge](/documentation/installation/packages/symfony-http-foundation-telemetry-bridge.md) - [symfony/config](https://packagist.org/packages/symfony/config) - [symfony/console](https://packagist.org/packages/symfony/console) - [symfony/dependency-injection](https://packagist.org/packages/symfony/dependency-injection) @@ -27,19 +29,12 @@ composer require flow-php/symfony-telemetry-bundle:~--FLOW_PHP_VERSION-- ## Suggested Dependencies -```bash -# For Doctrine DBAL tracing -composer require doctrine/dbal - -# For PSR-18 HTTP client tracing -composer require flow-php/psr18-telemetry-bridge:~--FLOW_PHP_VERSION-- +- [flow-php/symfony-postgresql-bundle](/documentation/installation/packages/symfony-postgresql-bundle.md) — for PostgreSQL database management and migrations with telemetry support +- [flow-php/psr18-telemetry-bridge](/documentation/installation/packages/psr18-telemetry-bridge.md) — for PSR-18 HTTP client tracing +- [flow-php/telemetry-otlp-bridge](/documentation/installation/packages/telemetry-otlp-bridge.md) — for OTLP exporter support +- [symfony/messenger](https://packagist.org/packages/symfony/messenger) — for Messenger tracing middleware +- [twig/twig](https://packagist.org/packages/twig/twig) — for Twig template tracing -# For OTLP exporter support -composer require flow-php/telemetry-otlp-bridge:~--FLOW_PHP_VERSION-- +## Optional Dependencies -# For Messenger tracing middleware -composer require symfony/messenger - -# For Twig template tracing -composer require twig/twig -``` +- [doctrine/dbal](https://packagist.org/packages/doctrine/dbal) — for Doctrine DBAL tracing diff --git a/documentation/upgrading.md b/documentation/upgrading.md index f2b395b3c7..6312d01a12 100644 --- a/documentation/upgrading.md +++ b/documentation/upgrading.md @@ -7,6 +7,252 @@ Please follow the instructions for your specific version to ensure a smooth upgr --- +## Upgrading from 0.35.x to 0.36.x + +### 1) PostgreSQL Library: `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) PostgreSQL Library: `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) PostgreSQL Library: 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) PostgreSQL Library: 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) PostgreSQL Library: 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 | + +--- + +## Upgrading from 0.34.x to 0.35.x + +### 1) PostgreSQL Library: `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) PostgreSQL Library: `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 diff --git a/manifest.json b/manifest.json index 9e28a6b9fe..8044641e7e 100644 --- a/manifest.json +++ b/manifest.json @@ -181,6 +181,11 @@ "path": "src/bridge/symfony/http-foundation-telemetry", "type": "bridge" }, + { + "name": "flow-php/symfony-postgresql-bundle", + "path": "src/bridge/symfony/postgresql-bundle", + "type": "bridge" + }, { "name": "flow-php/symfony-telemetry-bundle", "path": "src/bridge/symfony/telemetry-bundle", diff --git a/phpdoc/bridge.symfony.postgresql-migrations.xml b/phpdoc/bridge.symfony.postgresql-migrations.xml new file mode 100644 index 0000000000..b87c891e8d --- /dev/null +++ b/phpdoc/bridge.symfony.postgresql-migrations.xml @@ -0,0 +1,24 @@ + + + Flow PHP + + ./../web/landing/build/documentation/api/bridge/symfony/postgresql-migrations + ./../var/phpdocumentor/cache/bridge/symfony/postgresql-migrations + + + + + src/bridge/symfony/postgresql-bundle/src + + postgresql-migrations + Symfony PostgreSQL Migrations Bundle + public + false + + + + diff --git a/phpdoc/lib.postgresql-migrations.xml b/phpdoc/lib.postgresql-migrations.xml new file mode 100644 index 0000000000..94f7d1a7b2 --- /dev/null +++ b/phpdoc/lib.postgresql-migrations.xml @@ -0,0 +1,24 @@ + + + Flow PHP + + ./../web/landing/build/documentation/api/lib/postgresql-migrations + ./../var/phpdocumentor/cache/lib/postgresql-migrations + + + + + src/lib/postgresql/src/Flow/PostgreSql/Migrations + + postgresql-migrations + PostgreSQL Migrations + public + false + + + + diff --git a/phpstan.neon b/phpstan.neon index 2c21601abf..40e51ea7a0 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -31,6 +31,7 @@ parameters: - src/bridge/psr18/telemetry/src - src/bridge/symfony/http-foundation/src - src/bridge/symfony/http-foundation-telemetry/src + - src/bridge/symfony/postgresql-bundle/src - src/bridge/symfony/telemetry-bundle/src - src/bridge/telemetry/otlp/src - src/lib/array-dot/src @@ -71,6 +72,7 @@ parameters: - src/bridge/psr18/telemetry/tests - src/bridge/symfony/http-foundation/tests - src/bridge/symfony/http-foundation-telemetry/tests + - src/bridge/symfony/postgresql-bundle/tests - src/bridge/symfony/telemetry-bundle/tests - src/bridge/telemetry/otlp/tests - src/lib/telemetry/tests @@ -89,6 +91,8 @@ parameters: - src/lib/parquet/src/Flow/Parquet/BinaryReader/* - src/lib/parquet/src/Flow/Parquet/Dremel/ColumnData/DefinitionConverter.php - src/lib/postgresql/src/Flow/PostgreSql/Protobuf/* + - src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Resources/config/* + - src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/Command/* - src/bridge/symfony/telemetry-bundle/src/Flow/Bridge/Symfony/TelemetryBundle/Resources/config/instrumentation/* - src/bridge/symfony/telemetry-bundle/tests/Flow/Bridge/Symfony/TelemetryBundle/Tests/Unit/DependencyInjection/ConfigurationTest.php - src/bridge/symfony/telemetry-bundle/src/Flow/Bridge/Symfony/TelemetryBundle/Instrumentation/Messenger/TracingMiddleware.php diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 7d5e2869f6..987ba12eb1 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -95,6 +95,12 @@ src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration + + src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit + + + src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Integration + src/bridge/filesystem/azure/tests/Flow/Filesystem/Bridge/Azure/Tests/Unit @@ -143,6 +149,12 @@ src/bridge/symfony/http-foundation-telemetry/tests/Flow/Bridge/Symfony/HttpFoundationTelemetry/Tests/Integration + + src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit + + + src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration + src/bridge/symfony/telemetry-bundle/tests/Flow/Bridge/Symfony/TelemetryBundle/Tests/Unit diff --git a/shell.nix b/shell.nix index 269812e782..21b6967d63 100644 --- a/shell.nix +++ b/shell.nix @@ -17,7 +17,8 @@ assert (!(with-c && with-pg-query-ext)) || builtins.throw "Cannot use --arg with let nixpkgs = fetchTarball { - url = "https://github.com/NixOS/nixpkgs/archive/refs/heads/nixos-25.11.tar.gz"; + url = "https://github.com/NixOS/nixpkgs/archive/03158cb739fc4a09babe7949900bfc221871d642.tar.gz"; + sha256 = "0vl4iwqcpbczhzb3xbckjb86brcsxkcz4wcbqzidia2fyhm9llmx"; }; pkgs = import nixpkgs { diff --git a/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/EntryTypesMap.php b/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/EntryTypesMap.php index 75ac52fb28..85bbb1e2a5 100644 --- a/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/EntryTypesMap.php +++ b/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/EntryTypesMap.php @@ -8,7 +8,7 @@ use Flow\ETL\Row\Entry; use Flow\ETL\Row\Entry\{BooleanEntry, DateEntry, DateTimeEntry, EnumEntry, FloatEntry, HTMLElementEntry, HTMLEntry, IntegerEntry, JsonEntry, ListEntry, MapEntry, StringEntry, StructureEntry, TimeEntry, UuidEntry, XMLElementEntry, XMLEntry}; use Flow\PostgreSql\Client\TypedValue; -use Flow\PostgreSql\Client\Types\PostgreSqlType; +use Flow\PostgreSql\Client\Types\ValueType; /** * Maps ETL Entry types to PostgreSQL types. @@ -23,8 +23,8 @@ * * // Override specific types * $map = new EntryTypesMap([ - * IntegerEntry::class => PostgreSqlType::INT2, - * ListEntry::class => PostgreSqlType::TEXT_ARRAY, + * IntegerEntry::class => ValueType::INT2, + * ListEntry::class => ValueType::TEXT_ARRAY, * ]); * ``` */ @@ -33,35 +33,35 @@ /** * Default mapping of Entry classes to PostgreSQL types. * - * @var array>, PostgreSqlType> + * @var array>, ValueType> */ public const array DEFAULT_TYPES = [ - StringEntry::class => PostgreSqlType::TEXT, - IntegerEntry::class => PostgreSqlType::INT8, - FloatEntry::class => PostgreSqlType::FLOAT8, - BooleanEntry::class => PostgreSqlType::BOOL, - DateEntry::class => PostgreSqlType::DATE, - DateTimeEntry::class => PostgreSqlType::TIMESTAMPTZ, - TimeEntry::class => PostgreSqlType::TIME, - UuidEntry::class => PostgreSqlType::UUID, - JsonEntry::class => PostgreSqlType::JSONB, - XMLEntry::class => PostgreSqlType::XML, - XMLElementEntry::class => PostgreSqlType::XML, - HTMLEntry::class => PostgreSqlType::TEXT, - HTMLElementEntry::class => PostgreSqlType::TEXT, - EnumEntry::class => PostgreSqlType::TEXT, - ListEntry::class => PostgreSqlType::JSONB, - MapEntry::class => PostgreSqlType::JSONB, - StructureEntry::class => PostgreSqlType::JSONB, + StringEntry::class => ValueType::TEXT, + IntegerEntry::class => ValueType::INT8, + FloatEntry::class => ValueType::FLOAT8, + BooleanEntry::class => ValueType::BOOL, + DateEntry::class => ValueType::DATE, + DateTimeEntry::class => ValueType::TIMESTAMPTZ, + TimeEntry::class => ValueType::TIME, + UuidEntry::class => ValueType::UUID, + JsonEntry::class => ValueType::JSONB, + XMLEntry::class => ValueType::XML, + XMLElementEntry::class => ValueType::XML, + HTMLEntry::class => ValueType::TEXT, + HTMLElementEntry::class => ValueType::TEXT, + EnumEntry::class => ValueType::TEXT, + ListEntry::class => ValueType::JSONB, + MapEntry::class => ValueType::JSONB, + StructureEntry::class => ValueType::JSONB, ]; /** - * @var array>, PostgreSqlType> + * @var array>, ValueType> */ private array $typeMap; /** - * @param array>, PostgreSqlType> $overrides Entry class to PostgreSqlType mappings that override defaults + * @param array>, ValueType> $overrides Entry class to ValueType mappings that override defaults */ public function __construct(array $overrides = []) { 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 bf23502103..943782a346 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 @@ -10,7 +10,7 @@ use Flow\ETL\Extractor\Signal; use Flow\ETL\{Extractor, FlowContext, Schema}; use Flow\PostgreSql\Client\Client; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; /** * PostgreSQL extractor using server-side cursors for memory-efficient extraction. @@ -36,7 +36,7 @@ final class PostgreSqlCursorExtractor implements Extractor */ public function __construct( private readonly Client $client, - private readonly string|SqlQuery $query, + private readonly string|Sql $query, private readonly array $parameters = [], ) { } 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 a3198d7bf6..304e536018 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 @@ -11,7 +11,7 @@ use Flow\ETL\Extractor\Signal; use Flow\ETL\{Extractor, FlowContext, Schema}; use Flow\PostgreSql\Client\Client; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; final class PostgreSqlKeySetExtractor implements Extractor { @@ -26,7 +26,7 @@ final class PostgreSqlKeySetExtractor implements Extractor */ public function __construct( private readonly Client $client, - private readonly string|SqlQuery $query, + private readonly string|Sql $query, private readonly KeySet $keySet, private readonly array $parameters = [], ) { @@ -35,7 +35,7 @@ public function __construct( public function extract(FlowContext $context) : \Generator { $uri = 'postgresql://keyset'; - $sql = $this->query instanceof SqlQuery ? $this->query->toSql() : $this->query; + $sql = $this->query instanceof Sql ? $this->query->toSql() : $this->query; $totalFetched = 0; $cursorValues = null; 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 6a75dc5613..22422853b8 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 @@ -10,7 +10,7 @@ use Flow\ETL\Extractor\Signal; use Flow\ETL\{Extractor, FlowContext, Schema}; use Flow\PostgreSql\Client\Client; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; final class PostgreSqlLimitOffsetExtractor implements Extractor { @@ -25,7 +25,7 @@ final class PostgreSqlLimitOffsetExtractor implements Extractor */ public function __construct( private readonly Client $client, - private readonly string|SqlQuery $query, + private readonly string|Sql $query, private readonly array $parameters = [], ) { } @@ -33,7 +33,7 @@ public function __construct( public function extract(FlowContext $context) : \Generator { $uri = 'postgresql://limit-offset'; - $sql = $this->query instanceof SqlQuery ? $this->query->toSql() : $this->query; + $sql = $this->query instanceof Sql ? $this->query->toSql() : $this->query; if (!sql_query_order_by(sql_parse($sql))->hasOrderBy()) { throw new InvalidArgumentException( 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 805762450e..7050c42770 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 @@ -4,12 +4,12 @@ namespace Flow\ETL\Adapter\PostgreSql\QueryBuilder; -use function Flow\PostgreSql\DSL\{col, cond_and, delete, eq, param}; +use function Flow\PostgreSql\DSL\{and_, col, delete, eq, param}; use Flow\ETL\Adapter\PostgreSql\{EntryTypesMap, LoaderOptions\DeleteOptions}; use Flow\ETL\Adapter\PostgreSql\Exception\RuntimeException; use Flow\ETL\{Row, Row\Entry}; use Flow\PostgreSql\Client\TypedValue; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; final readonly class DeleteQueryBuilder { @@ -20,7 +20,7 @@ public function __construct( } /** - * @return array{SqlQuery, list} + * @return array{Sql, list} */ public function build(Row $row, DeleteOptions $options) : array { @@ -48,7 +48,7 @@ public function build(Row $row, DeleteOptions $options) : array $params[] = $this->mapEntryToParameter($entry); } - $query = delete()->from($this->table)->where(cond_and(...$conditions)); + $query = delete()->from($this->table)->where(and_(...$conditions)); return [$query, $params]; } 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 3cfe6880b7..4fbeb908a0 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 @@ -9,7 +9,7 @@ use Flow\ETL\{Row\Entry, Rows}; use Flow\PostgreSql\Client\TypedValue; use Flow\PostgreSql\QueryBuilder\Insert\BulkInsert; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; final readonly class InsertQueryBuilder { @@ -20,7 +20,7 @@ public function __construct( } /** - * @return array{SqlQuery, list} + * @return array{Sql, list} */ public function build(Rows $rows, ?InsertOptions $options = null) : array { 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 c7a47d7c68..496a1dec29 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 @@ -4,12 +4,12 @@ namespace Flow\ETL\Adapter\PostgreSql\QueryBuilder; -use function Flow\PostgreSql\DSL\{col, cond_and, eq, param, update}; +use function Flow\PostgreSql\DSL\{and_, col, eq, param, update}; use Flow\ETL\Adapter\PostgreSql\{EntryTypesMap, LoaderOptions\UpdateOptions}; use Flow\ETL\Adapter\PostgreSql\Exception\RuntimeException; use Flow\ETL\{Row, Row\Entry}; use Flow\PostgreSql\Client\TypedValue; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; final readonly class UpdateQueryBuilder { @@ -20,7 +20,7 @@ public function __construct( } /** - * @return array{null|SqlQuery, list} + * @return array{null|Sql, list} */ public function build(Row $row, UpdateOptions $options) : array { @@ -66,7 +66,7 @@ public function build(Row $row, UpdateOptions $options) : array $query = update() ->update($this->table) ->setAll($assignments) - ->where(cond_and(...$conditions)); + ->where(and_(...$conditions)); return [$query, $params]; } diff --git a/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/ValueConverter/EnumConverter.php b/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/ValueConverter/EnumConverter.php index 711a448e3f..6f72e8ef8a 100644 --- a/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/ValueConverter/EnumConverter.php +++ b/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/ValueConverter/EnumConverter.php @@ -4,7 +4,7 @@ namespace Flow\ETL\Adapter\PostgreSql\ValueConverter; -use Flow\PostgreSql\Client\Types\{PostgreSqlType, ValueConverter}; +use Flow\PostgreSql\Client\Types\{ValueConverter, ValueType}; final readonly class EnumConverter implements ValueConverter { @@ -15,7 +15,7 @@ public function __construct( public function supportedTypes() : array { - return [PostgreSqlType::TEXT]; + return [ValueType::TEXT]; } public function toDatabase(mixed $value) : ?string diff --git a/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/ValueConverter/HTMLConverter.php b/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/ValueConverter/HTMLConverter.php index 48ce7996d2..3eb49050b5 100644 --- a/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/ValueConverter/HTMLConverter.php +++ b/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/ValueConverter/HTMLConverter.php @@ -6,7 +6,7 @@ use Dom\{HTMLDocument, HTMLElement}; use Flow\PostgreSql\Client\Types\Converter\StringConverter; -use Flow\PostgreSql\Client\Types\{PostgreSqlType, ValueConverter}; +use Flow\PostgreSql\Client\Types\{ValueConverter, ValueType}; final readonly class HTMLConverter implements ValueConverter { @@ -17,7 +17,7 @@ public function __construct( public function supportedTypes() : array { - return [PostgreSqlType::TEXT]; + return [ValueType::TEXT]; } public function toDatabase(mixed $value) : ?string diff --git a/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/ValueConverter/XMLConverter.php b/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/ValueConverter/XMLConverter.php index 13fb2e43a6..4b9d7fd9ec 100644 --- a/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/ValueConverter/XMLConverter.php +++ b/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/ValueConverter/XMLConverter.php @@ -5,7 +5,7 @@ namespace Flow\ETL\Adapter\PostgreSql\ValueConverter; use Flow\PostgreSql\Client\Types\Converter\StringConverter; -use Flow\PostgreSql\Client\Types\{PostgreSqlType, ValueConverter}; +use Flow\PostgreSql\Client\Types\{ValueConverter, ValueType}; final readonly class XMLConverter implements ValueConverter { @@ -16,7 +16,7 @@ public function __construct( public function supportedTypes() : array { - return [PostgreSqlType::XML]; + return [ValueType::XML]; } public function toDatabase(mixed $value) : ?string diff --git a/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/functions.php b/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/functions.php index 4fc87d86db..fe0de12370 100644 --- a/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/functions.php +++ b/src/adapter/etl-adapter-postgresql/src/Flow/ETL/Adapter/PostgreSql/functions.php @@ -8,7 +8,7 @@ use Flow\ETL\Adapter\PostgreSql\Pagination\{Key, KeySet, Order}; use Flow\ETL\{Attribute\DocumentationDSL, Attribute\Module, Attribute\Type as DSLType}; use Flow\PostgreSql\Client\Client; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; /** * Create a PostgreSQL cursor extractor using server-side cursors for memory-efficient extraction. @@ -19,13 +19,13 @@ * Note: Requires a transaction context (auto-started if not in one). * * @param Client $client PostgreSQL client - * @param SqlQuery|string $query SQL query to execute (wrapped in DECLARE CURSOR) + * @param Sql|string $query SQL query to execute (wrapped in DECLARE CURSOR) * @param array $parameters Positional parameters for the query */ #[DocumentationDSL(module: Module::POSTGRESQL, type: DSLType::EXTRACTOR)] function from_pgsql_cursor( Client $client, - string|SqlQuery $query, + string|Sql $query, array $parameters = [], ) : PostgreSqlCursorExtractor { return new PostgreSqlCursorExtractor($client, $query, $parameters); @@ -38,13 +38,13 @@ function from_pgsql_cursor( * (from_pgsql_key_set) which is more efficient. * * @param Client $client PostgreSQL client - * @param SqlQuery|string $query SQL query to execute (must have ORDER BY clause) + * @param Sql|string $query SQL query to execute (must have ORDER BY clause) * @param array $parameters Positional parameters for the query */ #[DocumentationDSL(module: Module::POSTGRESQL, type: DSLType::EXTRACTOR)] function from_pgsql_limit_offset( Client $client, - string|SqlQuery $query, + string|Sql $query, array $parameters = [], ) : PostgreSqlLimitOffsetExtractor { return new PostgreSqlLimitOffsetExtractor($client, $query, $parameters); @@ -57,14 +57,14 @@ function from_pgsql_limit_offset( * instead of skipping rows. * * @param Client $client PostgreSQL client - * @param SqlQuery|string $query SQL query to execute (must have ORDER BY matching keyset columns) + * @param Sql|string $query SQL query to execute (must have ORDER BY matching keyset columns) * @param KeySet $keySet Columns to use for keyset pagination * @param array $parameters Positional parameters for the query */ #[DocumentationDSL(module: Module::POSTGRESQL, type: DSLType::EXTRACTOR)] function from_pgsql_key_set( Client $client, - string|SqlQuery $query, + string|Sql $query, KeySet $keySet, array $parameters = [], ) : PostgreSqlKeySetExtractor { 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 314aeb795f..b6cd5cd66b 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 @@ -6,7 +6,7 @@ use function Flow\ETL\Adapter\PostgreSql\from_pgsql_cursor; use function Flow\ETL\DSL\df; -use function Flow\PostgreSql\DSL\{asc, col, column, create, data_type_integer, data_type_text, delete, drop, insert, literal, select, star, table}; +use function Flow\PostgreSql\DSL\{asc, col, column, column_type_integer, column_type_text, create, delete, drop, insert, literal, select, star, table}; use Flow\ETL\Adapter\PostgreSql\Tests\IntegrationTestCase; final class PostgreSqlCursorExtractorIntegrationTest extends IntegrationTestCase @@ -23,8 +23,8 @@ protected function setUp() : void $this->client->execute( create()->table($this->tableName) - ->column(column('id', data_type_integer())->primaryKey()) - ->column(column('name', data_type_text())) + ->column(column('id', column_type_integer())->primaryKey()) + ->column(column('name', column_type_text())) ); $this->insertTestData(25); 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 f4e5da33a2..6527f85d20 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 @@ -6,7 +6,7 @@ use function Flow\ETL\Adapter\PostgreSql\{from_pgsql_key_set, pgsql_pagination_key_asc, pgsql_pagination_key_desc, pgsql_pagination_key_set}; use function Flow\ETL\DSL\df; -use function Flow\PostgreSql\DSL\{col, column, create, data_type_integer, data_type_text, delete, drop, insert, literal, select, star, table}; +use function Flow\PostgreSql\DSL\{col, column, column_type_integer, column_type_text, create, delete, drop, insert, literal, select, star, table}; use Flow\ETL\Adapter\PostgreSql\Tests\IntegrationTestCase; final class PostgreSqlKeySetExtractorIntegrationTest extends IntegrationTestCase @@ -23,8 +23,8 @@ protected function setUp() : void $this->client->execute( create()->table($this->tableName) - ->column(column('id', data_type_integer())->primaryKey()) - ->column(column('name', data_type_text())) + ->column(column('id', column_type_integer())->primaryKey()) + ->column(column('name', column_type_text())) ); $this->insertTestData(25); 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 937cbe0be6..d0cccf85f9 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 @@ -6,7 +6,7 @@ use function Flow\ETL\Adapter\PostgreSql\from_pgsql_limit_offset; use function Flow\ETL\DSL\df; -use function Flow\PostgreSql\DSL\{asc, col, column, create, data_type_integer, data_type_text, delete, drop, insert, literal, select, star, table}; +use function Flow\PostgreSql\DSL\{asc, col, column, column_type_integer, column_type_text, create, delete, drop, insert, literal, select, star, table}; use Flow\ETL\Adapter\PostgreSql\Tests\IntegrationTestCase; final class PostgreSqlLimitOffsetExtractorIntegrationTest extends IntegrationTestCase @@ -23,8 +23,8 @@ protected function setUp() : void $this->client->execute( create()->table($this->tableName) - ->column(column('id', data_type_integer())->primaryKey()) - ->column(column('name', data_type_text())) + ->column(column('id', column_type_integer())->primaryKey()) + ->column(column('name', column_type_text())) ); $this->insertTestData(25); 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 9a02361b0a..c44649024c 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 @@ -6,7 +6,7 @@ use function Flow\ETL\Adapter\PostgreSql\{from_pgsql_limit_offset, to_pgsql_table}; use function Flow\ETL\DSL\{bool_entry, date_entry, datetime_entry, df, enum_entry, float_entry, from_rows, int_entry, json_entry, list_entry, map_entry, row, rows, str_entry, structure_entry, time_entry, uuid_entry, xml_element_entry, xml_entry}; -use function Flow\PostgreSql\DSL\{asc, col, column, create, data_type_bigint, data_type_boolean, data_type_custom, data_type_date, data_type_double_precision, data_type_jsonb, data_type_serial, data_type_text, data_type_time, data_type_timestamptz, data_type_uuid, drop, select, star, table}; +use function Flow\PostgreSql\DSL\{asc, col, column, column_type_bigint, column_type_boolean, column_type_custom, column_type_date, column_type_double_precision, column_type_jsonb, column_type_serial, column_type_text, column_type_time, column_type_timestamptz, column_type_uuid, create, drop, select, star, table}; use function Flow\Types\DSL\{type_integer, type_list, type_map, type_string, type_structure}; use Flow\ETL\Adapter\PostgreSql\Tests\Fixtures\Enum\BackedStringEnum; use Flow\ETL\Adapter\PostgreSql\Tests\IntegrationTestCase; @@ -25,24 +25,24 @@ protected function setUp() : void $this->client->execute( create()->table($this->tableName) - ->column(column('id', data_type_serial())->primaryKey()) - ->column(column('col_string', data_type_text())) - ->column(column('col_integer', data_type_bigint())) - ->column(column('col_float', data_type_double_precision())) - ->column(column('col_boolean', data_type_boolean())) - ->column(column('col_date', data_type_date())) - ->column(column('col_datetime', data_type_timestamptz())) - ->column(column('col_time', data_type_time())) - ->column(column('col_uuid', data_type_uuid())) - ->column(column('col_json', data_type_jsonb())) - ->column(column('col_xml', data_type_custom('xml'))) - ->column(column('col_xml_element', data_type_custom('xml'))) - ->column(column('col_html', data_type_text())) - ->column(column('col_html_element', data_type_text())) - ->column(column('col_enum', data_type_text())) - ->column(column('col_list', data_type_jsonb())) - ->column(column('col_map', data_type_jsonb())) - ->column(column('col_structure', data_type_jsonb())) + ->column(column('id', column_type_serial())->primaryKey()) + ->column(column('col_string', column_type_text())) + ->column(column('col_integer', column_type_bigint())) + ->column(column('col_float', column_type_double_precision())) + ->column(column('col_boolean', column_type_boolean())) + ->column(column('col_date', column_type_date())) + ->column(column('col_datetime', column_type_timestamptz())) + ->column(column('col_time', column_type_time())) + ->column(column('col_uuid', column_type_uuid())) + ->column(column('col_json', column_type_jsonb())) + ->column(column('col_xml', column_type_custom('xml'))) + ->column(column('col_xml_element', column_type_custom('xml'))) + ->column(column('col_html', column_type_text())) + ->column(column('col_html_element', column_type_text())) + ->column(column('col_enum', column_type_text())) + ->column(column('col_list', column_type_jsonb())) + ->column(column('col_map', column_type_jsonb())) + ->column(column('col_structure', column_type_jsonb())) ); } diff --git a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Integration/PostgreSqlLoaderIntegrationTest.php b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Integration/PostgreSqlLoaderIntegrationTest.php index 32db60d7f8..b05593a106 100644 --- a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Integration/PostgreSqlLoaderIntegrationTest.php +++ b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Integration/PostgreSqlLoaderIntegrationTest.php @@ -6,7 +6,7 @@ use function Flow\ETL\Adapter\PostgreSql\{from_pgsql_limit_offset, pgsql_delete_options, pgsql_insert_options, pgsql_update_options, to_pgsql_table}; use function Flow\ETL\DSL\{df, from_array}; -use function Flow\PostgreSql\DSL\{asc, col, column, create, data_type_integer, data_type_text, drop, select, star, table}; +use function Flow\PostgreSql\DSL\{asc, col, column, column_type_integer, column_type_text, create, drop, select, star, table}; use Flow\ETL\Adapter\PostgreSql\Operation; use Flow\ETL\Adapter\PostgreSql\Tests\IntegrationTestCase; @@ -24,9 +24,9 @@ protected function setUp() : void $this->client->execute( create()->table($this->tableName) - ->column(column('id', data_type_integer())->primaryKey()) - ->column(column('name', data_type_text())) - ->column(column('email', data_type_text())->unique()) + ->column(column('id', column_type_integer())->primaryKey()) + ->column(column('name', column_type_text())) + ->column(column('email', column_type_text())->unique()) ); } diff --git a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/IntegrationTestCase.php b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/IntegrationTestCase.php index 0691a4722e..c3f620f6d5 100644 --- a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/IntegrationTestCase.php +++ b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/IntegrationTestCase.php @@ -4,7 +4,7 @@ namespace Flow\ETL\Adapter\PostgreSql\Tests; -use function Flow\PostgreSql\DSL\{pgsql_client, pgsql_connection_dsn, pgsql_mapper}; +use function Flow\PostgreSql\DSL\{pgsql_client, pgsql_connection_dsn}; use Flow\ETL\Tests\FlowTestCase; use Flow\PostgreSql\Client\Client; @@ -28,10 +28,7 @@ protected function setUp() : void static::markTestSkipped('PGSQL_DATABASE_URL environment variable is not set'); } - $this->client = pgsql_client( - pgsql_connection_dsn($dsn), - mapper: pgsql_mapper(), - ); + $this->client = pgsql_client(pgsql_connection_dsn($dsn)); } protected function tearDown() : void diff --git a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/EntryTypesMapTest.php b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/EntryTypesMapTest.php index 5981c84043..ebb81ebf89 100644 --- a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/EntryTypesMapTest.php +++ b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/EntryTypesMapTest.php @@ -9,7 +9,7 @@ use Flow\ETL\Adapter\PostgreSql\EntryTypesMap; use Flow\ETL\Row\Entry\IntegerEntry; use Flow\PostgreSql\Client\TypedValue; -use Flow\PostgreSql\Client\Types\PostgreSqlType; +use Flow\PostgreSql\Client\Types\ValueType; use PHPUnit\Framework\TestCase; final class EntryTypesMapTest extends TestCase @@ -17,13 +17,13 @@ final class EntryTypesMapTest extends TestCase public function test_allows_override_for_integer_entry_to_int2() : void { $map = new EntryTypesMap([ - IntegerEntry::class => PostgreSqlType::INT2, + IntegerEntry::class => ValueType::INT2, ]); $result = $map->mapEntry(int_entry('small_count', 42)); self::assertInstanceOf(TypedValue::class, $result); - self::assertSame(PostgreSqlType::INT2, $result->targetType); + self::assertSame(ValueType::INT2, $result->targetType); self::assertSame(42, $result->value); } @@ -33,7 +33,7 @@ public function test_maps_boolean_entry_to_bool_type() : void $result = $map->mapEntry(bool_entry('active', true)); self::assertInstanceOf(TypedValue::class, $result); - self::assertSame(PostgreSqlType::BOOL, $result->targetType); + self::assertSame(ValueType::BOOL, $result->targetType); self::assertTrue($result->value); } @@ -44,7 +44,7 @@ public function test_maps_datetime_entry_to_timestamptz_type() : void $result = $map->mapEntry(datetime_entry('created_at', $date)); self::assertInstanceOf(TypedValue::class, $result); - self::assertSame(PostgreSqlType::TIMESTAMPTZ, $result->targetType); + self::assertSame(ValueType::TIMESTAMPTZ, $result->targetType); self::assertEquals($date, $result->value); } @@ -54,7 +54,7 @@ public function test_maps_float_entry_to_float8_type() : void $result = $map->mapEntry(float_entry('price', 99.99)); self::assertInstanceOf(TypedValue::class, $result); - self::assertSame(PostgreSqlType::FLOAT8, $result->targetType); + self::assertSame(ValueType::FLOAT8, $result->targetType); self::assertSame(99.99, $result->value); } @@ -64,7 +64,7 @@ public function test_maps_integer_entry_to_int8_type() : void $result = $map->mapEntry(int_entry('count', 42)); self::assertInstanceOf(TypedValue::class, $result); - self::assertSame(PostgreSqlType::INT8, $result->targetType); + self::assertSame(ValueType::INT8, $result->targetType); self::assertSame(42, $result->value); } @@ -74,7 +74,7 @@ public function test_maps_json_entry_to_jsonb_type() : void $result = $map->mapEntry(json_entry('data', ['key' => 'value'])); self::assertInstanceOf(TypedValue::class, $result); - self::assertSame(PostgreSqlType::JSONB, $result->targetType); + self::assertSame(ValueType::JSONB, $result->targetType); } public function test_maps_list_entry_to_jsonb_type() : void @@ -83,7 +83,7 @@ public function test_maps_list_entry_to_jsonb_type() : void $result = $map->mapEntry(list_entry('tags', [1, 2, 3], type_list(type_integer()))); self::assertInstanceOf(TypedValue::class, $result); - self::assertSame(PostgreSqlType::JSONB, $result->targetType); + self::assertSame(ValueType::JSONB, $result->targetType); self::assertSame([1, 2, 3], $result->value); } @@ -93,7 +93,7 @@ public function test_maps_map_entry_to_jsonb_type() : void $result = $map->mapEntry(map_entry('metadata', ['key' => 'value'], type_map(type_string(), type_string()))); self::assertInstanceOf(TypedValue::class, $result); - self::assertSame(PostgreSqlType::JSONB, $result->targetType); + self::assertSame(ValueType::JSONB, $result->targetType); self::assertSame(['key' => 'value'], $result->value); } @@ -111,7 +111,7 @@ public function test_maps_string_entry_to_text_type() : void $result = $map->mapEntry(str_entry('name', 'Alice')); self::assertInstanceOf(TypedValue::class, $result); - self::assertSame(PostgreSqlType::TEXT, $result->targetType); + self::assertSame(ValueType::TEXT, $result->targetType); self::assertSame('Alice', $result->value); } @@ -124,7 +124,7 @@ public function test_maps_structure_entry_to_jsonb_type() : void ]))); self::assertInstanceOf(TypedValue::class, $result); - self::assertSame(PostgreSqlType::JSONB, $result->targetType); + self::assertSame(ValueType::JSONB, $result->targetType); } public function test_maps_uuid_entry_to_uuid_type() : void @@ -133,6 +133,6 @@ public function test_maps_uuid_entry_to_uuid_type() : void $result = $map->mapEntry(uuid_entry('id', '550e8400-e29b-41d4-a716-446655440000')); self::assertInstanceOf(TypedValue::class, $result); - self::assertSame(PostgreSqlType::UUID, $result->targetType); + self::assertSame(ValueType::UUID, $result->targetType); } } diff --git a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/QueryBuilder/DeleteQueryBuilderTest.php b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/QueryBuilder/DeleteQueryBuilderTest.php index 5792aacd0d..a090199f9c 100644 --- a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/QueryBuilder/DeleteQueryBuilderTest.php +++ b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/QueryBuilder/DeleteQueryBuilderTest.php @@ -8,7 +8,7 @@ use Flow\ETL\Adapter\PostgreSql\{EntryTypesMap, LoaderOptions\DeleteOptions, QueryBuilder\DeleteQueryBuilder}; use Flow\ETL\Adapter\PostgreSql\Exception\RuntimeException; use Flow\PostgreSql\Client\TypedValue; -use Flow\PostgreSql\Client\Types\PostgreSqlType; +use Flow\PostgreSql\Client\Types\ValueType; use PHPUnit\Framework\TestCase; final class DeleteQueryBuilderTest extends TestCase @@ -25,7 +25,7 @@ public function test_build_returns_typed_values() : void self::assertCount(1, $params); self::assertInstanceOf(TypedValue::class, $params[0]); self::assertSame(1, $params[0]->value); - self::assertSame(PostgreSqlType::INT8, $params[0]->targetType); + self::assertSame(ValueType::INT8, $params[0]->targetType); } public function test_build_simple_delete() : void 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 84b2fedc39..e95b079a8b 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,7 +7,7 @@ use function Flow\ETL\DSL\{int_entry, row, rows, str_entry}; use Flow\ETL\Adapter\PostgreSql\{EntryTypesMap, LoaderOptions\InsertOptions, QueryBuilder\InsertQueryBuilder}; use Flow\PostgreSql\Client\TypedValue; -use Flow\PostgreSql\Client\Types\PostgreSqlType; +use Flow\PostgreSql\Client\Types\ValueType; use PHPUnit\Framework\TestCase; final class InsertQueryBuilderTest extends TestCase @@ -24,9 +24,9 @@ public function test_build_returns_typed_values() : void self::assertInstanceOf(TypedValue::class, $params[0]); self::assertInstanceOf(TypedValue::class, $params[1]); self::assertSame(1, $params[0]->value); - self::assertSame(PostgreSqlType::INT8, $params[0]->targetType); + self::assertSame(ValueType::INT8, $params[0]->targetType); self::assertSame('Alice', $params[1]->value); - self::assertSame(PostgreSqlType::TEXT, $params[1]->targetType); + self::assertSame(ValueType::TEXT, $params[1]->targetType); } public function test_build_simple_insert() : void diff --git a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/QueryBuilder/UpdateQueryBuilderTest.php b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/QueryBuilder/UpdateQueryBuilderTest.php index c119490a9f..2942fc1e13 100644 --- a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/QueryBuilder/UpdateQueryBuilderTest.php +++ b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/QueryBuilder/UpdateQueryBuilderTest.php @@ -8,7 +8,7 @@ use Flow\ETL\Adapter\PostgreSql\{EntryTypesMap, LoaderOptions\UpdateOptions, QueryBuilder\UpdateQueryBuilder}; use Flow\ETL\Adapter\PostgreSql\Exception\RuntimeException; use Flow\PostgreSql\Client\TypedValue; -use Flow\PostgreSql\Client\Types\PostgreSqlType; +use Flow\PostgreSql\Client\Types\ValueType; use PHPUnit\Framework\TestCase; final class UpdateQueryBuilderTest extends TestCase @@ -38,10 +38,10 @@ public function test_build_returns_typed_values() : void self::assertCount(2, $params); self::assertInstanceOf(TypedValue::class, $params[0]); self::assertSame('Alice', $params[0]->value); - self::assertSame(PostgreSqlType::TEXT, $params[0]->targetType); + self::assertSame(ValueType::TEXT, $params[0]->targetType); self::assertInstanceOf(TypedValue::class, $params[1]); self::assertSame(1, $params[1]->value); - self::assertSame(PostgreSqlType::INT8, $params[1]->targetType); + self::assertSame(ValueType::INT8, $params[1]->targetType); } public function test_build_simple_update() : void diff --git a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/ValueConverter/EnumConverterTest.php b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/ValueConverter/EnumConverterTest.php index 27653d493f..016662f479 100644 --- a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/ValueConverter/EnumConverterTest.php +++ b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/ValueConverter/EnumConverterTest.php @@ -6,7 +6,7 @@ use Flow\ETL\Adapter\PostgreSql\Tests\Fixtures\Enum\{BackedIntEnum, BackedStringEnum, UnitEnum}; use Flow\ETL\Adapter\PostgreSql\ValueConverter\EnumConverter; -use Flow\PostgreSql\Client\Types\PostgreSqlType; +use Flow\PostgreSql\Client\Types\ValueType; use PHPUnit\Framework\TestCase; final class EnumConverterTest extends TestCase @@ -45,7 +45,7 @@ public function test_supported_types_returns_text() : void { $converter = new EnumConverter(); - self::assertSame([PostgreSqlType::TEXT], $converter->supportedTypes()); + self::assertSame([ValueType::TEXT], $converter->supportedTypes()); } public function test_unit_enum_returns_name() : void diff --git a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/ValueConverter/HTMLConverterTest.php b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/ValueConverter/HTMLConverterTest.php index 21bd48aee9..f6d0c65bcd 100644 --- a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/ValueConverter/HTMLConverterTest.php +++ b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/ValueConverter/HTMLConverterTest.php @@ -6,7 +6,7 @@ use Dom\{HTMLDocument, HTMLElement}; use Flow\ETL\Adapter\PostgreSql\ValueConverter\HTMLConverter; -use Flow\PostgreSql\Client\Types\PostgreSqlType; +use Flow\PostgreSql\Client\Types\ValueType; use PHPUnit\Framework\TestCase; final class HTMLConverterTest extends TestCase @@ -63,6 +63,6 @@ public function test_supported_types_returns_text() : void { $converter = new HTMLConverter(); - self::assertSame([PostgreSqlType::TEXT], $converter->supportedTypes()); + self::assertSame([ValueType::TEXT], $converter->supportedTypes()); } } diff --git a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/ValueConverter/XMLConverterTest.php b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/ValueConverter/XMLConverterTest.php index 91e7e9560a..bca8ab3548 100644 --- a/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/ValueConverter/XMLConverterTest.php +++ b/src/adapter/etl-adapter-postgresql/tests/Flow/ETL/Adapter/PostgreSql/Tests/Unit/ValueConverter/XMLConverterTest.php @@ -5,7 +5,7 @@ namespace Flow\ETL\Adapter\PostgreSql\Tests\Unit\ValueConverter; use Flow\ETL\Adapter\PostgreSql\ValueConverter\XMLConverter; -use Flow\PostgreSql\Client\Types\PostgreSqlType; +use Flow\PostgreSql\Client\Types\ValueType; use PHPUnit\Framework\TestCase; final class XMLConverterTest extends TestCase @@ -57,6 +57,6 @@ public function test_supported_types_returns_xml() : void { $converter = new XMLConverter(); - self::assertSame([PostgreSqlType::XML], $converter->supportedTypes()); + self::assertSame([ValueType::XML], $converter->supportedTypes()); } } diff --git a/src/bridge/symfony/http-foundation-telemetry/composer.json b/src/bridge/symfony/http-foundation-telemetry/composer.json index 39cdfd555d..2fe84e18b8 100644 --- a/src/bridge/symfony/http-foundation-telemetry/composer.json +++ b/src/bridge/symfony/http-foundation-telemetry/composer.json @@ -14,7 +14,7 @@ "require": { "php": "~8.3.0 || ~8.4.0 || ~8.5.0", "flow-php/telemetry": "self.version", - "symfony/http-foundation": "^6.4 || ^7.3 || ^8.0" + "symfony/http-foundation": "^6.4 || ^7.4 || ^8.0" }, "autoload": { "psr-4": { diff --git a/src/bridge/symfony/http-foundation/composer.json b/src/bridge/symfony/http-foundation/composer.json index e77fe053a0..6518f3c6cf 100644 --- a/src/bridge/symfony/http-foundation/composer.json +++ b/src/bridge/symfony/http-foundation/composer.json @@ -12,7 +12,7 @@ ], "require": { "php": "~8.3.0 || ~8.4.0 || ~8.5.0", - "symfony/http-foundation": "^6.4 || ^7.3 || ^8.0", + "symfony/http-foundation": "^6.4 || ^7.4 || ^8.0", "flow-php/etl": "self.version" }, "require-dev": { diff --git a/src/bridge/symfony/postgresql-bundle/.github/workflows/readonly.yaml b/src/bridge/symfony/postgresql-bundle/.github/workflows/readonly.yaml new file mode 100644 index 0000000000..24255888e1 --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/.github/workflows/readonly.yaml @@ -0,0 +1,17 @@ +name: Readonly + +on: + pull_request_target: + types: [opened] + +jobs: + run: + runs-on: ubuntu-latest + steps: + - uses: superbrothers/close-pull-request@v3 + with: + comment: | + Hi, thank you for your contribution. + Unfortunately, this repository is read-only. It's a split from our main monorepo repository. + In order to proceed with this PR please open it against https://github.com/flow-php/flow repository. + Thank you. diff --git a/src/bridge/symfony/postgresql-bundle/CONTRIBUTING.md b/src/bridge/symfony/postgresql-bundle/CONTRIBUTING.md new file mode 100644 index 0000000000..f035b534af --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/CONTRIBUTING.md @@ -0,0 +1,6 @@ +## Contributing + +This repo is **READ ONLY**, in order to contribute to Flow PHP project, please +open PR against [flow](https://github.com/flow-php/flow) monorepo. + +Changes merged to monorepo are automatically propagated into sub repositories. diff --git a/src/bridge/symfony/postgresql-bundle/LICENSE b/src/bridge/symfony/postgresql-bundle/LICENSE new file mode 100644 index 0000000000..bc3cc4d085 --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2020-present Flow PHP + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/src/bridge/symfony/postgresql-bundle/README.md b/src/bridge/symfony/postgresql-bundle/README.md new file mode 100644 index 0000000000..348df61869 --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/README.md @@ -0,0 +1,11 @@ +# Symfony PostgreSQL Bundle + +Symfony bundle integrating Flow PHP PostgreSQL library with connection management and database migrations. + +> [!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). + +- 📜 [Documentation](https://flow-php.com/documentation/components/bridges/symfony-postgresql-bundle/) +- ➡️ [Installation](https://flow-php.com/documentation/installation/packages/symfony-postgresql-bundle/) +- 🛠️ [Contributing](https://flow-php.com/documentation/contributing/) +- 🚧 [Upgrading](https://flow-php.com/documentation/upgrading/) diff --git a/src/bridge/symfony/postgresql-bundle/composer.json b/src/bridge/symfony/postgresql-bundle/composer.json new file mode 100644 index 0000000000..c71168a856 --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/composer.json @@ -0,0 +1,44 @@ +{ + "name": "flow-php/symfony-postgresql-bundle", + "type": "symfony-bundle", + "description": "Flow PHP - Symfony PostgreSQL Bundle", + "keywords": [ + "flow-php", + "symfony", + "postgresql", + "bundle" + ], + "homepage": "https://github.com/flow-php/flow", + "license": "MIT", + "require": { + "php": "~8.3.0 || ~8.4.0 || ~8.5.0", + "flow-php/filesystem": "self.version", + "flow-php/postgresql": "self.version", + "symfony/config": "^6.4 || ^7.4 || ^8.0", + "symfony/console": "^6.4 || ^7.4 || ^8.0", + "symfony/dependency-injection": "^6.4 || ^7.4 || ^8.0", + "symfony/http-kernel": "^6.4 || ^7.4 || ^8.0", + "twig/twig": "^3.0" + }, + "require-dev": { + "symfony/framework-bundle": "^6.4 || ^7.4 || ^8.0" + }, + "config": { + "optimize-autoloader": true, + "sort-packages": true + }, + "autoload": { + "psr-4": { + "Flow\\": [ + "src/Flow" + ] + } + }, + "autoload-dev": { + "psr-4": { + "Flow\\": "tests/Flow" + } + }, + "minimum-stability": "dev", + "prefer-stable": true +} diff --git a/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Attribute/AsCatalogProvider.php b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Attribute/AsCatalogProvider.php new file mode 100644 index 0000000000..7c903e21a8 --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Attribute/AsCatalogProvider.php @@ -0,0 +1,13 @@ +data); + } +} diff --git a/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Command/CreateDatabaseCommand.php b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Command/CreateDatabaseCommand.php new file mode 100644 index 0000000000..67abb9a49c --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Command/CreateDatabaseCommand.php @@ -0,0 +1,69 @@ +addOption('connection', 'c', InputOption::VALUE_OPTIONAL, 'The connection to use', null) + ->addOption('if-not-exists', null, InputOption::VALUE_NONE, 'Don\'t error if database already exists'); + } + + protected function execute(InputInterface $input, OutputInterface $output) : int + { + $connection = type_string()->assert($input->getOption('connection') ?? $this->defaultConnection); + $params = type_instance_of(ConnectionParameters::class)->assert($this->container->get("flow.postgresql.{$connection}.connection_parameters")); + + $maintenanceClient = PgSqlClient::connect($params->withDatabase('postgres')); + + $exists = $maintenanceClient->fetchScalarInt( + select(agg_count())->from('pg_database')->where(eq(col('datname'), param(1))), + [$params->database()] + ) > 0; + + if ($exists) { + $maintenanceClient->close(); + + if ($input->getOption('if-not-exists')) { + $output->writeln(\sprintf('Database "%s" already exists.', $params->database())); + + return Command::SUCCESS; + } + + $output->writeln(\sprintf('Database "%s" already exists.', $params->database())); + + return Command::FAILURE; + } + + $maintenanceClient->execute(create()->database($params->database())); + $maintenanceClient->close(); + + $output->writeln(\sprintf('Database "%s" created successfully.', $params->database())); + + return Command::SUCCESS; + } +} diff --git a/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Command/CurrentCommand.php b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Command/CurrentCommand.php new file mode 100644 index 0000000000..e961515043 --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Command/CurrentCommand.php @@ -0,0 +1,61 @@ +addOption('connection', 'c', InputOption::VALUE_OPTIONAL, 'The connection to use', null); + } + + protected function execute(InputInterface $input, OutputInterface $output) : int + { + $io = new SymfonyStyle($input, $output); + $connection = type_string()->assert($input->getOption('connection') ?? $this->defaultConnection); + $store = type_instance_of(MigrationStore::class)->assert($this->container->get("flow.postgresql.{$connection}.migrations.store")); + + $store->initialize(); + $executed = $store->executedMigrations(); + $latest = $executed->latest(); + + $io->title('Current Migration'); + + if ($latest === null) { + $io->note('No migrations have been executed yet.'); + + return Command::SUCCESS; + } + + $io->definitionList( + ['Version' => "{$latest->version}"], + ['Executed at' => '' . $latest->executedAt->format('Y-m-d H:i:s') . ''], + ['Execution time' => $latest->executionTimeMs !== null ? $latest->executionTimeMs . 'ms' : '-'], + ['Total executed' => (string) \count($executed)], + ); + + return Command::SUCCESS; + } +} diff --git a/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Command/DiffCommand.php b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Command/DiffCommand.php new file mode 100644 index 0000000000..57eeef9d78 --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Command/DiffCommand.php @@ -0,0 +1,75 @@ +addOption('connection', 'c', InputOption::VALUE_OPTIONAL, 'The connection to use', null) + ->addArgument('name', InputArgument::OPTIONAL, 'The name of the migration (e.g. \'add_categories\')') + ->addOption('allow-empty-diff', null, InputOption::VALUE_NONE, 'Do not throw when no changes are detected') + ->addOption('from-empty-schema', null, InputOption::VALUE_NONE, 'Generate as if the database were empty'); + } + + protected function execute(InputInterface $input, OutputInterface $output) : int + { + $io = new SymfonyStyle($input, $output); + $connection = type_string()->assert($input->getOption('connection') ?? $this->defaultConnection); + $diffGenerator = type_instance_of(DiffMigrationGenerator::class)->assert($this->container->get("flow.postgresql.{$connection}.migrations.diff_generator")); + $configuration = type_instance_of(MigrationsConfiguration::class)->assert($this->container->get("flow.postgresql.{$connection}.migrations.configuration")); + /** @var ?string $name */ + $name = $input->getArgument('name'); + $allowEmpty = (bool) $input->getOption('allow-empty-diff'); + $fromEmpty = (bool) $input->getOption('from-empty-schema'); + + try { + $version = $diffGenerator->generate($name, $allowEmpty, $fromEmpty); + } catch (MigrationException $e) { + $io->warning($e->getMessage()); + + return Command::FAILURE; + } + + $directory = $configuration->migrationsDirectory . '/' . $version . ($name !== null ? '_' . $name : ''); + $realDirectory = \realpath($directory) ?: $directory; + $migrationPath = $realDirectory . '/' . $configuration->migrationFileName; + $rollbackPath = $realDirectory . '/' . $configuration->rollbackFileName; + + $io->success(\sprintf('Generated migration: %s', $version)); + + $rows = [['Migration', $migrationPath]]; + + if (\file_exists($rollbackPath)) { + $rows[] = ['Rollback', $rollbackPath]; + } + + $io->table(['File', 'Path'], $rows); + + return Command::SUCCESS; + } +} diff --git a/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Command/DropDatabaseCommand.php b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Command/DropDatabaseCommand.php new file mode 100644 index 0000000000..5522fe0394 --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Command/DropDatabaseCommand.php @@ -0,0 +1,83 @@ +addOption('connection', 'c', InputOption::VALUE_OPTIONAL, 'The connection to use', null) + ->addOption('if-exists', null, InputOption::VALUE_NONE, 'Don\'t error if database doesn\'t exist') + ->addOption('force', null, InputOption::VALUE_NONE, 'Required to actually execute the drop'); + } + + protected function execute(InputInterface $input, OutputInterface $output) : int + { + $connection = type_string()->assert($input->getOption('connection') ?? $this->defaultConnection); + + if (!$input->getOption('force')) { + $output->writeln('This operation cannot be undone. Use --force to proceed.'); + + return Command::FAILURE; + } + + $params = type_instance_of(ConnectionParameters::class)->assert($this->container->get("flow.postgresql.{$connection}.connection_parameters")); + + $maintenanceClient = PgSqlClient::connect($params->withDatabase('postgres')); + + $exists = $maintenanceClient->fetchScalarInt( + select(agg_count())->from('pg_database')->where(eq(col('datname'), param(1))), + [$params->database()] + ) > 0; + + if (!$exists) { + $maintenanceClient->close(); + + if ($input->getOption('if-exists')) { + $output->writeln(\sprintf('Database "%s" does not exist.', $params->database())); + + return Command::SUCCESS; + } + + $output->writeln(\sprintf('Database "%s" does not exist.', $params->database())); + + return Command::FAILURE; + } + + $maintenanceClient->execute( + select(func('pg_terminate_backend', [col('pid')])) + ->from('pg_stat_activity') + ->where(and_(eq(col('datname'), param(1)), ne(col('pid'), func('pg_backend_pid')))), + [$params->database()] + ); + $maintenanceClient->execute(drop()->database($params->database())); + $maintenanceClient->close(); + + $output->writeln(\sprintf('Database "%s" dropped successfully.', $params->database())); + + return Command::SUCCESS; + } +} diff --git a/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Command/ExecuteCommand.php b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Command/ExecuteCommand.php new file mode 100644 index 0000000000..84da038434 --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Command/ExecuteCommand.php @@ -0,0 +1,82 @@ +addArgument('version', InputArgument::REQUIRED, 'The migration version to execute') + ->addOption('connection', 'c', InputOption::VALUE_OPTIONAL, 'The connection to use', null) + ->addOption('dry-run', null, InputOption::VALUE_NONE, 'Execute migration as a dry run') + ->addOption('up', null, InputOption::VALUE_NONE, 'Execute the migration up (default)') + ->addOption('down', null, InputOption::VALUE_NONE, 'Execute the migration down'); + } + + protected function execute(InputInterface $input, OutputInterface $output) : int + { + $io = new SymfonyStyle($input, $output); + $connection = type_string()->assert($input->getOption('connection') ?? $this->defaultConnection); + $migrator = type_instance_of(Migrator::class)->assert($this->container->get("flow.postgresql.{$connection}.migrations.migrator")); + $versionString = type_string()->assert($input->getArgument('version')); + $version = Version::fromString($versionString); + $dryRun = (bool) $input->getOption('dry-run'); + $direction = $input->getOption('down') ? Direction::DOWN : Direction::UP; + $directionLabel = $direction === Direction::UP ? 'UP' : 'DOWN'; + + $io->title('Execute Migration' . ($dryRun ? ' (dry run)' : '')); + + $io->definitionList( + ['Version' => "{$version}"], + ['Direction' => $direction === Direction::UP ? 'UP' : 'DOWN'], + ); + + if ($input->isInteractive() && !$io->confirm(\sprintf('Execute migration %s %s?', $direction === Direction::UP ? 'UP' : 'DOWN', $version), false)) { + $io->warning('Execution cancelled.'); + + return Command::SUCCESS; + } + + $result = $migrator->executeVersion($version, $direction, $dryRun); + + if ($result->error !== null) { + $io->error(\sprintf('%s %s failed: %s', $direction === Direction::UP ? 'UP' : 'DOWN', $version, $result->error->getMessage())); + + return Command::FAILURE; + } + + $io->table(['Direction', 'Version', 'Result', 'Time'], [ + [$directionLabel, (string) $version, 'OK', $result->executionTimeMs . 'ms'], + ]); + + if ($dryRun) { + $io->note('Dry run completed. No changes were applied.'); + } else { + $io->success(\sprintf('Migration %s executed successfully in %dms.', $version, $result->executionTimeMs)); + } + + return Command::SUCCESS; + } +} diff --git a/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Command/GenerateCommand.php b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Command/GenerateCommand.php new file mode 100644 index 0000000000..6380e70f5f --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Command/GenerateCommand.php @@ -0,0 +1,59 @@ +addOption('connection', 'c', InputOption::VALUE_OPTIONAL, 'The connection to use', null) + ->addArgument('name', InputArgument::OPTIONAL, 'The name of the migration (e.g. \'add_email_index\')'); + } + + protected function execute(InputInterface $input, OutputInterface $output) : int + { + $io = new SymfonyStyle($input, $output); + $connection = type_string()->assert($input->getOption('connection') ?? $this->defaultConnection); + $generator = type_instance_of(MigrationGenerator::class)->assert($this->container->get("flow.postgresql.{$connection}.migrations.generator")); + $configuration = type_instance_of(MigrationsConfiguration::class)->assert($this->container->get("flow.postgresql.{$connection}.migrations.configuration")); + /** @var ?string $name */ + $name = $input->getArgument('name'); + + $version = $generator->generateDataMigration($name); + + $directory = $configuration->migrationsDirectory . '/' . $version . ($name !== null ? '_' . $name : ''); + $realDirectory = \realpath($directory) ?: $directory; + + $io->success(\sprintf('Generated migration: %s', $version)); + + $io->table(['File', 'Path'], [ + ['Migration', $realDirectory . '/' . $configuration->migrationFileName], + ['Rollback', $realDirectory . '/' . $configuration->rollbackFileName], + ]); + + return Command::SUCCESS; + } +} diff --git a/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Command/LatestCommand.php b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Command/LatestCommand.php new file mode 100644 index 0000000000..820eb56f83 --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Command/LatestCommand.php @@ -0,0 +1,80 @@ +addOption('connection', 'c', InputOption::VALUE_OPTIONAL, 'The connection to use', null); + } + + protected function execute(InputInterface $input, OutputInterface $output) : int + { + $io = new SymfonyStyle($input, $output); + $connection = type_string()->assert($input->getOption('connection') ?? $this->defaultConnection); + $migrator = type_instance_of(Migrator::class)->assert($this->container->get("flow.postgresql.{$connection}.migrations.migrator")); + + $statuses = $migrator->status(); + + if (\count($statuses) === 0) { + $io->note('No migrations available.'); + + return Command::SUCCESS; + } + + $io->title('Latest Migrations'); + + $all = \iterator_to_array($statuses); + $latest = \array_slice($all, -5); + + $rows = []; + + foreach ($latest as $migration) { + $isLast = $migration === \end($all); + $stateLabel = match ($migration->state) { + MigrationState::EXECUTED => 'EXECUTED', + MigrationState::PENDING => 'PENDING', + MigrationState::UNAVAILABLE => 'UNAVAILABLE', + }; + + $rows[] = [ + $isLast ? '►' : ' ', + $stateLabel, + (string) $migration->version, + $migration->name, + ]; + } + + $io->table(['', 'Status', 'Version', 'Name'], $rows); + + if (\count($all) > 5) { + $io->text(\sprintf(' Showing last 5 of %d migrations', \count($all))); + $io->newLine(); + } + + return Command::SUCCESS; + } +} diff --git a/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Command/ListCommand.php b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Command/ListCommand.php new file mode 100644 index 0000000000..5c7e264fa2 --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Command/ListCommand.php @@ -0,0 +1,81 @@ +addOption('connection', 'c', InputOption::VALUE_OPTIONAL, 'The connection to use', null); + } + + protected function execute(InputInterface $input, OutputInterface $output) : int + { + $io = new SymfonyStyle($input, $output); + $connection = type_string()->assert($input->getOption('connection') ?? $this->defaultConnection); + $migrator = type_instance_of(Migrator::class)->assert($this->container->get("flow.postgresql.{$connection}.migrations.migrator")); + + $io->title('Migrations'); + + $statuses = $migrator->status(); + + if (\count($statuses) === 0) { + $io->note('No migrations found.'); + + return Command::SUCCESS; + } + + $rows = []; + + foreach ($statuses as $migration) { + $stateLabel = match ($migration->state) { + MigrationState::EXECUTED => 'EXECUTED', + MigrationState::PENDING => 'PENDING', + MigrationState::UNAVAILABLE => 'UNAVAILABLE', + }; + + $executedAt = $migration->executedAt !== null + ? '' . $migration->executedAt->format('Y-m-d H:i:s') . '' + : '-'; + + $rows[] = [$stateLabel, (string) $migration->version, $migration->name, $executedAt]; + } + + $io->table(['Status', 'Version', 'Name', 'Executed at'], $rows); + + $executed = \count($statuses->executed()); + $pending = \count($statuses->pending()); + + $io->text(\sprintf( + ' %d executed, %d pending', + $executed, + $pending > 0 ? 'yellow' : 'green', + $pending, + )); + $io->newLine(); + + return Command::SUCCESS; + } +} diff --git a/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Command/MigrateCommand.php b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Command/MigrateCommand.php new file mode 100644 index 0000000000..16c753c9ff --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Command/MigrateCommand.php @@ -0,0 +1,133 @@ +addArgument('version', InputArgument::OPTIONAL, 'The version to migrate to (first, prev, next, latest, or version string)', 'latest') + ->addOption('connection', 'c', InputOption::VALUE_OPTIONAL, 'The connection to use', null) + ->addOption('dry-run', null, InputOption::VALUE_NONE, 'Execute migration as a dry run') + ->addOption('all-or-nothing', null, InputOption::VALUE_NONE, 'Wrap the entire migration in a transaction'); + } + + protected function execute(InputInterface $input, OutputInterface $output) : int + { + $io = new SymfonyStyle($input, $output); + $connection = type_string()->assert($input->getOption('connection') ?? $this->defaultConnection); + $migrator = type_instance_of(Migrator::class)->assert($this->container->get("flow.postgresql.{$connection}.migrations.migrator")); + $resolver = type_instance_of(VersionResolver::class)->assert($this->container->get("flow.postgresql.{$connection}.migrations.version_resolver")); + $configuration = type_instance_of(MigrationsConfiguration::class)->assert($this->container->get("flow.postgresql.{$connection}.migrations.configuration")); + $versionAlias = type_string()->assert($input->getArgument('version')); + $dryRun = (bool) $input->getOption('dry-run'); + $allOrNothing = $input->getOption('all-or-nothing') ? true : null; + + $io->title('Migrate' . ($dryRun ? ' (dry run)' : '')); + + $io->definitionList( + ['Connection' => "{$connection}"], + ['Target' => "{$versionAlias}"], + ['Directory' => "{$configuration->migrationsDirectory}"], + ); + + $statuses = $migrator->status(); + $pendingCount = \count($statuses->pending()); + $executedCount = \count($statuses->executed()); + + if (\count($statuses) === 0) { + $io->success('No migrations found.'); + + return Command::SUCCESS; + } + + if ($pendingCount === 0 && $versionAlias === 'latest') { + $io->success('Already up to date.'); + + return Command::SUCCESS; + } + + $statusRows = []; + + foreach ($statuses as $migration) { + $stateLabel = match ($migration->state) { + MigrationState::EXECUTED => 'EXECUTED', + MigrationState::PENDING => 'PENDING', + MigrationState::UNAVAILABLE => 'UNAVAILABLE', + }; + $statusRows[] = [$stateLabel, (string) $migration->version, $migration->name]; + } + + $io->table(['Status', 'Version', 'Name'], $statusRows); + + $version = $resolver->resolve($versionAlias); + + if ($input->isInteractive() && !$io->confirm(\sprintf('Migrate to version %s?', $version), false)) { + $io->warning('Migration cancelled.'); + + return Command::SUCCESS; + } + + $results = $migrator->migrate($version, $dryRun, $allOrNothing); + + if (\count($results) === 0) { + $io->success('Already up to date.'); + + return Command::SUCCESS; + } + + $rows = []; + $totalTime = 0; + + foreach ($results as $result) { + $totalTime += $result->executionTimeMs; + $direction = $result->direction === Direction::UP ? 'UP' : 'DOWN'; + + if ($result->error !== null) { + $rows[] = [$direction, (string) $result->version, 'FAILED', $result->executionTimeMs . 'ms']; + $io->table(['Direction', 'Version', 'Result', 'Time'], $rows); + $io->error(\sprintf('%s failed: %s', $result->version, $result->error->getMessage())); + + return Command::FAILURE; + } + + if ($result->skipped) { + $rows[] = [$direction, (string) $result->version, 'SKIPPED', '-']; + } else { + $rows[] = [$direction, (string) $result->version, 'OK', $result->executionTimeMs . 'ms']; + } + } + + $io->table(['Direction', 'Version', 'Result', 'Time'], $rows); + + if ($dryRun) { + $io->note('Dry run completed. No changes were applied.'); + } else { + $io->success(\sprintf('%d migration(s) executed in %dms.', \count($results), $totalTime)); + } + + return Command::SUCCESS; + } +} diff --git a/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Command/RunSqlCommand.php b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Command/RunSqlCommand.php new file mode 100644 index 0000000000..b7c06f473f --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Command/RunSqlCommand.php @@ -0,0 +1,68 @@ +addOption('connection', 'c', InputOption::VALUE_OPTIONAL, 'The connection to use', null) + ->addArgument('sql', InputArgument::REQUIRED, 'The SQL statement to execute'); + } + + protected function execute(InputInterface $input, OutputInterface $output) : int + { + $connection = type_string()->assert($input->getOption('connection') ?? $this->defaultConnection); + $client = type_instance_of(Client::class)->assert($this->container->get("flow.postgresql.{$connection}.client")); + $sql = type_string()->assert($input->getArgument('sql')); + + if (\str_starts_with(\strtoupper(\trim($sql)), 'SELECT')) { + $rows = $client->fetchAll($sql); + + if (empty($rows)) { + $output->writeln('No results.'); + + return Command::SUCCESS; + } + + $headers = \array_keys($rows[0]); + $output->writeln(\implode("\t", $headers)); + $output->writeln(\str_repeat('-', 80)); + + foreach ($rows as $row) { + /** @var array $row */ + $output->writeln(\implode("\t", \array_map(static fn ($v) => $v === null ? 'NULL' : \strval($v), $row))); + } + + $output->writeln(''); + $output->writeln(\sprintf('%d row(s) returned.', \count($rows))); + + return Command::SUCCESS; + } + + $affected = $client->execute($sql); + $output->writeln(\sprintf('%d row(s) affected.', $affected)); + + return Command::SUCCESS; + } +} diff --git a/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Command/StatusCommand.php b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Command/StatusCommand.php new file mode 100644 index 0000000000..fb87abc233 --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Command/StatusCommand.php @@ -0,0 +1,63 @@ +addOption('connection', 'c', InputOption::VALUE_OPTIONAL, 'The connection to use', null); + } + + protected function execute(InputInterface $input, OutputInterface $output) : int + { + $io = new SymfonyStyle($input, $output); + $connection = type_string()->assert($input->getOption('connection') ?? $this->defaultConnection); + $migrator = type_instance_of(Migrator::class)->assert($this->container->get("flow.postgresql.{$connection}.migrations.migrator")); + + $status = $migrator->status(); + + $total = \count($status); + $executed = \count($status->executed()); + $pending = \count($status->pending()); + + $io->title('Migration Status'); + + $io->definitionList( + ['Connection' => "{$connection}"], + ['Total migrations' => (string) $total], + ['Executed' => "{$executed}"], + ['Pending' => $pending > 0 ? "{$pending}" : '0'], + ); + + if ($pending > 0) { + $io->warning(\sprintf('%d migration(s) pending. Run flow:migrations:migrate to execute.', $pending)); + } else { + $io->success('All migrations are up to date.'); + } + + return Command::SUCCESS; + } +} diff --git a/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Command/UpToDateCommand.php b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Command/UpToDateCommand.php new file mode 100644 index 0000000000..16a91fb709 --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Command/UpToDateCommand.php @@ -0,0 +1,62 @@ +addOption('connection', 'c', InputOption::VALUE_OPTIONAL, 'The connection to use', null); + } + + protected function execute(InputInterface $input, OutputInterface $output) : int + { + $io = new SymfonyStyle($input, $output); + $connection = type_string()->assert($input->getOption('connection') ?? $this->defaultConnection); + $migrator = type_instance_of(Migrator::class)->assert($this->container->get("flow.postgresql.{$connection}.migrations.migrator")); + + $status = $migrator->status(); + $pending = $status->pending(); + + if (\count($pending) === 0) { + $io->success('All migrations are up to date.'); + + return Command::SUCCESS; + } + + $rows = []; + + foreach ($pending as $migration) { + $rows[] = ['PENDING', (string) $migration->version, $migration->name]; + } + + $io->error(\sprintf('Out of date! %d pending migration(s).', \count($pending))); + $io->table(['Status', 'Version', 'Name'], $rows); + $io->text(' Run flow:migrations:migrate to execute pending migrations.'); + $io->newLine(); + + return Command::FAILURE; + } +} diff --git a/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/DependencyInjection/Compiler/CatalogProviderPass.php b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/DependencyInjection/Compiler/CatalogProviderPass.php new file mode 100644 index 0000000000..7e4e9aa29a --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/DependencyInjection/Compiler/CatalogProviderPass.php @@ -0,0 +1,38 @@ +findTaggedServiceIds('flow.postgresql.catalog_provider') as $serviceId => $tags) { + $providerRefs[] = new Reference($serviceId); + } + + if ($container->hasParameter('flow.postgresql.catalog_provider.service_ids')) { + /** @var list $serviceIds */ + $serviceIds = $container->getParameter('flow.postgresql.catalog_provider.service_ids'); + + foreach ($serviceIds as $serviceId) { + $providerRefs[] = new Reference($serviceId); + } + } + + if ($providerRefs === [] && $container->hasParameter('flow.postgresql.migrations.connections')) { + throw new \LogicException('No catalog providers found. Register at least one catalog provider using #[AsCatalogProvider] attribute, "flow.postgresql.catalog_provider" tag, or "catalog_providers" configuration.'); + } + + $chainDef = new Definition(ChainCatalogProvider::class, $providerRefs); + $chainDef->setPublic(true); + $container->setDefinition('flow.postgresql.migrations.catalog_provider', $chainDef); + } +} diff --git a/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/DependencyInjection/Configuration.php b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/DependencyInjection/Configuration.php new file mode 100644 index 0000000000..442031c2aa --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/DependencyInjection/Configuration.php @@ -0,0 +1,108 @@ +getRootNode() + ->children() + ->arrayNode('connections') + ->requiresAtLeastOneElement() + ->useAttributeAsKey('name') + ->arrayPrototype() + ->children() + ->scalarNode('dsn') + ->isRequired() + ->cannotBeEmpty() + ->info('PostgreSQL connection DSN (e.g. postgresql://user:pass@localhost:5432/dbname)') + ->end() + ->arrayNode('telemetry') + ->children() + ->scalarNode('service_id') + ->isRequired() + ->cannotBeEmpty() + ->info('Service ID of the Telemetry instance (e.g. flow.telemetry)') + ->end() + ->scalarNode('clock_service_id') + ->defaultNull() + ->info('Service ID of a PSR ClockInterface implementation. Default: creates SystemClock') + ->end() + ->booleanNode('trace_queries')->defaultTrue()->end() + ->booleanNode('trace_transactions')->defaultTrue()->end() + ->booleanNode('collect_metrics')->defaultTrue()->end() + ->booleanNode('log_queries')->defaultFalse()->end() + ->integerNode('max_query_length')->defaultValue(1000)->min(0)->end() + ->booleanNode('include_parameters')->defaultFalse()->end() + ->integerNode('max_parameters')->defaultValue(10)->min(0)->end() + ->integerNode('max_parameter_length')->defaultValue(100)->min(0)->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ->arrayNode('migrations') + ->canBeEnabled() + ->children() + ->scalarNode('directory') + ->defaultValue('%kernel.project_dir%/migrations') + ->cannotBeEmpty() + ->end() + ->scalarNode('namespace') + ->defaultValue('App\\Migrations') + ->cannotBeEmpty() + ->end() + ->scalarNode('table_name') + ->defaultValue('flow_migrations') + ->cannotBeEmpty() + ->end() + ->scalarNode('table_schema') + ->defaultValue('public') + ->cannotBeEmpty() + ->end() + ->scalarNode('migration_file_name') + ->defaultValue('migration.php') + ->cannotBeEmpty() + ->end() + ->scalarNode('rollback_file_name') + ->defaultValue('rollback.php') + ->cannotBeEmpty() + ->end() + ->booleanNode('all_or_nothing') + ->defaultFalse() + ->info('Wrap all migrations in a single transaction (default: false)') + ->end() + ->booleanNode('generate_rollback') + ->defaultTrue() + ->info('Generate rollback files when creating migrations (default: true)') + ->end() + ->end() + ->end() + ->arrayNode('catalog_providers') + ->info('List of catalog providers to merge into the target schema. Each entry must have either "catalog_provider_id" or "catalog".') + ->arrayPrototype() + ->children() + ->scalarNode('catalog_provider_id') + ->defaultNull() + ->info('Service ID of Flow\\PostgreSql\\Schema\\CatalogProvider') + ->end() + ->variableNode('catalog') + ->defaultNull() + ->info('Inline catalog definition matching Catalog::fromArray() shape') + ->end() + ->end() + ->end() + ->end() + ->end(); + + return $treeBuilder; + } +} diff --git a/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/DependencyInjection/FlowPostgreSqlExtension.php b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/DependencyInjection/FlowPostgreSqlExtension.php new file mode 100644 index 0000000000..b2694ed3f0 --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/DependencyInjection/FlowPostgreSqlExtension.php @@ -0,0 +1,276 @@ + $configs + */ + public function load(array $configs, ContainerBuilder $container) : void + { + $configuration = new Configuration(); + + /** @var array{connections: array, migrations: array{enabled: bool, directory: string, namespace: string, table_name: string, table_schema: string, migration_file_name: string, rollback_file_name: string, all_or_nothing: bool, generate_rollback: bool}, catalog_providers: list}>} $config */ + $config = $this->processConfiguration($configuration, $configs); + + $isFirst = true; + $connectionNames = \array_keys($config['connections']); + + foreach ($config['connections'] as $name => $connectionConfig) { + $this->registerConnection($name, $connectionConfig, $container, $isFirst); + $isFirst = false; + } + + $this->registerCatalogProviders($config['catalog_providers'] ?? [], $container); + + $container->setParameter('flow.postgresql.default_connection', $connectionNames[0]); + + $loader = new PhpFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config')); + $loader->load('database.php'); + + if ($config['migrations']['enabled']) { + $isFirst = true; + + foreach ($connectionNames as $name) { + $this->registerMigrations($name, $config['migrations'], $container, $isFirst); + $isFirst = false; + } + + $container->setParameter('flow.postgresql.migrations.connections', $connectionNames); + $container->setParameter('flow.postgresql.migrations.default_connection', $connectionNames[0]); + + $loader->load('migrations.php'); + } + } + + /** + * @param list}> $catalogProviders + */ + private function registerCatalogProviders(array $catalogProviders, ContainerBuilder $container) : void + { + $configProviderServiceIds = []; + + foreach ($catalogProviders as $i => $providerConfig) { + if (\array_key_exists('catalog', $providerConfig) && $providerConfig['catalog'] !== null) { + $providerDef = new Definition(ArrayCatalogProvider::class, [$providerConfig['catalog']]); + $providerDef->addTag('flow.postgresql.catalog_provider'); + $container->setDefinition("flow.postgresql.catalog_provider.{$i}", $providerDef); + } elseif (\array_key_exists('catalog_provider_id', $providerConfig) && $providerConfig['catalog_provider_id'] !== null) { + $configProviderServiceIds[] = type_string()->assert($providerConfig['catalog_provider_id']); + } + } + + if ($configProviderServiceIds !== []) { + $container->setParameter('flow.postgresql.catalog_provider.service_ids', $configProviderServiceIds); + } + } + + /** + * @param array{dsn: string, telemetry?: array{service_id: string, clock_service_id: ?string, trace_queries: bool, trace_transactions: bool, collect_metrics: bool, log_queries: bool, max_query_length: int, include_parameters: bool, max_parameters: int, max_parameter_length: int}} $connectionConfig + */ + private function registerConnection(string $name, array $connectionConfig, ContainerBuilder $container, bool $isFirst) : void + { + $parserDef = new Definition(DsnParser::class); + $container->setDefinition("flow.postgresql.{$name}.dsn_parser", $parserDef); + + $paramsDef = new Definition(ConnectionParameters::class); + $paramsDef->setFactory([new Reference("flow.postgresql.{$name}.dsn_parser"), 'parse']); + $paramsDef->setArguments([$connectionConfig['dsn']]); + $container->setDefinition("flow.postgresql.{$name}.connection_parameters", $paramsDef); + + $paramsDef->setPublic(true); + + $clientDef = new Definition(PgSqlClient::class); + $clientDef->setFactory([PgSqlClient::class, 'connect']); + $clientDef->setArguments([new Reference("flow.postgresql.{$name}.connection_parameters")]); + $clientDef->setPublic(true); + $container->setDefinition("flow.postgresql.{$name}.client", $clientDef); + + if (\array_key_exists('telemetry', $connectionConfig)) { + $this->registerTelemetry($name, $connectionConfig['telemetry'], $container); + } + + if ($isFirst) { + $container->setAlias(Client::class, "flow.postgresql.{$name}.client"); + $container->setAlias(ConnectionParameters::class, "flow.postgresql.{$name}.connection_parameters"); + } + } + + /** + * @param array{enabled: bool, directory: string, namespace: string, table_name: string, table_schema: string, migration_file_name: string, rollback_file_name: string, all_or_nothing: bool, generate_rollback: bool} $mc + */ + private function registerMigrations(string $name, array $mc, ContainerBuilder $container, bool $isFirst) : void + { + + $catalogProviderRef = new Reference('flow.postgresql.migrations.catalog_provider'); + + $configDef = new Definition(MigrationsConfiguration::class, [ + new Reference("flow.postgresql.{$name}.client"), + $catalogProviderRef, + $mc['directory'], + $mc['namespace'], + $mc['table_name'], + $mc['table_schema'], + $mc['migration_file_name'], + $mc['rollback_file_name'], + $mc['all_or_nothing'], + $mc['generate_rollback'], + ]); + $configDef->setPublic(true); + $container->setDefinition("flow.postgresql.{$name}.migrations.configuration", $configDef); + + $fsDef = new Definition(NativeLocalFilesystem::class); + $container->setDefinition("flow.postgresql.{$name}.migrations.filesystem", $fsDef); + + $pathDef = new Definition(Path::class); + $pathDef->setFactory([Path::class, 'from']); + $pathDef->setArguments([$mc['directory']]); + $container->setDefinition("flow.postgresql.{$name}.migrations.path", $pathDef); + + $repoDef = new Definition(FilesystemMigrationRepository::class, [ + new Reference("flow.postgresql.{$name}.migrations.filesystem"), + new Reference("flow.postgresql.{$name}.migrations.path"), + new Reference("flow.postgresql.{$name}.migrations.configuration"), + ]); + $repoDef->setPublic(true); + $container->setDefinition("flow.postgresql.{$name}.migrations.repository", $repoDef); + + $factoryDef = new Definition(MigrationsFactory::class, [ + new Reference("flow.postgresql.{$name}.migrations.configuration"), + new Reference("flow.postgresql.{$name}.migrations.repository"), + ]); + $container->setDefinition("flow.postgresql.{$name}.migrations.factory", $factoryDef); + + $migratorDef = new Definition(Migrator::class); + $migratorDef->setFactory([new Reference("flow.postgresql.{$name}.migrations.factory"), 'createMigrator']); + $migratorDef->setPublic(true); + $container->setDefinition("flow.postgresql.{$name}.migrations.migrator", $migratorDef); + + $storeDef = new Definition(MigrationStore::class); + $storeDef->setFactory([new Reference("flow.postgresql.{$name}.migrations.factory"), 'createStore']); + $storeDef->setPublic(true); + $container->setDefinition("flow.postgresql.{$name}.migrations.store", $storeDef); + + $executorDef = new Definition(MigrationExecutor::class); + $executorDef->setFactory([new Reference("flow.postgresql.{$name}.migrations.factory"), 'createExecutor']); + $container->setDefinition("flow.postgresql.{$name}.migrations.executor", $executorDef); + + $resolverDef = new Definition(VersionResolver::class); + $resolverDef->setFactory([new Reference("flow.postgresql.{$name}.migrations.factory"), 'createVersionResolver']); + $resolverDef->setPublic(true); + $container->setDefinition("flow.postgresql.{$name}.migrations.version_resolver", $resolverDef); + + $twigLoaderDef = new Definition(FilesystemLoader::class, [ + [__DIR__ . '/../Resources/templates'], + ]); + $container->setDefinition("flow.postgresql.{$name}.migrations.twig_loader", $twigLoaderDef); + + $twigDef = new Definition(Environment::class, [ + new Reference("flow.postgresql.{$name}.migrations.twig_loader"), + ]); + $container->setDefinition("flow.postgresql.{$name}.migrations.twig", $twigDef); + + $versionGenDef = new Definition(TimestampVersionGenerator::class); + $container->setDefinition("flow.postgresql.{$name}.migrations.version_generator", $versionGenDef); + + $generatorDef = new Definition(TwigMigrationGenerator::class, [ + new Reference("flow.postgresql.{$name}.migrations.configuration"), + new Reference("flow.postgresql.{$name}.migrations.version_generator"), + new Reference("flow.postgresql.{$name}.migrations.twig"), + new Reference("flow.postgresql.{$name}.migrations.filesystem"), + ]); + $generatorDef->setPublic(true); + $container->setDefinition("flow.postgresql.{$name}.migrations.generator", $generatorDef); + + $diffGenDef = new Definition(DiffMigrationGenerator::class); + $diffGenDef->setFactory([new Reference("flow.postgresql.{$name}.migrations.factory"), 'createDiffGenerator']); + $diffGenDef->setArguments([new Reference("flow.postgresql.{$name}.migrations.generator")]); + $diffGenDef->setPublic(true); + $container->setDefinition("flow.postgresql.{$name}.migrations.diff_generator", $diffGenDef); + + if ($isFirst) { + $container->setAlias(MigrationsConfiguration::class, "flow.postgresql.{$name}.migrations.configuration"); + $container->setAlias(MigrationsFactory::class, "flow.postgresql.{$name}.migrations.factory"); + $container->setAlias(Migrator::class, "flow.postgresql.{$name}.migrations.migrator"); + $container->setAlias(MigrationStore::class, "flow.postgresql.{$name}.migrations.store"); + $container->setAlias(MigrationRepository::class, "flow.postgresql.{$name}.migrations.repository"); + $container->setAlias(MigrationExecutor::class, "flow.postgresql.{$name}.migrations.executor"); + $container->setAlias(VersionResolver::class, "flow.postgresql.{$name}.migrations.version_resolver"); + $container->setAlias(MigrationGenerator::class, "flow.postgresql.{$name}.migrations.generator"); + $container->setAlias(DiffMigrationGenerator::class, "flow.postgresql.{$name}.migrations.diff_generator"); + } + } + + /** + * @param array{service_id: string, clock_service_id: ?string, trace_queries: bool, trace_transactions: bool, collect_metrics: bool, log_queries: bool, max_query_length: int, include_parameters: bool, max_parameters: int, max_parameter_length: int} $telemetryConfig + */ + private function registerTelemetry(string $name, array $telemetryConfig, ContainerBuilder $container) : void + { + $optionsDef = new Definition(PostgreSqlTelemetryOptions::class, [ + $telemetryConfig['trace_queries'], + $telemetryConfig['trace_transactions'], + $telemetryConfig['collect_metrics'], + $telemetryConfig['log_queries'], + $telemetryConfig['max_query_length'], + $telemetryConfig['include_parameters'], + $telemetryConfig['max_parameters'], + $telemetryConfig['max_parameter_length'], + ]); + $container->setDefinition("flow.postgresql.{$name}.telemetry.options", $optionsDef); + + if ($telemetryConfig['clock_service_id'] !== null) { + $clockRef = new Reference($telemetryConfig['clock_service_id']); + } else { + $container->setDefinition("flow.postgresql.{$name}.telemetry.clock", new Definition(SystemClock::class)); + $clockRef = new Reference("flow.postgresql.{$name}.telemetry.clock"); + } + + $configDef = new Definition(PostgreSqlTelemetryConfig::class, [ + new Reference($telemetryConfig['service_id']), + $clockRef, + new Reference("flow.postgresql.{$name}.telemetry.options"), + ]); + $container->setDefinition("flow.postgresql.{$name}.telemetry.config", $configDef); + + $traceableDef = new Definition(TraceableClient::class, [ + new Reference("flow.postgresql.{$name}.client.telemetry.inner"), + new Reference("flow.postgresql.{$name}.telemetry.config"), + ]); + $traceableDef->setDecoratedService("flow.postgresql.{$name}.client"); + $traceableDef->setPublic(true); + $container->setDefinition("flow.postgresql.{$name}.client.telemetry", $traceableDef); + } +} diff --git a/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/FlowPostgreSqlBundle.php b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/FlowPostgreSqlBundle.php new file mode 100644 index 0000000000..7b66df2526 --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/FlowPostgreSqlBundle.php @@ -0,0 +1,36 @@ +addCompilerPass(new CatalogProviderPass()); + + $container->registerAttributeForAutoconfiguration( + AsCatalogProvider::class, + static function (ChildDefinition $definition, AsCatalogProvider $attribute, \Reflector $reflector) : void { + $definition->addTag('flow.postgresql.catalog_provider'); + }, + ); + } + + #[\Override] + public function getContainerExtension() : ExtensionInterface + { + return new FlowPostgreSqlExtension(); + } +} diff --git a/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Generator/TwigMigrationGenerator.php b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Generator/TwigMigrationGenerator.php new file mode 100644 index 0000000000..0f2eb4ddf7 --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Generator/TwigMigrationGenerator.php @@ -0,0 +1,76 @@ +versionGenerator->generate(); + $directory = $this->migrationDirectory($version, $name); + + $this->filesystem->writeTo(Path::from($directory . '/' . $this->configuration->migrationFileName)) + ->append($this->twig->render('data_migration.php.twig', ['namespace' => $this->configuration->migrationsNamespace])) + ->close(); + + if ($this->configuration->generateRollback) { + $this->filesystem->writeTo(Path::from($directory . '/' . $this->configuration->rollbackFileName)) + ->append($this->twig->render('data_rollback.php.twig', ['namespace' => $this->configuration->migrationsNamespace])) + ->close(); + } + + return $version; + } + + /** + * @param list $upSql + * @param null|list $downSql + */ + public function generateSchemaMigration(?string $name, array $upSql, ?array $downSql = null) : Version + { + $version = $this->versionGenerator->generate(); + $directory = $this->migrationDirectory($version, $name); + + $this->filesystem->writeTo(Path::from($directory . '/' . $this->configuration->migrationFileName)) + ->append($this->twig->render('schema_migration.php.twig', [ + 'namespace' => $this->configuration->migrationsNamespace, + 'queries' => $upSql, + ])) + ->close(); + + if ($downSql !== null) { + $this->filesystem->writeTo(Path::from($directory . '/' . $this->configuration->rollbackFileName)) + ->append($this->twig->render('schema_rollback.php.twig', [ + 'namespace' => $this->configuration->migrationsNamespace, + 'queries' => $downSql, + ])) + ->close(); + } + + return $version; + } + + private function migrationDirectory(Version $version, ?string $name) : string + { + if ($name === null) { + return $this->configuration->migrationsDirectory . '/' . $version; + } + + return $this->configuration->migrationsDirectory . '/' . $version . '_' . $name; + } +} diff --git a/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Repository/FilesystemMigrationRepository.php b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Repository/FilesystemMigrationRepository.php new file mode 100644 index 0000000000..d8f84f4be9 --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Repository/FilesystemMigrationRepository.php @@ -0,0 +1,87 @@ +migrationsDirectory->path() . '/*'); + $migrations = []; + + foreach ($this->filesystem->list($pattern, new KeepAll()) as $entry) { + if ($entry->isFile()) { + continue; + } + + $dirName = $entry->path->basename(); + + if (\preg_match('/^(\w+?)_(.+)$/', $dirName, $matches) === 1) { + $version = Version::fromString($matches[1]); + $name = $matches[2]; + } elseif (\preg_match('/^(\w+)$/', $dirName, $matches) === 1) { + $version = Version::fromString($matches[1]); + $name = $matches[1]; + } else { + continue; + } + + $migrations[] = $this->loadMigration($entry->path, $version, $name); + } + + return new AvailableMigrations(...$migrations); + } + + public function get(Version $version) : AvailableMigration + { + return $this->all()->get($version); + } + + public function has(Version $version) : bool + { + return $this->all()->has($version); + } + + private function loadMigration(Path $directoryPath, Version $version, string $name) : AvailableMigration + { + $migrationPath = Path::from($directoryPath->path() . '/' . $this->configuration->migrationFileName); + + if ($this->filesystem->status($migrationPath) === null) { + throw MigrationException::missingMigrationFile($directoryPath->path()); + } + + $migration = require $migrationPath->path(); + + if (!$migration instanceof Migration) { + throw MigrationException::invalidDataMigration($migrationPath->path()); + } + + $rollback = null; + $rollbackPath = Path::from($directoryPath->path() . '/' . $this->configuration->rollbackFileName); + + if ($this->filesystem->status($rollbackPath) !== null) { + $rollback = require $rollbackPath->path(); + + if (!$rollback instanceof Rollback) { + throw MigrationException::invalidRollback($rollbackPath->path()); + } + } + + return new AvailableMigration($version, $name, $migration, $rollback); + } +} diff --git a/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Resources/config/database.php b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Resources/config/database.php new file mode 100644 index 0000000000..fe0349b21b --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Resources/config/database.php @@ -0,0 +1,24 @@ +services(); + + $services->set('flow.postgresql.command.database_create', CreateDatabaseCommand::class) + ->args([service('service_container'), param('flow.postgresql.default_connection')]) + ->tag('console.command'); + + $services->set('flow.postgresql.command.database_drop', DropDatabaseCommand::class) + ->args([service('service_container'), param('flow.postgresql.default_connection')]) + ->tag('console.command'); + + $services->set('flow.postgresql.command.sql_run', RunSqlCommand::class) + ->args([service('service_container'), param('flow.postgresql.default_connection')]) + ->tag('console.command'); +}; diff --git a/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Resources/config/migrations.php b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Resources/config/migrations.php new file mode 100644 index 0000000000..023bd1d695 --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Resources/config/migrations.php @@ -0,0 +1,55 @@ +services(); + + $services->set('flow.postgresql.command.current', CurrentCommand::class) + ->args([service('service_container'), param('flow.postgresql.migrations.default_connection')]) + ->tag('console.command'); + + $services->set('flow.postgresql.command.latest', LatestCommand::class) + ->args([service('service_container'), param('flow.postgresql.migrations.default_connection')]) + ->tag('console.command'); + + $services->set('flow.postgresql.command.status', StatusCommand::class) + ->args([service('service_container'), param('flow.postgresql.migrations.default_connection')]) + ->tag('console.command'); + + $services->set('flow.postgresql.command.list', ListCommand::class) + ->args([service('service_container'), param('flow.postgresql.migrations.default_connection')]) + ->tag('console.command'); + + $services->set('flow.postgresql.command.migrate', MigrateCommand::class) + ->args([service('service_container'), param('flow.postgresql.migrations.default_connection')]) + ->tag('console.command'); + + $services->set('flow.postgresql.command.execute', ExecuteCommand::class) + ->args([service('service_container'), param('flow.postgresql.migrations.default_connection')]) + ->tag('console.command'); + + $services->set('flow.postgresql.command.diff', DiffCommand::class) + ->args([service('service_container'), param('flow.postgresql.migrations.default_connection')]) + ->tag('console.command'); + + $services->set('flow.postgresql.command.generate', GenerateCommand::class) + ->args([service('service_container'), param('flow.postgresql.migrations.default_connection')]) + ->tag('console.command'); + + $services->set('flow.postgresql.command.up_to_date', UpToDateCommand::class) + ->args([service('service_container'), param('flow.postgresql.migrations.default_connection')]) + ->tag('console.command'); +}; diff --git a/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Resources/templates/data_migration.php.twig b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Resources/templates/data_migration.php.twig new file mode 100644 index 0000000000..12178a9ece --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Resources/templates/data_migration.php.twig @@ -0,0 +1,22 @@ +{% autoescape false %}client->execute('{{ query|replace({"'": "\\'"}) }}'); +{% endfor %} + } + + public function transactional() : bool + { + return true; + } +}; +{% endautoescape %} diff --git a/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Resources/templates/schema_rollback.php.twig b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Resources/templates/schema_rollback.php.twig new file mode 100644 index 0000000000..39b7b18630 --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/src/Flow/Bridge/Symfony/PostgreSqlBundle/Resources/templates/schema_rollback.php.twig @@ -0,0 +1,24 @@ +{% autoescape false %}client->execute('{{ query|replace({"'": "\\'"}) }}'); +{% endfor %} + } + + public function transactional() : bool + { + return true; + } +}; +{% endautoescape %} diff --git a/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Context/SymfonyContext.php b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Context/SymfonyContext.php new file mode 100644 index 0000000000..053867185d --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Context/SymfonyContext.php @@ -0,0 +1,88 @@ +kernel !== null) { + $this->shutdown(); + } + + $this->kernel = new TestKernel('test', false); + + if (isset($options['config']) && \is_callable($options['config'])) { + $options['config']($this->kernel); + } + + $this->kernel->boot(); + + return $this->kernel; + } + + public function getContainer() : ContainerInterface + { + if ($this->kernel === null) { + throw new \LogicException('Kernel has not been booted. Call bootKernel() first.'); + } + + return $this->kernel->getContainer(); + } + + public function getKernel() : TestKernel + { + if ($this->kernel === null) { + throw new \LogicException('Kernel has not been booted. Call bootKernel() first.'); + } + + return $this->kernel; + } + + /** + * @template T of object + * + * @param class-string $typeClass + * + * @return T + */ + public function getService(string $serviceId, string $typeClass) : object + { + return type_instance_of($typeClass)->assert($this->getContainer()->get($serviceId)); + } + + public function shutdown() : void + { + if ($this->kernel === null) { + return; + } + + $cacheDir = $this->kernel->getCacheDir(); + $logDir = $this->kernel->getLogDir(); + + $this->kernel->shutdown(); + $this->kernel = null; + + $filesystem = new Filesystem(); + + if ($filesystem->exists($cacheDir)) { + $filesystem->remove($cacheDir); + } + + if ($filesystem->exists($logDir)) { + $filesystem->remove($logDir); + } + } +} diff --git a/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Fixture/migrations/20260401120000_create_users/migration.php b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Fixture/migrations/20260401120000_create_users/migration.php new file mode 100644 index 0000000000..c3b783e29b --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Fixture/migrations/20260401120000_create_users/migration.php @@ -0,0 +1,17 @@ +client->execute('CREATE TABLE users (id SERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL)'); + } + + public function transactional() : bool + { + return true; + } +}; diff --git a/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Fixture/migrations/20260401120000_create_users/rollback.php b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Fixture/migrations/20260401120000_create_users/rollback.php new file mode 100644 index 0000000000..91742b3bf1 --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Fixture/migrations/20260401120000_create_users/rollback.php @@ -0,0 +1,17 @@ +client->execute('DROP TABLE users'); + } + + public function transactional() : bool + { + return true; + } +}; diff --git a/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Fixture/migrations/20260402100000_seed_data/migration.php b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Fixture/migrations/20260402100000_seed_data/migration.php new file mode 100644 index 0000000000..6f4d905717 --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Fixture/migrations/20260402100000_seed_data/migration.php @@ -0,0 +1,17 @@ +client->execute("INSERT INTO users (name) VALUES ('seed')"); + } + + public function transactional() : bool + { + return true; + } +}; diff --git a/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Fixture/migrations/20260402100000_seed_data/rollback.php b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Fixture/migrations/20260402100000_seed_data/rollback.php new file mode 100644 index 0000000000..2973a2e909 --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Fixture/migrations/20260402100000_seed_data/rollback.php @@ -0,0 +1,17 @@ +client->execute("DELETE FROM users WHERE name = 'seed'"); + } + + public function transactional() : bool + { + return true; + } +}; diff --git a/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Fixture/migrations/20260403090000_add_column/migration.php b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Fixture/migrations/20260403090000_add_column/migration.php new file mode 100644 index 0000000000..e450697b6b --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Fixture/migrations/20260403090000_add_column/migration.php @@ -0,0 +1,17 @@ +client->execute('ALTER TABLE users ADD COLUMN email VARCHAR(255)'); + } + + public function transactional() : bool + { + return true; + } +}; diff --git a/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Fixtures/AttributeTestCatalogProvider.php b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Fixtures/AttributeTestCatalogProvider.php new file mode 100644 index 0000000000..2600611e53 --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Fixtures/AttributeTestCatalogProvider.php @@ -0,0 +1,25 @@ +> */ + private array $testBundles = []; + + /** @var array */ + private array $testConfigs = []; + + /** @var array */ + private array $testContainerConfigurators = []; + + /** @var array> */ + private array $testExtensionConfigs = []; + + private readonly string $testId; + + public function __construct(string $environment = 'test', bool $debug = true) + { + $this->testId = \bin2hex(\random_bytes(8)); + + parent::__construct($environment, $debug); + } + + /** + * @param class-string $bundleClass + */ + public function addTestBundle(string $bundleClass) : void + { + $this->testBundles[] = $bundleClass; + } + + public function addTestConfig(string $configPath) : void + { + $this->testConfigs[] = $configPath; + } + + /** + * @param callable(ContainerBuilder): void $configurator + */ + public function addTestContainerConfigurator(callable $configurator) : void + { + $this->testContainerConfigurators[] = $configurator; + } + + /** + * @param array $config + */ + public function addTestExtensionConfig(string $extension, array $config) : void + { + $this->testExtensionConfigs[$extension] = \array_merge( + $this->testExtensionConfigs[$extension] ?? [], + $config + ); + } + + #[\Override] + public function getCacheDir() : string + { + return \sys_get_temp_dir() . '/flow_postgresql_bundle_test/' . $this->environment . '/' . $this->testId . '/cache'; + } + + #[\Override] + public function getLogDir() : string + { + return \sys_get_temp_dir() . '/flow_postgresql_bundle_test/' . $this->environment . '/' . $this->testId . '/log'; + } + + #[\Override] + public function getProjectDir() : string + { + return __DIR__ . '/..'; + } + + public function registerBundles() : iterable + { + yield new FlowPostgreSqlBundle(); + + foreach ($this->testBundles as $bundleClass) { + yield new $bundleClass(); + } + } + + public function registerContainerConfiguration(LoaderInterface $loader) : void + { + foreach ($this->testConfigs as $configPath) { + $loader->load($configPath); + } + + $loader->load(function (ContainerBuilder $container) : void { + foreach ($this->testExtensionConfigs as $extension => $config) { + $container->loadFromExtension($extension, $config); + } + + foreach ($this->testContainerConfigurators as $configurator) { + $configurator($container); + } + + $container->setParameter('kernel.secret', 'test_secret_' . $this->testId); + }); + } + + protected function build(ContainerBuilder $container) : void + { + parent::build($container); + + $container->addCompilerPass(new class implements CompilerPassInterface { + public function process(ContainerBuilder $container) : void + { + foreach ($container->getDefinitions() as $id => $definition) { + if (\str_starts_with($id, 'flow.postgresql') || \str_starts_with($id, 'test.')) { + $definition->setPublic(true); + } + } + + foreach ($container->getAliases() as $id => $alias) { + if (\str_starts_with($id, 'Flow\\PostgreSql\\') || \str_starts_with($id, 'Flow\\Bridge\\Symfony\\PostgreSqlBundle\\') || \str_starts_with($id, 'flow.postgresql')) { + $alias->setPublic(true); + } + } + } + }); + } +} diff --git a/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Fixtures/VoidTelemetryFactory.php b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Fixtures/VoidTelemetryFactory.php new file mode 100644 index 0000000000..2f8d51a40a --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Fixtures/VoidTelemetryFactory.php @@ -0,0 +1,29 @@ +context = new CommandTestContext(); + $this->context->bootWithMigrations(); + } + + protected function tearDown() : void + { + $this->context->shutdown(); + } +} diff --git a/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/Command/CommandTestContext.php b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/Command/CommandTestContext.php new file mode 100644 index 0000000000..14c3021b4f --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/Command/CommandTestContext.php @@ -0,0 +1,219 @@ +symfonyContext = new SymfonyContext(); + $this->filesystem = native_local_filesystem(); + $this->testDsn = \getenv('PGSQL_DATABASE_URL') ?: 'postgresql://postgres:postgres@localhost:5432/postgres'; + $this->migrationsDir = \sys_get_temp_dir() . '/flow_test_migrations_' . \bin2hex(\random_bytes(4)); + \mkdir($this->migrationsDir, 0755, true); + + $client = PgSqlClient::connect((new DsnParser())->parse($this->testDsn)); + $client->execute('DROP TABLE IF EXISTS test_users, flow_migrations_test CASCADE'); + $client->close(); + } + + public function bootForDatabaseManagement(string $targetDatabase) : void + { + $targetDsn = \preg_replace('#/[^/?]+(\?|$)#', '/' . $targetDatabase . '$1', $this->testDsn); + + $this->symfonyContext->bootKernel([ + 'config' => static function (TestKernel $kernel) use ($targetDsn) : void { + $kernel->addTestExtensionConfig('flow_postgresql', [ + 'connections' => [ + 'default' => [ + 'dsn' => $targetDsn, + ], + ], + ]); + }, + ]); + } + + public function bootWithMigrations() : void + { + $this->symfonyContext->bootKernel([ + 'config' => function (TestKernel $kernel) : void { + $kernel->addTestContainerConfigurator(static function (ContainerBuilder $container) : void { + $container->register('test.catalog_provider', SimpleTestCatalogProvider::class) + ->setPublic(true); + }); + $kernel->addTestExtensionConfig('flow_postgresql', [ + 'connections' => [ + 'default' => [ + 'dsn' => $this->testDsn, + ], + ], + 'migrations' => [ + 'enabled' => true, + 'directory' => $this->migrationsDir, + 'namespace' => 'FlowTest\\Migrations', + 'table_name' => 'flow_migrations_test', + ], + 'catalog_providers' => [ + ['catalog_provider_id' => 'test.catalog_provider'], + ], + ]); + }, + ]); + } + + public function bootWithMigrationsForDatabase(string $database) : void + { + $targetDsn = \preg_replace('#/[^/?]+(\?|$)#', '/' . $database . '$1', $this->testDsn); + + $this->symfonyContext->bootKernel([ + 'config' => function (TestKernel $kernel) use ($targetDsn) : void { + $kernel->addTestContainerConfigurator(static function (ContainerBuilder $container) : void { + $container->register('test.catalog_provider', SimpleTestCatalogProvider::class) + ->setPublic(true); + }); + $kernel->addTestExtensionConfig('flow_postgresql', [ + 'connections' => [ + 'default' => [ + 'dsn' => $targetDsn, + ], + ], + 'migrations' => [ + 'enabled' => true, + 'directory' => $this->migrationsDir, + 'namespace' => 'FlowTest\\Migrations', + 'table_name' => 'flow_migrations_test', + ], + 'catalog_providers' => [ + ['catalog_provider_id' => 'test.catalog_provider'], + ], + ]); + }, + ]); + } + + public function container() : ContainerInterface + { + return $this->symfonyContext->getContainer(); + } + + public function createDatabase(string $name) : void + { + $client = PgSqlClient::connect((new DsnParser())->parse($this->testDsn)->withDatabase('postgres')); + $client->execute("CREATE DATABASE \"{$name}\""); + $client->close(); + } + + public function databaseExists(string $name) : bool + { + $client = PgSqlClient::connect((new DsnParser())->parse($this->testDsn)->withDatabase('postgres')); + $count = $client->fetchScalarInt('SELECT COUNT(*) FROM pg_database WHERE datname = $1', [$name]); + $client->close(); + + return $count > 0; + } + + public function dropDatabase(string $name) : void + { + $client = PgSqlClient::connect((new DsnParser())->parse($this->testDsn)->withDatabase('postgres')); + $client->execute('SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = $1 AND pid <> pg_backend_pid()', [$name]); + $client->execute("DROP DATABASE IF EXISTS \"{$name}\""); + $client->close(); + } + + public function fileContent(string $filePath) : string + { + return $this->filesystem->readFrom(path($filePath))->content(); + } + + public function fileExists(string $filePath) : bool + { + return $this->filesystem->status(path($filePath)) !== null; + } + + public function generateDiffMigration() : string + { + /** @var Command $command */ + $command = $this->container()->get('flow.postgresql.command.diff'); + $tester = new CommandTester($command); + $tester->execute(['name' => 'create_test_users']); + + \preg_match('/Generated migration: (\S+)/', $tester->getDisplay(), $matches); + + return $matches[1]; + } + + public function migrationDirs(string $pattern) : array + { + $dirs = []; + + foreach ($this->filesystem->list(path($this->migrationsDir . '/' . $pattern), new KeepAll()) as $status) { + if ($status->isDirectory()) { + $dirs[] = $status->path->path(); + } + } + + return $dirs; + } + + public function runMigrate() : void + { + /** @var Command $command */ + $command = $this->container()->get('flow.postgresql.command.migrate'); + $tester = new CommandTester($command); + $tester->setInputs(['yes']); + $tester->execute([]); + } + + public function shutdown() : void + { + $this->symfonyContext->shutdown(); + + $client = PgSqlClient::connect((new DsnParser())->parse($this->testDsn)); + $client->execute('DROP TABLE IF EXISTS test_users, flow_migrations_test, flow_sql_test CASCADE'); + $client->close(); + + $this->filesystem->rm(path($this->migrationsDir)); + } + + public function tableExists(string $table, string $schema = 'public') : bool + { + $client = PgSqlClient::connect((new DsnParser())->parse($this->testDsn)); + $result = $client->fetch('SELECT 1 FROM information_schema.tables WHERE table_schema = $1 AND table_name = $2', [$schema, $table]); + $client->close(); + + return $result !== null; + } + + public function tableExistsInDatabase(string $database, string $table, string $schema = 'public') : bool + { + $targetDsn = \preg_replace('#/[^/?]+(\?|$)#', '/' . $database . '$1', $this->testDsn); + $client = PgSqlClient::connect((new DsnParser())->parse($targetDsn)); + $result = $client->fetch('SELECT 1 FROM information_schema.tables WHERE table_schema = $1 AND table_name = $2', [$schema, $table]); + $client->close(); + + return $result !== null; + } +} diff --git a/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/Command/CreateDatabaseCommandTest.php b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/Command/CreateDatabaseCommandTest.php new file mode 100644 index 0000000000..7144bf6a8c --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/Command/CreateDatabaseCommandTest.php @@ -0,0 +1,78 @@ +createDatabase($testDbName); + $context->bootForDatabaseManagement($testDbName); + + /** @var Command $command */ + $command = $context->container()->get('flow.postgresql.command.database_create'); + $tester = new CommandTester($command); + $tester->execute([]); + + self::assertSame(Command::FAILURE, $tester->getStatusCode()); + self::assertStringContainsString('already exists', $tester->getDisplay()); + } finally { + $context->dropDatabase($testDbName); + $context->shutdown(); + } + } + + public function test_create_with_if_not_exists_succeeds_when_database_already_exists() : void + { + $context = new CommandTestContext(); + $testDbName = 'flow_test_create_' . \bin2hex(\random_bytes(4)); + + try { + $context->createDatabase($testDbName); + $context->bootForDatabaseManagement($testDbName); + + /** @var Command $command */ + $command = $context->container()->get('flow.postgresql.command.database_create'); + $tester = new CommandTester($command); + $tester->execute(['--if-not-exists' => true]); + + self::assertSame(Command::SUCCESS, $tester->getStatusCode()); + self::assertTrue($context->databaseExists($testDbName)); + } finally { + $context->dropDatabase($testDbName); + $context->shutdown(); + } + } + + public function test_creates_database() : void + { + $context = new CommandTestContext(); + $testDbName = 'flow_test_create_' . \bin2hex(\random_bytes(4)); + + try { + $context->bootForDatabaseManagement($testDbName); + + /** @var Command $command */ + $command = $context->container()->get('flow.postgresql.command.database_create'); + $tester = new CommandTester($command); + $tester->execute([]); + + self::assertSame(Command::SUCCESS, $tester->getStatusCode()); + self::assertStringContainsString($testDbName, $tester->getDisplay()); + self::assertTrue($context->databaseExists($testDbName)); + } finally { + $context->dropDatabase($testDbName); + $context->shutdown(); + } + } +} diff --git a/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/Command/CurrentCommandTest.php b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/Command/CurrentCommandTest.php new file mode 100644 index 0000000000..e97662c874 --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/Command/CurrentCommandTest.php @@ -0,0 +1,27 @@ +context->generateDiffMigration(); + $this->context->runMigrate(); + + /** @var Command $command */ + $command = $this->context->container()->get('flow.postgresql.command.current'); + $tester = new CommandTester($command); + $tester->execute([]); + + self::assertSame(Command::SUCCESS, $tester->getStatusCode()); + self::assertStringContainsString($version, $tester->getDisplay()); + self::assertTrue($this->context->tableExists('flow_migrations_test')); + self::assertTrue($this->context->tableExists('test_users')); + } +} diff --git a/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/Command/DiffCommandTest.php b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/Command/DiffCommandTest.php new file mode 100644 index 0000000000..36939896d7 --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/Command/DiffCommandTest.php @@ -0,0 +1,38 @@ +context->container()->get('flow.postgresql.command.diff'); + $tester = new CommandTester($command); + $tester->execute(['name' => 'create_test_users']); + + self::assertSame(Command::SUCCESS, $tester->getStatusCode()); + self::assertStringContainsString('Generated migration:', $tester->getDisplay()); + + $dirs = $this->context->migrationDirs('*_create_test_users'); + self::assertCount(1, $dirs); + + $migrationDir = $dirs[0]; + self::assertTrue($this->context->fileExists($migrationDir . '/migration.php')); + self::assertTrue($this->context->fileExists($migrationDir . '/rollback.php')); + + $migrationContent = $this->context->fileContent($migrationDir . '/migration.php'); + self::assertStringContainsString('CREATE TABLE', $migrationContent); + self::assertStringContainsString('test_users', $migrationContent); + self::assertStringContainsString('implements Migration', $migrationContent); + + $rollbackContent = $this->context->fileContent($migrationDir . '/rollback.php'); + self::assertStringContainsString('DROP TABLE', $rollbackContent); + self::assertStringContainsString('implements Rollback', $rollbackContent); + } +} diff --git a/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/Command/DropDatabaseCommandTest.php b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/Command/DropDatabaseCommandTest.php new file mode 100644 index 0000000000..0be98c1353 --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/Command/DropDatabaseCommandTest.php @@ -0,0 +1,102 @@ +bootForDatabaseManagement($testDbName); + + /** @var Command $command */ + $command = $context->container()->get('flow.postgresql.command.database_drop'); + $tester = new CommandTester($command); + $tester->execute([]); + + self::assertSame(Command::FAILURE, $tester->getStatusCode()); + self::assertStringContainsString('--force', $tester->getDisplay()); + } finally { + $context->shutdown(); + } + } + + public function test_drop_with_if_exists_succeeds_when_database_missing() : void + { + $context = new CommandTestContext(); + $testDbName = 'flow_test_drop_nonexistent_' . \bin2hex(\random_bytes(4)); + + try { + self::assertFalse($context->databaseExists($testDbName)); + + $context->bootForDatabaseManagement($testDbName); + + /** @var Command $command */ + $command = $context->container()->get('flow.postgresql.command.database_drop'); + $tester = new CommandTester($command); + $tester->execute(['--force' => true, '--if-exists' => true]); + + self::assertSame(Command::SUCCESS, $tester->getStatusCode()); + } finally { + $context->shutdown(); + } + } + + public function test_drops_database() : void + { + $context = new CommandTestContext(); + $testDbName = 'flow_test_drop_' . \bin2hex(\random_bytes(4)); + + try { + $context->createDatabase($testDbName); + self::assertTrue($context->databaseExists($testDbName)); + + $context->bootForDatabaseManagement($testDbName); + + /** @var Command $command */ + $command = $context->container()->get('flow.postgresql.command.database_drop'); + $tester = new CommandTester($command); + $tester->execute(['--force' => true]); + + self::assertSame(Command::SUCCESS, $tester->getStatusCode()); + self::assertStringContainsString($testDbName, $tester->getDisplay()); + self::assertFalse($context->databaseExists($testDbName)); + } finally { + $context->dropDatabase($testDbName); + $context->shutdown(); + } + } + + public function test_drops_postgres_database() : void + { + $context = new CommandTestContext(); + $testDbName = 'flow_test_postgres_drop_' . \bin2hex(\random_bytes(4)); + + try { + $context->createDatabase($testDbName); + self::assertTrue($context->databaseExists($testDbName)); + + $context->bootForDatabaseManagement($testDbName); + + /** @var Command $command */ + $command = $context->container()->get('flow.postgresql.command.database_drop'); + $tester = new CommandTester($command); + $tester->execute(['--force' => true]); + + self::assertSame(Command::SUCCESS, $tester->getStatusCode()); + self::assertFalse($context->databaseExists($testDbName)); + } finally { + $context->dropDatabase($testDbName); + $context->shutdown(); + } + } +} diff --git a/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/Command/ExecuteCommandTest.php b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/Command/ExecuteCommandTest.php new file mode 100644 index 0000000000..8d1a5d559c --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/Command/ExecuteCommandTest.php @@ -0,0 +1,73 @@ +context->generateDiffMigration(); + + /** @var Command $command */ + $command = $this->context->container()->get('flow.postgresql.command.execute'); + $tester = new CommandTester($command); + $tester->setInputs(['no']); + $tester->execute(['version' => $version]); + + self::assertSame(Command::SUCCESS, $tester->getStatusCode()); + self::assertStringContainsString('cancelled', $tester->getDisplay()); + self::assertFalse($this->context->tableExists('test_users')); + } + + public function test_execute_skips_confirm_in_non_interactive_mode() : void + { + $version = $this->context->generateDiffMigration(); + + /** @var Command $command */ + $command = $this->context->container()->get('flow.postgresql.command.execute'); + $tester = new CommandTester($command); + $tester->execute(['version' => $version], ['interactive' => false]); + + self::assertSame(Command::SUCCESS, $tester->getStatusCode()); + self::assertTrue($this->context->tableExists('test_users')); + } + + public function test_executes_migration_down() : void + { + $version = $this->context->generateDiffMigration(); + $this->context->runMigrate(); + + self::assertTrue($this->context->tableExists('test_users')); + + /** @var Command $command */ + $command = $this->context->container()->get('flow.postgresql.command.execute'); + $tester = new CommandTester($command); + $tester->setInputs(['yes']); + $tester->execute(['version' => $version, '--down' => true]); + + self::assertSame(Command::SUCCESS, $tester->getStatusCode()); + self::assertStringContainsString('DOWN', $tester->getDisplay()); + self::assertFalse($this->context->tableExists('test_users')); + } + + public function test_executes_migration_up() : void + { + $version = $this->context->generateDiffMigration(); + + /** @var Command $command */ + $command = $this->context->container()->get('flow.postgresql.command.execute'); + $tester = new CommandTester($command); + $tester->setInputs(['yes']); + $tester->execute(['version' => $version, '--up' => true]); + + self::assertSame(Command::SUCCESS, $tester->getStatusCode()); + self::assertStringContainsString('UP', $tester->getDisplay()); + self::assertStringContainsString($version, $tester->getDisplay()); + self::assertTrue($this->context->tableExists('test_users')); + } +} diff --git a/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/Command/FullLifecycleTest.php b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/Command/FullLifecycleTest.php new file mode 100644 index 0000000000..c2bb3bfd0b --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/Command/FullLifecycleTest.php @@ -0,0 +1,88 @@ +createDatabase($testDbName); + self::assertTrue($context->databaseExists($testDbName)); + + $context->dropDatabase($testDbName); + self::assertFalse($context->databaseExists($testDbName)); + + $context->createDatabase($testDbName); + self::assertTrue($context->databaseExists($testDbName)); + + $context->bootWithMigrationsForDatabase($testDbName); + + $diffCommand = $context->container()->get('flow.postgresql.command.diff'); + $tester = new CommandTester($diffCommand); + $tester->execute(['name' => 'initial_schema', '--from-empty-schema' => true]); + self::assertSame(Command::SUCCESS, $tester->getStatusCode()); + self::assertStringContainsString('Generated migration', $tester->getDisplay()); + + $migrateCommand = $context->container()->get('flow.postgresql.command.migrate'); + $tester = new CommandTester($migrateCommand); + $tester->setInputs(['yes']); + $tester->execute([]); + self::assertSame(Command::SUCCESS, $tester->getStatusCode(), $tester->getDisplay()); + self::assertStringContainsString('UP', $tester->getDisplay()); + self::assertTrue($context->tableExistsInDatabase($testDbName, 'test_users')); + + $tester = new CommandTester($migrateCommand); + $tester->setInputs(['yes']); + $tester->execute(['version' => 'prev']); + self::assertSame(Command::SUCCESS, $tester->getStatusCode()); + self::assertStringContainsString('DOWN', $tester->getDisplay()); + self::assertFalse($context->tableExistsInDatabase($testDbName, 'test_users')); + + $tester = new CommandTester($migrateCommand); + $tester->setInputs(['yes']); + $tester->execute(['version' => 'next']); + self::assertSame(Command::SUCCESS, $tester->getStatusCode()); + self::assertStringContainsString('UP', $tester->getDisplay()); + self::assertTrue($context->tableExistsInDatabase($testDbName, 'test_users')); + + $tester = new CommandTester($migrateCommand); + $tester->execute([]); + self::assertSame(Command::SUCCESS, $tester->getStatusCode()); + self::assertStringContainsString('Already up to date', $tester->getDisplay()); + } finally { + $context->dropDatabase($testDbName); + $context->shutdown(); + } + } + + public function test_migrate_with_no_migrations_available() : void + { + $context = new CommandTestContext(); + $testDbName = 'flow_test_empty_' . \bin2hex(\random_bytes(4)); + + try { + $context->createDatabase($testDbName); + $context->bootWithMigrationsForDatabase($testDbName); + + $migrateCommand = $context->container()->get('flow.postgresql.command.migrate'); + $tester = new CommandTester($migrateCommand); + $tester->execute([]); + + self::assertSame(Command::SUCCESS, $tester->getStatusCode()); + self::assertStringContainsString('No migrations found', $tester->getDisplay()); + } finally { + $context->dropDatabase($testDbName); + $context->shutdown(); + } + } +} diff --git a/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/Command/GenerateCommandTest.php b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/Command/GenerateCommandTest.php new file mode 100644 index 0000000000..7a71fbdd97 --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/Command/GenerateCommandTest.php @@ -0,0 +1,29 @@ +context->container()->get('flow.postgresql.command.generate'); + $tester = new CommandTester($command); + $tester->execute(['name' => 'add_email_index']); + + self::assertSame(Command::SUCCESS, $tester->getStatusCode()); + self::assertStringContainsString('Generated migration:', $tester->getDisplay()); + + $dirs = $this->context->migrationDirs('*_add_email_index'); + self::assertCount(1, $dirs); + self::assertTrue($this->context->fileExists($dirs[0] . '/migration.php')); + self::assertTrue($this->context->fileExists($dirs[0] . '/rollback.php')); + self::assertStringContainsString('implements Migration', $this->context->fileContent($dirs[0] . '/migration.php')); + self::assertStringContainsString('implements Rollback', $this->context->fileContent($dirs[0] . '/rollback.php')); + } +} diff --git a/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/Command/LatestCommandTest.php b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/Command/LatestCommandTest.php new file mode 100644 index 0000000000..e246001733 --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/Command/LatestCommandTest.php @@ -0,0 +1,24 @@ +context->generateDiffMigration(); + + /** @var Command $command */ + $command = $this->context->container()->get('flow.postgresql.command.latest'); + $tester = new CommandTester($command); + $tester->execute([]); + + self::assertSame(Command::SUCCESS, $tester->getStatusCode()); + self::assertStringContainsString($version, $tester->getDisplay()); + } +} diff --git a/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/Command/ListCommandTest.php b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/Command/ListCommandTest.php new file mode 100644 index 0000000000..94541adb47 --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/Command/ListCommandTest.php @@ -0,0 +1,25 @@ +context->generateDiffMigration(); + + /** @var Command $command */ + $command = $this->context->container()->get('flow.postgresql.command.list'); + $tester = new CommandTester($command); + $tester->execute([]); + + self::assertSame(Command::SUCCESS, $tester->getStatusCode()); + self::assertStringContainsString('PENDING', $tester->getDisplay()); + self::assertStringContainsString('create_test_users', $tester->getDisplay()); + } +} diff --git a/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/Command/MigrateCommandTest.php b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/Command/MigrateCommandTest.php new file mode 100644 index 0000000000..0fc1768bfb --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/Command/MigrateCommandTest.php @@ -0,0 +1,136 @@ +context->generateDiffMigration(); + + /** @var Command $command */ + $command = $this->context->container()->get('flow.postgresql.command.migrate'); + $tester = new CommandTester($command); + $tester->setInputs(['no']); + $tester->execute([]); + + self::assertSame(Command::SUCCESS, $tester->getStatusCode()); + self::assertStringContainsString('cancelled', $tester->getDisplay()); + self::assertFalse($this->context->tableExists('test_users')); + } + + public function test_migrate_dry_run_does_not_apply_changes() : void + { + $this->context->generateDiffMigration(); + + /** @var Command $command */ + $command = $this->context->container()->get('flow.postgresql.command.migrate'); + $tester = new CommandTester($command); + $tester->setInputs(['yes']); + $tester->execute(['--dry-run' => true]); + + self::assertSame(Command::SUCCESS, $tester->getStatusCode()); + self::assertStringContainsString('Dry run completed', $tester->getDisplay()); + self::assertFalse($this->context->tableExists('test_users')); + } + + public function test_migrate_first_rolls_back_to_first_version() : void + { + $this->context->generateDiffMigration(); + $this->context->runMigrate(); + + self::assertTrue($this->context->tableExists('test_users')); + + /** @var Command $command */ + $command = $this->context->container()->get('flow.postgresql.command.migrate'); + $tester = new CommandTester($command); + $tester->setInputs(['yes']); + $tester->execute(['version' => 'first']); + + self::assertSame(Command::SUCCESS, $tester->getStatusCode()); + self::assertStringContainsString('Already up to date', $tester->getDisplay()); + } + + public function test_migrate_latest_applies_all_pending() : void + { + $this->context->generateDiffMigration(); + + /** @var Command $command */ + $command = $this->context->container()->get('flow.postgresql.command.migrate'); + $tester = new CommandTester($command); + $tester->setInputs(['yes']); + $tester->execute([]); + + self::assertSame(Command::SUCCESS, $tester->getStatusCode()); + self::assertStringContainsString('UP', $tester->getDisplay()); + self::assertTrue($this->context->tableExists('test_users')); + self::assertTrue($this->context->tableExists('flow_migrations_test')); + } + + public function test_migrate_latest_shows_up_to_date_when_nothing_pending() : void + { + $this->context->generateDiffMigration(); + $this->context->runMigrate(); + + /** @var Command $command */ + $command = $this->context->container()->get('flow.postgresql.command.migrate'); + $tester = new CommandTester($command); + $tester->setInputs(['yes']); + $tester->execute([]); + + self::assertSame(Command::SUCCESS, $tester->getStatusCode()); + self::assertStringContainsString('Already up to date', $tester->getDisplay()); + } + + public function test_migrate_next_applies_one_step() : void + { + $this->context->generateDiffMigration(); + + /** @var Command $command */ + $command = $this->context->container()->get('flow.postgresql.command.migrate'); + $tester = new CommandTester($command); + $tester->setInputs(['yes']); + $tester->execute(['version' => 'next']); + + self::assertSame(Command::SUCCESS, $tester->getStatusCode()); + self::assertStringContainsString('UP', $tester->getDisplay()); + self::assertTrue($this->context->tableExists('test_users')); + } + + public function test_migrate_prev_rolls_back_last_migration() : void + { + $this->context->generateDiffMigration(); + $this->context->runMigrate(); + + self::assertTrue($this->context->tableExists('test_users')); + + /** @var Command $command */ + $command = $this->context->container()->get('flow.postgresql.command.migrate'); + $tester = new CommandTester($command); + $tester->setInputs(['yes']); + $tester->execute(['version' => 'prev']); + + self::assertSame(Command::SUCCESS, $tester->getStatusCode()); + self::assertStringContainsString('DOWN', $tester->getDisplay()); + self::assertFalse($this->context->tableExists('test_users')); + } + + public function test_migrate_skips_confirm_in_non_interactive_mode() : void + { + $this->context->generateDiffMigration(); + + /** @var Command $command */ + $command = $this->context->container()->get('flow.postgresql.command.migrate'); + $tester = new CommandTester($command); + $tester->execute([], ['interactive' => false]); + + self::assertSame(Command::SUCCESS, $tester->getStatusCode()); + self::assertStringContainsString('UP', $tester->getDisplay()); + self::assertTrue($this->context->tableExists('test_users')); + } +} diff --git a/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/Command/RunSqlCommandTest.php b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/Command/RunSqlCommandTest.php new file mode 100644 index 0000000000..0e7ed3641c --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/Command/RunSqlCommandTest.php @@ -0,0 +1,36 @@ +context->container()->get('flow.postgresql.command.sql_run'); + $tester = new CommandTester($command); + $tester->execute(['sql' => 'CREATE TABLE flow_sql_test (id SERIAL PRIMARY KEY, name TEXT NOT NULL)']); + + self::assertSame(Command::SUCCESS, $tester->getStatusCode()); + self::assertTrue($this->context->tableExists('flow_sql_test')); + } + + public function test_runs_select_query_and_returns_data() : void + { + /** @var Command $command */ + $command = $this->context->container()->get('flow.postgresql.command.sql_run'); + $tester = new CommandTester($command); + $tester->execute(['sql' => "SELECT 1 AS result, 'hello' AS greeting"]); + + self::assertSame(Command::SUCCESS, $tester->getStatusCode()); + self::assertStringContainsString('result', $tester->getDisplay()); + self::assertStringContainsString('greeting', $tester->getDisplay()); + self::assertStringContainsString('hello', $tester->getDisplay()); + self::assertStringContainsString('1 row(s) returned', $tester->getDisplay()); + } +} diff --git a/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/Command/StatusCommandTest.php b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/Command/StatusCommandTest.php new file mode 100644 index 0000000000..45f7cca2a4 --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/Command/StatusCommandTest.php @@ -0,0 +1,27 @@ +context->generateDiffMigration(); + + /** @var Command $command */ + $command = $this->context->container()->get('flow.postgresql.command.status'); + $tester = new CommandTester($command); + $tester->execute([]); + + self::assertSame(Command::SUCCESS, $tester->getStatusCode()); + $display = $tester->getDisplay(); + self::assertStringContainsString('Total migrations', $display); + self::assertStringContainsString('Pending', $display); + self::assertStringContainsString('pending', $display); + } +} diff --git a/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/Command/UpToDateCommandTest.php b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/Command/UpToDateCommandTest.php new file mode 100644 index 0000000000..f7fc5227cc --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/Command/UpToDateCommandTest.php @@ -0,0 +1,38 @@ +context->generateDiffMigration(); + + /** @var Command $command */ + $command = $this->context->container()->get('flow.postgresql.command.up_to_date'); + $tester = new CommandTester($command); + $tester->execute([]); + + self::assertSame(Command::FAILURE, $tester->getStatusCode()); + self::assertStringContainsString('1 pending', $tester->getDisplay()); + } + + public function test_returns_success_when_up_to_date() : void + { + $this->context->generateDiffMigration(); + $this->context->runMigrate(); + + /** @var Command $command */ + $command = $this->context->container()->get('flow.postgresql.command.up_to_date'); + $tester = new CommandTester($command); + $tester->execute([]); + + self::assertSame(Command::SUCCESS, $tester->getStatusCode()); + self::assertStringContainsString('up to date', $tester->getDisplay()); + } +} diff --git a/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/FlowPostgreSqlExtensionTest.php b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/FlowPostgreSqlExtensionTest.php new file mode 100644 index 0000000000..7c789d54bd --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/FlowPostgreSqlExtensionTest.php @@ -0,0 +1,638 @@ +bootKernel([ + 'config' => static function (TestKernel $kernel) : void { + $kernel->addTestContainerConfigurator(static function (ContainerBuilder $container) : void { + $container->register('flow.postgresql.default.client', SpyClient::class)->setPublic(true); + $container->register(AttributeTestCatalogProvider::class, AttributeTestCatalogProvider::class) + ->setAutoconfigured(true) + ->setPublic(true); + }); + $kernel->addTestExtensionConfig('flow_postgresql', [ + 'connections' => [ + 'default' => [ + 'dsn' => 'postgresql://postgres:postgres@localhost:5432/postgres', + ], + ], + 'migrations' => [ + 'enabled' => true, + 'directory' => '/tmp/test_migrations', + 'namespace' => 'App\\Migrations', + ], + ]); + }, + ]); + + self::assertTrue($this->getContainer()->has('flow.postgresql.migrations.catalog_provider')); + self::assertInstanceOf(ChainCatalogProvider::class, $this->getContainer()->get('flow.postgresql.migrations.catalog_provider')); + + $catalog = $this->getContainer()->get('flow.postgresql.migrations.catalog_provider')->get(); + self::assertTrue($catalog->get('public')->hasTable('attribute_test')); + } + + public function test_catalog_providers_with_inline_catalog() : void + { + $this->bootKernel([ + 'config' => static function (TestKernel $kernel) : void { + $kernel->addTestContainerConfigurator(static function (ContainerBuilder $container) : void { + $container->register('flow.postgresql.default.client', SpyClient::class)->setPublic(true); + }); + $kernel->addTestExtensionConfig('flow_postgresql', [ + 'connections' => [ + 'default' => [ + 'dsn' => 'postgresql://postgres:postgres@localhost:5432/postgres', + ], + ], + 'migrations' => [ + 'enabled' => true, + 'directory' => '/tmp/test_migrations', + 'namespace' => 'App\\Migrations', + ], + 'catalog_providers' => [ + [ + 'catalog' => [ + 'schemas' => [ + [ + 'name' => 'public', + 'tables' => [ + [ + 'name' => 'users', + 'columns' => [ + ['name' => 'id', 'type' => ['name' => 'int4', 'schema' => 'pg_catalog'], 'nullable' => false], + ], + ], + ], + ], + ], + ], + ], + ], + ]); + }, + ]); + + self::assertTrue($this->getContainer()->has('flow.postgresql.migrations.catalog_provider')); + self::assertInstanceOf(ChainCatalogProvider::class, $this->getContainer()->get('flow.postgresql.migrations.catalog_provider')); + + $catalog = $this->getContainer()->get('flow.postgresql.migrations.catalog_provider')->get(); + self::assertSame(['public'], $catalog->names()); + self::assertTrue($catalog->get('public')->hasTable('users')); + } + + public function test_catalog_providers_with_service_reference() : void + { + $this->bootKernel([ + 'config' => static function (TestKernel $kernel) : void { + $kernel->addTestContainerConfigurator(static function (ContainerBuilder $container) : void { + $container->register('flow.postgresql.default.client', SpyClient::class)->setPublic(true); + $catalogDef = new Definition(Catalog::class, [[]]); + $container->register('test.catalog_provider', FakeCatalogProvider::class) + ->addArgument($catalogDef) + ->setPublic(true); + }); + $kernel->addTestExtensionConfig('flow_postgresql', [ + 'connections' => [ + 'default' => [ + 'dsn' => 'postgresql://postgres:postgres@localhost:5432/postgres', + ], + ], + 'migrations' => [ + 'enabled' => true, + 'directory' => '/tmp/test_migrations', + 'namespace' => 'App\\Migrations', + ], + 'catalog_providers' => [ + ['catalog_provider_id' => 'test.catalog_provider'], + ], + ]); + }, + ]); + + self::assertTrue($this->getContainer()->has('flow.postgresql.migrations.catalog_provider')); + self::assertInstanceOf(ChainCatalogProvider::class, $this->getContainer()->get('flow.postgresql.migrations.catalog_provider')); + } + + public function test_class_aliases_for_migration_services() : void + { + $this->bootKernel([ + 'config' => static function (TestKernel $kernel) : void { + $kernel->addTestContainerConfigurator(static function (ContainerBuilder $container) : void { + $container->register('flow.postgresql.default.client', SpyClient::class)->setPublic(true); + $catalogDef = new Definition(Catalog::class, [[]]); + $container->register('test.catalog_provider', FakeCatalogProvider::class) + ->addArgument($catalogDef) + ->setPublic(true); + }); + $kernel->addTestExtensionConfig('flow_postgresql', [ + 'connections' => [ + 'default' => [ + 'dsn' => 'postgresql://postgres:postgres@localhost:5432/postgres', + ], + ], + 'migrations' => [ + 'enabled' => true, + 'directory' => '/tmp/test_migrations', + 'namespace' => 'App\\Migrations', + ], + 'catalog_providers' => [ + ['catalog_provider_id' => 'test.catalog_provider'], + ], + ]); + }, + ]); + + self::assertTrue($this->getContainer()->has(Migrator::class)); + self::assertTrue($this->getContainer()->has(MigrationStore::class)); + self::assertTrue($this->getContainer()->has(MigrationsFactory::class)); + self::assertTrue($this->getContainer()->has(MigrationsConfiguration::class)); + self::assertTrue($this->getContainer()->has(MigrationRepository::class)); + self::assertTrue($this->getContainer()->has(MigrationExecutor::class)); + self::assertTrue($this->getContainer()->has(VersionResolver::class)); + self::assertTrue($this->getContainer()->has(MigrationGenerator::class)); + self::assertTrue($this->getContainer()->has(DiffMigrationGenerator::class)); + } + + public function test_client_with_telemetry_creates_default_clock_when_not_specified() : void + { + $this->bootKernel([ + 'config' => static function (TestKernel $kernel) : void { + $kernel->addTestContainerConfigurator(static function (ContainerBuilder $container) : void { + $container->register('flow.postgresql.default.client', SpyClient::class)->setPublic(true); + $container->register('test.telemetry.factory', VoidTelemetryFactory::class); + $container->register('test.telemetry', Telemetry::class) + ->setFactory([new Reference('test.telemetry.factory'), 'create']) + ->setPublic(true); + }); + $kernel->addTestExtensionConfig('flow_postgresql', [ + 'connections' => [ + 'default' => [ + 'dsn' => 'postgresql://postgres:postgres@localhost:5432/postgres', + 'telemetry' => [ + 'service_id' => 'test.telemetry', + ], + ], + ], + ]); + }, + ]); + + self::assertInstanceOf(TraceableClient::class, $this->getContainer()->get('flow.postgresql.default.client')); + self::assertInstanceOf(SystemClock::class, $this->getContainer()->get('flow.postgresql.default.telemetry.clock')); + } + + public function test_client_with_telemetry_is_decorated_with_traceable_client() : void + { + $this->bootKernel([ + 'config' => static function (TestKernel $kernel) : void { + $kernel->addTestContainerConfigurator(static function (ContainerBuilder $container) : void { + $container->register('flow.postgresql.default.client', SpyClient::class)->setPublic(true); + $container->register('test.telemetry.factory', VoidTelemetryFactory::class); + $container->register('test.telemetry', Telemetry::class) + ->setFactory([new Reference('test.telemetry.factory'), 'create']) + ->setPublic(true); + }); + $kernel->addTestExtensionConfig('flow_postgresql', [ + 'connections' => [ + 'default' => [ + 'dsn' => 'postgresql://postgres:postgres@localhost:5432/postgres', + 'telemetry' => [ + 'service_id' => 'test.telemetry', + ], + ], + ], + ]); + }, + ]); + + self::assertInstanceOf(TraceableClient::class, $this->getContainer()->get('flow.postgresql.default.client')); + self::assertInstanceOf(TraceableClient::class, $this->getContainer()->get(Client::class)); + self::assertTrue($this->getContainer()->has('flow.postgresql.default.telemetry.options')); + self::assertTrue($this->getContainer()->has('flow.postgresql.default.telemetry.config')); + } + + public function test_client_with_telemetry_uses_custom_clock_service() : void + { + $this->bootKernel([ + 'config' => static function (TestKernel $kernel) : void { + $kernel->addTestContainerConfigurator(static function (ContainerBuilder $container) : void { + $container->register('flow.postgresql.default.client', SpyClient::class)->setPublic(true); + $container->register('test.telemetry.factory', VoidTelemetryFactory::class); + $container->register('test.telemetry', Telemetry::class) + ->setFactory([new Reference('test.telemetry.factory'), 'create']) + ->setPublic(true); + $container->register('test.clock', SystemClock::class)->setPublic(true); + }); + $kernel->addTestExtensionConfig('flow_postgresql', [ + 'connections' => [ + 'default' => [ + 'dsn' => 'postgresql://postgres:postgres@localhost:5432/postgres', + 'telemetry' => [ + 'service_id' => 'test.telemetry', + 'clock_service_id' => 'test.clock', + ], + ], + ], + ]); + }, + ]); + + self::assertInstanceOf(TraceableClient::class, $this->getContainer()->get('flow.postgresql.default.client')); + self::assertFalse($this->getContainer()->has('flow.postgresql.default.telemetry.clock')); + } + + public function test_client_without_telemetry_is_not_decorated() : void + { + $this->bootKernel([ + 'config' => static function (TestKernel $kernel) : void { + $kernel->addTestContainerConfigurator(static function (ContainerBuilder $container) : void { + $container->register('flow.postgresql.default.client', SpyClient::class)->setPublic(true); + }); + $kernel->addTestExtensionConfig('flow_postgresql', [ + 'connections' => [ + 'default' => [ + 'dsn' => 'postgresql://postgres:postgres@localhost:5432/postgres', + ], + ], + ]); + }, + ]); + + self::assertInstanceOf(SpyClient::class, $this->getContainer()->get('flow.postgresql.default.client')); + self::assertFalse($this->getContainer()->has('flow.postgresql.default.telemetry.options')); + self::assertFalse($this->getContainer()->has('flow.postgresql.default.telemetry.config')); + } + + public function test_connection_with_migrations_registers_migration_services() : void + { + $this->bootKernel([ + 'config' => static function (TestKernel $kernel) : void { + $kernel->addTestContainerConfigurator(static function (ContainerBuilder $container) : void { + $container->register('flow.postgresql.default.client', SpyClient::class)->setPublic(true); + $catalogDef = new Definition(Catalog::class, [[]]); + $container->register('test.catalog_provider', FakeCatalogProvider::class) + ->addArgument($catalogDef) + ->setPublic(true); + }); + $kernel->addTestExtensionConfig('flow_postgresql', [ + 'connections' => [ + 'default' => [ + 'dsn' => 'postgresql://postgres:postgres@localhost:5432/postgres', + ], + ], + 'migrations' => [ + 'enabled' => true, + 'directory' => '/tmp/test_migrations', + 'namespace' => 'App\\Migrations', + ], + 'catalog_providers' => [ + ['catalog_provider_id' => 'test.catalog_provider'], + ], + ]); + }, + ]); + + self::assertTrue($this->getContainer()->has('flow.postgresql.default.migrations.configuration')); + self::assertTrue($this->getContainer()->has('flow.postgresql.default.migrations.factory')); + self::assertTrue($this->getContainer()->has('flow.postgresql.default.migrations.migrator')); + self::assertTrue($this->getContainer()->has('flow.postgresql.default.migrations.store')); + self::assertTrue($this->getContainer()->has('flow.postgresql.default.migrations.repository')); + self::assertTrue($this->getContainer()->has('flow.postgresql.default.migrations.generator')); + self::assertTrue($this->getContainer()->has('flow.postgresql.default.migrations.diff_generator')); + self::assertTrue($this->getContainer()->has('flow.postgresql.default.migrations.version_resolver')); + } + + public function test_connection_without_migrations_has_no_migration_services() : void + { + $this->bootKernel([ + 'config' => static function (TestKernel $kernel) : void { + $kernel->addTestContainerConfigurator(static function (ContainerBuilder $container) : void { + $container->register('flow.postgresql.default.client', SpyClient::class)->setPublic(true); + }); + $kernel->addTestExtensionConfig('flow_postgresql', [ + 'connections' => [ + 'default' => [ + 'dsn' => 'postgresql://postgres:postgres@localhost:5432/postgres', + ], + ], + ]); + }, + ]); + + self::assertFalse($this->getContainer()->has('flow.postgresql.default.migrations.migrator')); + } + + public function test_database_commands_registered_for_any_connection() : void + { + $this->bootKernel([ + 'config' => static function (TestKernel $kernel) : void { + $kernel->addTestExtensionConfig('flow_postgresql', [ + 'connections' => [ + 'default' => [ + 'dsn' => 'postgresql://postgres:postgres@localhost:5432/postgres', + ], + ], + ]); + $kernel->addTestContainerConfigurator(static function (ContainerBuilder $container) : void { + $container->register('flow.postgresql.default.client', SpyClient::class)->setPublic(true); + }); + }, + ]); + + self::assertInstanceOf(CreateDatabaseCommand::class, $this->getContainer()->get('flow.postgresql.command.database_create')); + self::assertInstanceOf(DropDatabaseCommand::class, $this->getContainer()->get('flow.postgresql.command.database_drop')); + self::assertInstanceOf(RunSqlCommand::class, $this->getContainer()->get('flow.postgresql.command.sql_run')); + } + + public function test_first_connection_gets_class_aliases() : void + { + $this->bootKernel([ + 'config' => static function (TestKernel $kernel) : void { + $kernel->addTestContainerConfigurator(static function (ContainerBuilder $container) : void { + $container->register('flow.postgresql.default.client', SpyClient::class)->setPublic(true); + $container->register('flow.postgresql.reporting.client', SpyClient::class)->setPublic(true); + }); + $kernel->addTestExtensionConfig('flow_postgresql', [ + 'connections' => [ + 'default' => [ + 'dsn' => 'postgresql://postgres:postgres@localhost:5432/postgres', + ], + 'reporting' => [ + 'dsn' => 'postgresql://postgres:postgres@localhost:5432/reporting', + ], + ], + ]); + }, + ]); + + self::assertInstanceOf(SpyClient::class, $this->getContainer()->get(Client::class)); + } + + public function test_migration_commands_registered_when_migrations_enabled() : void + { + $this->bootKernel([ + 'config' => static function (TestKernel $kernel) : void { + $kernel->addTestContainerConfigurator(static function (ContainerBuilder $container) : void { + $container->register('flow.postgresql.default.client', SpyClient::class)->setPublic(true); + $catalogDef = new Definition(Catalog::class, [[]]); + $container->register('test.catalog_provider', FakeCatalogProvider::class) + ->addArgument($catalogDef) + ->setPublic(true); + }); + $kernel->addTestExtensionConfig('flow_postgresql', [ + 'connections' => [ + 'default' => [ + 'dsn' => 'postgresql://postgres:postgres@localhost:5432/postgres', + ], + ], + 'migrations' => [ + 'enabled' => true, + 'directory' => '/tmp/test_migrations', + 'namespace' => 'App\\Migrations', + ], + 'catalog_providers' => [ + ['catalog_provider_id' => 'test.catalog_provider'], + ], + ]); + }, + ]); + + self::assertTrue($this->getContainer()->has('flow.postgresql.command.current')); + self::assertTrue($this->getContainer()->has('flow.postgresql.command.latest')); + self::assertTrue($this->getContainer()->has('flow.postgresql.command.status')); + self::assertTrue($this->getContainer()->has('flow.postgresql.command.list')); + self::assertTrue($this->getContainer()->has('flow.postgresql.command.migrate')); + self::assertTrue($this->getContainer()->has('flow.postgresql.command.execute')); + self::assertTrue($this->getContainer()->has('flow.postgresql.command.diff')); + } + + public function test_migration_configuration_values_propagated() : void + { + $this->bootKernel([ + 'config' => static function (TestKernel $kernel) : void { + $kernel->addTestContainerConfigurator(static function (ContainerBuilder $container) : void { + $container->register('flow.postgresql.default.client', SpyClient::class)->setPublic(true); + $catalogDef = new Definition(Catalog::class, [[]]); + $container->register('test.catalog_provider', FakeCatalogProvider::class) + ->addArgument($catalogDef) + ->setPublic(true); + }); + $kernel->addTestExtensionConfig('flow_postgresql', [ + 'connections' => [ + 'default' => [ + 'dsn' => 'postgresql://postgres:postgres@localhost:5432/postgres', + ], + ], + 'migrations' => [ + 'enabled' => true, + 'directory' => '/tmp/custom_migrations', + 'namespace' => 'Custom\\Migrations', + 'table_name' => 'custom_migrations_table', + 'table_schema' => 'custom_schema', + ], + 'catalog_providers' => [ + ['catalog_provider_id' => 'test.catalog_provider'], + ], + ]); + }, + ]); + + /** @var MigrationsConfiguration $configuration */ + $configuration = $this->getContainer()->get('flow.postgresql.default.migrations.configuration'); + + self::assertSame('/tmp/custom_migrations', $configuration->migrationsDirectory); + self::assertSame('Custom\\Migrations', $configuration->migrationsNamespace); + self::assertSame('custom_migrations_table', $configuration->tableName); + self::assertSame('custom_schema', $configuration->tableSchema); + } + + public function test_migration_generate_and_up_to_date_commands_registered() : void + { + $this->bootKernel([ + 'config' => static function (TestKernel $kernel) : void { + $kernel->addTestContainerConfigurator(static function (ContainerBuilder $container) : void { + $container->register('flow.postgresql.default.client', SpyClient::class)->setPublic(true); + $catalogDef = new Definition(Catalog::class, [[]]); + $container->register('test.catalog_provider', FakeCatalogProvider::class) + ->addArgument($catalogDef) + ->setPublic(true); + }); + $kernel->addTestExtensionConfig('flow_postgresql', [ + 'connections' => [ + 'default' => [ + 'dsn' => 'postgresql://postgres:postgres@localhost:5432/postgres', + ], + ], + 'migrations' => [ + 'enabled' => true, + 'directory' => '/tmp/test_migrations', + 'namespace' => 'App\\Migrations', + ], + 'catalog_providers' => [ + ['catalog_provider_id' => 'test.catalog_provider'], + ], + ]); + }, + ]); + + self::assertInstanceOf(GenerateCommand::class, $this->getContainer()->get('flow.postgresql.command.generate')); + self::assertInstanceOf(UpToDateCommand::class, $this->getContainer()->get('flow.postgresql.command.up_to_date')); + } + + public function test_multiple_connections_register_separate_clients() : void + { + $this->bootKernel([ + 'config' => static function (TestKernel $kernel) : void { + $kernel->addTestContainerConfigurator(static function (ContainerBuilder $container) : void { + $container->register('flow.postgresql.default.client', SpyClient::class)->setPublic(true); + $container->register('flow.postgresql.reporting.client', SpyClient::class)->setPublic(true); + }); + $kernel->addTestExtensionConfig('flow_postgresql', [ + 'connections' => [ + 'default' => [ + 'dsn' => 'postgresql://postgres:postgres@localhost:5432/postgres', + ], + 'reporting' => [ + 'dsn' => 'postgresql://postgres:postgres@localhost:5432/reporting', + ], + ], + ]); + }, + ]); + + self::assertTrue($this->getContainer()->has('flow.postgresql.default.client')); + self::assertTrue($this->getContainer()->has('flow.postgresql.reporting.client')); + self::assertInstanceOf(SpyClient::class, $this->getContainer()->get('flow.postgresql.default.client')); + self::assertInstanceOf(SpyClient::class, $this->getContainer()->get('flow.postgresql.reporting.client')); + } + + public function test_no_generate_command_without_migrations() : void + { + $this->bootKernel([ + 'config' => static function (TestKernel $kernel) : void { + $kernel->addTestExtensionConfig('flow_postgresql', [ + 'connections' => [ + 'default' => [ + 'dsn' => 'postgresql://postgres:postgres@localhost:5432/postgres', + ], + ], + ]); + $kernel->addTestContainerConfigurator(static function (ContainerBuilder $container) : void { + $container->register('flow.postgresql.default.client', SpyClient::class)->setPublic(true); + }); + }, + ]); + + self::assertFalse($this->getContainer()->has('flow.postgresql.command.generate')); + } + + public function test_no_migration_commands_when_no_migrations() : void + { + $this->bootKernel([ + 'config' => static function (TestKernel $kernel) : void { + $kernel->addTestContainerConfigurator(static function (ContainerBuilder $container) : void { + $container->register('flow.postgresql.default.client', SpyClient::class)->setPublic(true); + }); + $kernel->addTestExtensionConfig('flow_postgresql', [ + 'connections' => [ + 'default' => [ + 'dsn' => 'postgresql://postgres:postgres@localhost:5432/postgres', + ], + ], + ]); + }, + ]); + + self::assertFalse($this->getContainer()->has('flow.postgresql.command.current')); + self::assertFalse($this->getContainer()->has('flow.postgresql.command.latest')); + self::assertFalse($this->getContainer()->has('flow.postgresql.command.status')); + self::assertFalse($this->getContainer()->has('flow.postgresql.command.list')); + self::assertFalse($this->getContainer()->has('flow.postgresql.command.migrate')); + self::assertFalse($this->getContainer()->has('flow.postgresql.command.execute')); + self::assertFalse($this->getContainer()->has('flow.postgresql.command.diff')); + } + + public function test_single_connection_registers_client() : void + { + $this->bootKernel([ + 'config' => static function (TestKernel $kernel) : void { + $kernel->addTestContainerConfigurator(static function (ContainerBuilder $container) : void { + $container->register('flow.postgresql.default.client', SpyClient::class)->setPublic(true); + }); + $kernel->addTestExtensionConfig('flow_postgresql', [ + 'connections' => [ + 'default' => [ + 'dsn' => 'postgresql://postgres:postgres@localhost:5432/postgres', + ], + ], + ]); + }, + ]); + + self::assertInstanceOf(SpyClient::class, $this->getContainer()->get('flow.postgresql.default.client')); + self::assertInstanceOf(SpyClient::class, $this->getContainer()->get(Client::class)); + } + + public function test_telemetry_options_propagated_to_config() : void + { + $this->bootKernel([ + 'config' => static function (TestKernel $kernel) : void { + $kernel->addTestContainerConfigurator(static function (ContainerBuilder $container) : void { + $container->register('flow.postgresql.default.client', SpyClient::class)->setPublic(true); + $container->register('test.telemetry.factory', VoidTelemetryFactory::class); + $container->register('test.telemetry', Telemetry::class) + ->setFactory([new Reference('test.telemetry.factory'), 'create']) + ->setPublic(true); + }); + $kernel->addTestExtensionConfig('flow_postgresql', [ + 'connections' => [ + 'default' => [ + 'dsn' => 'postgresql://postgres:postgres@localhost:5432/postgres', + 'telemetry' => [ + 'service_id' => 'test.telemetry', + 'log_queries' => true, + 'include_parameters' => true, + 'max_query_length' => 500, + ], + ], + ], + ]); + }, + ]); + + /** @var PostgreSqlTelemetryOptions $options */ + $options = $this->getContainer()->get('flow.postgresql.default.telemetry.options'); + self::assertInstanceOf(PostgreSqlTelemetryOptions::class, $options); + self::assertTrue($options->logQueries); + self::assertTrue($options->includeParameters); + self::assertSame(500, $options->maxQueryLength); + self::assertTrue($options->traceQueries); + self::assertTrue($options->traceTransactions); + self::assertTrue($options->collectMetrics); + } +} diff --git a/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/KernelTestCase.php b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/KernelTestCase.php new file mode 100644 index 0000000000..b7d3eb9545 --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Integration/KernelTestCase.php @@ -0,0 +1,60 @@ +context = new SymfonyContext(); + } + + protected function tearDown() : void + { + $this->context->shutdown(); + } + + protected function addCommand(Application $application, Command $command) : void + { + /** @phpstan-ignore function.alreadyNarrowedType */ + if (\method_exists($application, 'addCommand')) { + $application->addCommand($command); + } else { + $application->add($command); + } + } + + /** + * @param array{config?: callable(TestKernel): void} $options + */ + protected function bootKernel(array $options = []) : TestKernel + { + return $this->context->bootKernel($options); + } + + protected function getContainer() : ContainerInterface + { + return $this->context->getContainer(); + } + + protected function getKernel() : TestKernel + { + return $this->context->getKernel(); + } + + protected function symfonyContext() : SymfonyContext + { + return $this->context; + } +} diff --git a/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/CatalogProvider/ArrayCatalogProviderTest.php b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/CatalogProvider/ArrayCatalogProviderTest.php new file mode 100644 index 0000000000..dc7b3ceabd --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/CatalogProvider/ArrayCatalogProviderTest.php @@ -0,0 +1,86 @@ +normalize()); + + $restored = $provider->get(); + + self::assertSame(['public'], $restored->names()); + self::assertTrue($restored->get('public')->hasTable('users')); + self::assertNotNull($restored->get('public')->table('users')->primaryKey); + self::assertSame('users_pkey', $restored->get('public')->table('users')->primaryKey->name); + self::assertCount(2, $restored->get('public')->table('users')->columns); + } + + public function test_creates_catalog_with_all_schema_objects() : void + { + $catalog = new Catalog([ + new Schema( + 'public', + tables: [ + new Table( + 'public', + 'users', + [new Column('id', ColumnType::integer(), false)], + primaryKey: new PrimaryKey(['id']), + indexes: [new Index('idx_id', ['id'], unique: true)], + uniqueConstraints: [new UniqueConstraint(['id'], 'uq_id')], + ), + ], + sequences: [new Sequence('users_id_seq')], + views: [new View('active_users', 'SELECT * FROM users')], + materializedViews: [new MaterializedView('user_stats', 'SELECT count(*) FROM users')], + functions: [new Func('get_user', 'text', ['integer'], 'sql', 'SELECT 1', volatility: FunctionVolatility::STABLE)], + procedures: [new Procedure('cleanup', [], 'sql', 'DELETE FROM logs')], + extensions: [new Extension('uuid-ossp', '1.1')], + ), + ]); + + $provider = new ArrayCatalogProvider($catalog->normalize()); + + $restored = $provider->get(); + + $schema = $restored->get('public'); + self::assertCount(1, $schema->tables); + self::assertCount(1, $schema->sequences); + self::assertCount(1, $schema->views); + self::assertCount(1, $schema->materializedViews); + self::assertCount(1, $schema->functions); + self::assertCount(1, $schema->procedures); + self::assertCount(1, $schema->extensions); + } + + public function test_creates_empty_catalog() : void + { + $provider = new ArrayCatalogProvider(['schemas' => []]); + + self::assertSame([], $provider->get()->all()); + } +} diff --git a/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/Command/CreateDatabaseCommandTest.php b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/Command/CreateDatabaseCommandTest.php new file mode 100644 index 0000000000..ab34a7c603 --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/Command/CreateDatabaseCommandTest.php @@ -0,0 +1,19 @@ +getName()); + } +} diff --git a/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/Command/CurrentCommandTest.php b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/Command/CurrentCommandTest.php new file mode 100644 index 0000000000..d78217d5e7 --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/Command/CurrentCommandTest.php @@ -0,0 +1,42 @@ +set('flow.postgresql.default.migrations.store', new FakeMigrationStore()); + + $tester = new CommandTester(new CurrentCommand($container, 'default')); + $tester->execute([]); + + self::assertStringContainsString('No migrations have been executed yet.', $tester->getDisplay()); + } + + public function test_shows_latest_version() : void + { + $store = new FakeMigrationStore(); + $store->initialize(); + $store->complete(Version::fromString('20260401120000'), 10); + $store->complete(Version::fromString('20260402100000'), 5); + + $container = new Container(); + $container->set('flow.postgresql.default.migrations.store', $store); + + $tester = new CommandTester(new CurrentCommand($container, 'default')); + $tester->execute([]); + + self::assertStringContainsString('20260402100000', $tester->getDisplay()); + } +} diff --git a/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/Command/DiffCommandTest.php b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/Command/DiffCommandTest.php new file mode 100644 index 0000000000..efc6a9ed2e --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/Command/DiffCommandTest.php @@ -0,0 +1,59 @@ +set('flow.postgresql.default.migrations.diff_generator', $diffGenerator); + $container->set('flow.postgresql.default.migrations.configuration', new Configuration(new SpyClient(), new FakeCatalogProvider(new Catalog([])), '/tmp/migrations', 'App\\Migrations')); + + $tester = new CommandTester(new DiffCommand($container, 'default')); + $tester->execute(['name' => 'schema_change']); + + self::assertSame(Command::FAILURE, $tester->getStatusCode()); + self::assertStringContainsString('No changes detected', $tester->getDisplay()); + } + + public function test_generates_diff() : void + { + $generator = new SpyMigrationGenerator(Version::fromString('20260401120000')); + $diffGenerator = new DiffMigrationGenerator( + new FakeCatalogProvider(new Catalog([])), + new FakeCatalogProvider(new Catalog([])), + CatalogComparator::create(), + $generator, + ); + + $container = new Container(); + $container->set('flow.postgresql.default.migrations.diff_generator', $diffGenerator); + $container->set('flow.postgresql.default.migrations.configuration', new Configuration(new SpyClient(), new FakeCatalogProvider(new Catalog([])), '/tmp/migrations', 'App\\Migrations')); + + $tester = new CommandTester(new DiffCommand($container, 'default')); + $tester->execute(['name' => 'schema_change', '--allow-empty-diff' => true]); + + self::assertStringContainsString('Generated migration: 20260401120000', $tester->getDisplay()); + } +} diff --git a/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/Command/DropDatabaseCommandTest.php b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/Command/DropDatabaseCommandTest.php new file mode 100644 index 0000000000..2fb7479984 --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/Command/DropDatabaseCommandTest.php @@ -0,0 +1,30 @@ +getName()); + } + + public function test_requires_force_flag() : void + { + $tester = new CommandTester(new DropDatabaseCommand(new Container(), 'default')); + $tester->execute([]); + + self::assertSame(Command::FAILURE, $tester->getStatusCode()); + self::assertStringContainsString('Use --force to proceed', $tester->getDisplay()); + } +} diff --git a/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/Command/ExecuteCommandTest.php b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/Command/ExecuteCommandTest.php new file mode 100644 index 0000000000..ff2d2b3a6a --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/Command/ExecuteCommandTest.php @@ -0,0 +1,73 @@ +set('flow.postgresql.default.migrations.migrator', new Migrator($repository, new FakeMigrationStore(), new SpyMigrationExecutor(), $client = new SpyClient(), new Configuration($client, new FakeCatalogProvider(new Catalog([])), '/tmp', 'App\\Migrations'))); + + $tester = new CommandTester(new ExecuteCommand($container, 'default')); + $tester->setInputs(['yes']); + $tester->execute(['version' => '20260401120000', '--dry-run' => true]); + + self::assertStringContainsString('Dry run completed.', $tester->getDisplay()); + } + + public function test_executes_migration_down() : void + { + $repository = new FakeMigrationRepository( + new AvailableMigration(Version::fromString('20260401120000'), 'create_users', new SpyMigration(), new SpyRollback()), + ); + + $store = new FakeMigrationStore(); + $store->initialize(); + $store->complete(Version::fromString('20260401120000'), 10); + + $container = new Container(); + $container->set('flow.postgresql.default.migrations.migrator', new Migrator($repository, $store, new SpyMigrationExecutor(), $client = new SpyClient(), new Configuration($client, new FakeCatalogProvider(new Catalog([])), '/tmp', 'App\\Migrations'))); + + $tester = new CommandTester(new ExecuteCommand($container, 'default')); + $tester->setInputs(['yes']); + $tester->execute(['version' => '20260401120000', '--down' => true]); + + $display = $tester->getDisplay(); + self::assertStringContainsString('DOWN', $display); + self::assertStringContainsString('20260401120000', $display); + } + + public function test_executes_single_migration() : void + { + $repository = new FakeMigrationRepository( + new AvailableMigration(Version::fromString('20260401120000'), 'create_users', new SpyMigration(), new SpyRollback()), + ); + + $container = new Container(); + $container->set('flow.postgresql.default.migrations.migrator', new Migrator($repository, new FakeMigrationStore(), new SpyMigrationExecutor(), $client = new SpyClient(), new Configuration($client, new FakeCatalogProvider(new Catalog([])), '/tmp', 'App\\Migrations'))); + + $tester = new CommandTester(new ExecuteCommand($container, 'default')); + $tester->setInputs(['yes']); + $tester->execute(['version' => '20260401120000']); + + $display = $tester->getDisplay(); + self::assertStringContainsString('UP', $display); + self::assertStringContainsString('20260401120000', $display); + } +} diff --git a/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/Command/GenerateCommandTest.php b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/Command/GenerateCommandTest.php new file mode 100644 index 0000000000..9d14a431e7 --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/Command/GenerateCommandTest.php @@ -0,0 +1,50 @@ +set('flow.postgresql.default.migrations.generator', $generator); + $container->set('flow.postgresql.default.migrations.configuration', new Configuration(new SpyClient(), new FakeCatalogProvider(new Catalog([])), '/tmp/migrations', 'App\\Migrations')); + + $tester = new CommandTester(new GenerateCommand($container, 'default')); + $tester->execute(['name' => 'add_email_index']); + + self::assertSame(0, $tester->getStatusCode()); + self::assertStringContainsString('20260401120000', $tester->getDisplay()); + self::assertSame('add_email_index', $generator->lastDataName); + } + + public function test_uses_connection_option() : void + { + $version = Version::fromString('20260402100000'); + $generator = new SpyMigrationGenerator($version); + + $container = new Container(); + $container->set('flow.postgresql.other.migrations.generator', $generator); + $container->set('flow.postgresql.other.migrations.configuration', new Configuration(new SpyClient(), new FakeCatalogProvider(new Catalog([])), '/tmp/migrations', 'App\\Migrations')); + + $tester = new CommandTester(new GenerateCommand($container, 'default')); + $tester->execute(['name' => 'create_table', '--connection' => 'other']); + + self::assertSame(0, $tester->getStatusCode()); + self::assertStringContainsString('20260402100000', $tester->getDisplay()); + self::assertSame('create_table', $generator->lastDataName); + } +} diff --git a/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/Command/LatestCommandTest.php b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/Command/LatestCommandTest.php new file mode 100644 index 0000000000..ba0772951f --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/Command/LatestCommandTest.php @@ -0,0 +1,54 @@ +set('flow.postgresql.default.migrations.migrator', new Migrator(new FakeMigrationRepository(), new FakeMigrationStore(), new SpyMigrationExecutor(), $client = new SpyClient(), new Configuration($client, new FakeCatalogProvider(new Catalog([])), '/tmp', 'App\\Migrations'))); + + $tester = new CommandTester(new LatestCommand($container, 'default')); + $tester->execute([]); + + self::assertStringContainsString('No migrations available.', $tester->getDisplay()); + } + + public function test_shows_latest_version_with_marker() : void + { + $store = new FakeMigrationStore(); + $store->initialize(); + $store->complete(Version::fromString('20260401120000'), 10); + + $repository = new FakeMigrationRepository( + new AvailableMigration(Version::fromString('20260401120000'), 'create_users', new SpyMigration(), new SpyRollback()), + new AvailableMigration(Version::fromString('20260402100000'), 'seed_data', new SpyMigration(), new SpyRollback()), + ); + + $container = new Container(); + $container->set('flow.postgresql.default.migrations.migrator', new Migrator($repository, $store, new SpyMigrationExecutor(), $client = new SpyClient(), new Configuration($client, new FakeCatalogProvider(new Catalog([])), '/tmp', 'App\\Migrations'))); + + $tester = new CommandTester(new LatestCommand($container, 'default')); + $tester->execute([]); + + $display = $tester->getDisplay(); + self::assertStringContainsString('20260401120000', $display); + self::assertStringContainsString('create_users', $display); + self::assertStringContainsString('20260402100000', $display); + self::assertStringContainsString('seed_data', $display); + self::assertStringContainsString('EXECUTED', $display); + self::assertStringContainsString('PENDING', $display); + } +} diff --git a/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/Command/ListCommandTest.php b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/Command/ListCommandTest.php new file mode 100644 index 0000000000..ef0dd1813c --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/Command/ListCommandTest.php @@ -0,0 +1,56 @@ +set('flow.postgresql.default.migrations.migrator', new Migrator(new FakeMigrationRepository(), new FakeMigrationStore(), new SpyMigrationExecutor(), $client = new SpyClient(), new Configuration($client, new FakeCatalogProvider(new Catalog([])), '/tmp', 'App\\Migrations'))); + + $tester = new CommandTester(new ListCommand($container, 'default')); + $tester->execute([]); + + self::assertStringContainsString('No migrations found', $tester->getDisplay()); + } + + public function test_lists_migrations_with_states() : void + { + $store = new FakeMigrationStore(); + $store->initialize(); + $store->complete(Version::fromString('20260401120000'), 10); + + $repository = new FakeMigrationRepository( + new AvailableMigration(Version::fromString('20260401120000'), 'create_users', new SpyMigration(), new SpyRollback()), + new AvailableMigration(Version::fromString('20260402100000'), 'seed_data', new SpyMigration(), new SpyRollback()), + ); + + $container = new Container(); + $container->set('flow.postgresql.default.migrations.migrator', new Migrator($repository, $store, new SpyMigrationExecutor(), $client = new SpyClient(), new Configuration($client, new FakeCatalogProvider(new Catalog([])), '/tmp', 'App\\Migrations'))); + + $tester = new CommandTester(new ListCommand($container, 'default')); + $tester->execute([]); + + $display = $tester->getDisplay(); + self::assertStringContainsString('EXECUTED', $display); + self::assertStringContainsString('20260401120000', $display); + self::assertStringContainsString('create_users', $display); + self::assertStringContainsString('PENDING', $display); + self::assertStringContainsString('20260402100000', $display); + self::assertStringContainsString('seed_data', $display); + self::assertStringContainsString('1 executed', $display); + self::assertStringContainsString('1 pending', $display); + } +} diff --git a/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/Command/MigrateCommandTest.php b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/Command/MigrateCommandTest.php new file mode 100644 index 0000000000..bacaec3ffa --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/Command/MigrateCommandTest.php @@ -0,0 +1,100 @@ +initialize(); + $store->complete(Version::fromString('20260401120000'), 10); + + $container = new Container(); + $container->set('flow.postgresql.other.migrations.migrator', new Migrator($repository, $store, new SpyMigrationExecutor(), $client = new SpyClient(), new Configuration($client, new FakeCatalogProvider(new Catalog([])), '/tmp', 'App\\Migrations'))); + $container->set('flow.postgresql.other.migrations.version_resolver', new VersionResolver($repository, $store)); + $container->set('flow.postgresql.other.migrations.configuration', new Configuration(new SpyClient(), new FakeCatalogProvider(new Catalog([])), '/tmp/migrations', 'App\\Migrations')); + + $tester = new CommandTester(new MigrateCommand($container, 'default')); + $tester->setInputs(['yes']); + $tester->execute(['--connection' => 'other']); + + self::assertStringContainsString('Already up to date.', $tester->getDisplay()); + } + + public function test_dry_run_note() : void + { + $repository = new FakeMigrationRepository( + new AvailableMigration(Version::fromString('20260401120000'), 'create_users', new SpyMigration(), new SpyRollback()), + ); + + $container = new Container(); + $container->set('flow.postgresql.default.migrations.migrator', new Migrator($repository, new FakeMigrationStore(), new SpyMigrationExecutor(), $client = new SpyClient(), new Configuration($client, new FakeCatalogProvider(new Catalog([])), '/tmp', 'App\\Migrations'))); + $container->set('flow.postgresql.default.migrations.version_resolver', new VersionResolver($repository, new FakeMigrationStore())); + $container->set('flow.postgresql.default.migrations.configuration', new Configuration(new SpyClient(), new FakeCatalogProvider(new Catalog([])), '/tmp/migrations', 'App\\Migrations')); + + $tester = new CommandTester(new MigrateCommand($container, 'default')); + $tester->setInputs(['yes']); + $tester->execute(['--dry-run' => true]); + + self::assertStringContainsString('Dry run completed.', $tester->getDisplay()); + } + + public function test_executes_pending_migrations() : void + { + $repository = new FakeMigrationRepository( + new AvailableMigration(Version::fromString('20260401120000'), 'create_users', new SpyMigration(), new SpyRollback()), + new AvailableMigration(Version::fromString('20260402100000'), 'seed_data', new SpyMigration(), new SpyRollback()), + ); + $store = new FakeMigrationStore(); + + $container = new Container(); + $container->set('flow.postgresql.default.migrations.migrator', new Migrator($repository, $store, new SpyMigrationExecutor(), $client = new SpyClient(), new Configuration($client, new FakeCatalogProvider(new Catalog([])), '/tmp', 'App\\Migrations'))); + $container->set('flow.postgresql.default.migrations.version_resolver', new VersionResolver($repository, $store)); + $container->set('flow.postgresql.default.migrations.configuration', new Configuration(new SpyClient(), new FakeCatalogProvider(new Catalog([])), '/tmp/migrations', 'App\\Migrations')); + + $tester = new CommandTester(new MigrateCommand($container, 'default')); + $tester->setInputs(['yes']); + $tester->execute([]); + + $display = $tester->getDisplay(); + self::assertStringContainsString('UP', $display); + self::assertStringContainsString('20260401120000', $display); + self::assertStringContainsString('20260402100000', $display); + } + + public function test_no_migrations_to_execute() : void + { + $repository = new FakeMigrationRepository( + new AvailableMigration(Version::fromString('20260401120000'), 'create_users', new SpyMigration(), new SpyRollback()), + ); + $store = new FakeMigrationStore(); + $store->initialize(); + $store->complete(Version::fromString('20260401120000'), 10); + + $container = new Container(); + $container->set('flow.postgresql.default.migrations.migrator', new Migrator($repository, $store, new SpyMigrationExecutor(), $client = new SpyClient(), new Configuration($client, new FakeCatalogProvider(new Catalog([])), '/tmp', 'App\\Migrations'))); + $container->set('flow.postgresql.default.migrations.version_resolver', new VersionResolver($repository, $store)); + $container->set('flow.postgresql.default.migrations.configuration', new Configuration(new SpyClient(), new FakeCatalogProvider(new Catalog([])), '/tmp/migrations', 'App\\Migrations')); + + $tester = new CommandTester(new MigrateCommand($container, 'default')); + $tester->setInputs(['yes']); + $tester->execute([]); + + self::assertStringContainsString('Already up to date.', $tester->getDisplay()); + } +} diff --git a/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/Command/RunSqlCommandTest.php b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/Command/RunSqlCommandTest.php new file mode 100644 index 0000000000..6c817e3869 --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/Command/RunSqlCommandTest.php @@ -0,0 +1,44 @@ +set('flow.postgresql.default.client', $client); + + $tester = new CommandTester(new RunSqlCommand($container, 'default')); + $tester->execute(['sql' => 'DELETE FROM users WHERE id = 1']); + + self::assertSame(Command::SUCCESS, $tester->getStatusCode()); + self::assertStringContainsString('0 row(s) affected.', $tester->getDisplay()); + self::assertSame('DELETE FROM users WHERE id = 1', $client->executedQueries[0]['sql']); + } + + public function test_uses_connection_option() : void + { + $client = new SpyClient(); + + $container = new Container(); + $container->set('flow.postgresql.other.client', $client); + + $tester = new CommandTester(new RunSqlCommand($container, 'default')); + $tester->execute(['sql' => 'UPDATE users SET active = true', '--connection' => 'other']); + + self::assertSame(Command::SUCCESS, $tester->getStatusCode()); + self::assertSame('UPDATE users SET active = true', $client->executedQueries[0]['sql']); + } +} diff --git a/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/Command/StatusCommandTest.php b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/Command/StatusCommandTest.php new file mode 100644 index 0000000000..bdd9428b75 --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/Command/StatusCommandTest.php @@ -0,0 +1,61 @@ +initialize(); + $store->complete(Version::fromString('20260401120000'), 10); + + $repository = new FakeMigrationRepository( + new AvailableMigration(Version::fromString('20260401120000'), 'create_users', new SpyMigration(), new SpyRollback()), + new AvailableMigration(Version::fromString('20260402100000'), 'seed_data', new SpyMigration(), new SpyRollback()), + new AvailableMigration(Version::fromString('20260403090000'), 'add_column', new SpyMigration(), null), + ); + + $container = new Container(); + $container->set('flow.postgresql.default.migrations.migrator', new Migrator($repository, $store, new SpyMigrationExecutor(), $client = new SpyClient(), new Configuration($client, new FakeCatalogProvider(new Catalog([])), '/tmp', 'App\\Migrations'))); + + $tester = new CommandTester(new StatusCommand($container, 'default')); + $tester->execute([]); + + $display = $tester->getDisplay(); + self::assertStringContainsString('3', $display); + self::assertStringContainsString('1', $display); + self::assertStringContainsString('2', $display); + self::assertStringContainsString('pending', $display); + } + + public function test_shows_success_when_all_executed() : void + { + $store = new FakeMigrationStore(); + $store->initialize(); + $store->complete(Version::fromString('20260401120000'), 10); + + $repository = new FakeMigrationRepository( + new AvailableMigration(Version::fromString('20260401120000'), 'create_users', new SpyMigration(), new SpyRollback()), + ); + + $container = new Container(); + $container->set('flow.postgresql.default.migrations.migrator', new Migrator($repository, $store, new SpyMigrationExecutor(), $client = new SpyClient(), new Configuration($client, new FakeCatalogProvider(new Catalog([])), '/tmp', 'App\\Migrations'))); + + $tester = new CommandTester(new StatusCommand($container, 'default')); + $tester->execute([]); + + self::assertStringContainsString('up to date', $tester->getDisplay()); + } +} diff --git a/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/Command/UpToDateCommandTest.php b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/Command/UpToDateCommandTest.php new file mode 100644 index 0000000000..17c0f5fdd7 --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/Command/UpToDateCommandTest.php @@ -0,0 +1,56 @@ +set('flow.postgresql.default.migrations.migrator', new Migrator($repository, new FakeMigrationStore(), new SpyMigrationExecutor(), $client = new SpyClient(), new Configuration($client, new FakeCatalogProvider(new Catalog([])), '/tmp', 'App\\Migrations'))); + + $tester = new CommandTester(new UpToDateCommand($container, 'default')); + $tester->execute([]); + + self::assertSame(Command::FAILURE, $tester->getStatusCode()); + self::assertStringContainsString('2 pending migration(s)', $tester->getDisplay()); + self::assertStringContainsString('PENDING', $tester->getDisplay()); + } + + public function test_up_to_date_returns_success() : void + { + $store = new FakeMigrationStore(); + $store->initialize(); + $store->complete(Version::fromString('20260401120000'), 10); + + $repository = new FakeMigrationRepository( + new AvailableMigration(Version::fromString('20260401120000'), 'create_users', new SpyMigration(), new SpyRollback()), + ); + + $container = new Container(); + $container->set('flow.postgresql.default.migrations.migrator', new Migrator($repository, $store, new SpyMigrationExecutor(), $client = new SpyClient(), new Configuration($client, new FakeCatalogProvider(new Catalog([])), '/tmp', 'App\\Migrations'))); + + $tester = new CommandTester(new UpToDateCommand($container, 'default')); + $tester->execute([]); + + self::assertSame(Command::SUCCESS, $tester->getStatusCode()); + self::assertStringContainsString('up to date', $tester->getDisplay()); + } +} diff --git a/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/DependencyInjection/ConfigurationTest.php b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/DependencyInjection/ConfigurationTest.php new file mode 100644 index 0000000000..2e495babe4 --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/DependencyInjection/ConfigurationTest.php @@ -0,0 +1,272 @@ + [ + [ + 'name' => 'public', + 'tables' => [ + [ + 'name' => 'users', + 'columns' => [ + ['name' => 'id', 'type' => ['name' => 'int4', 'schema' => 'pg_catalog'], 'nullable' => false], + ], + ], + ], + ], + ], + ]; + + $config = (new Processor())->processConfiguration(new Configuration(), [[ + 'connections' => [ + 'default' => [ + 'dsn' => 'postgresql://user:pass@localhost:5432/db', + ], + ], + 'migrations' => [ + 'enabled' => true, + ], + 'catalog_providers' => [ + ['catalog' => $catalogData], + ], + ]]); + + self::assertCount(1, $config['catalog_providers']); + self::assertSame($catalogData, $config['catalog_providers'][0]['catalog']); + } + + public function test_catalog_providers_at_top_level_with_service_reference() : void + { + $config = (new Processor())->processConfiguration(new Configuration(), [[ + 'connections' => [ + 'default' => [ + 'dsn' => 'postgresql://user:pass@localhost:5432/db', + ], + ], + 'migrations' => [ + 'enabled' => true, + 'directory' => '/custom/migrations', + 'namespace' => 'Custom\\Migrations', + 'table_name' => 'custom_migrations', + 'table_schema' => 'custom', + ], + 'catalog_providers' => [ + ['catalog_provider_id' => 'app.catalog_provider'], + ], + ]]); + + self::assertSame('app.catalog_provider', $config['catalog_providers'][0]['catalog_provider_id']); + self::assertSame('/custom/migrations', $config['migrations']['directory']); + self::assertSame('Custom\\Migrations', $config['migrations']['namespace']); + self::assertSame('custom_migrations', $config['migrations']['table_name']); + self::assertSame('custom', $config['migrations']['table_schema']); + } + + public function test_catalog_providers_multiple_entries() : void + { + $config = (new Processor())->processConfiguration(new Configuration(), [[ + 'connections' => [ + 'default' => [ + 'dsn' => 'postgresql://user:pass@localhost:5432/db', + ], + ], + 'catalog_providers' => [ + ['catalog' => ['schemas' => []]], + ['catalog_provider_id' => 'app.second_provider'], + ], + ]]); + + self::assertCount(2, $config['catalog_providers']); + self::assertSame('app.second_provider', $config['catalog_providers'][1]['catalog_provider_id']); + } + + public function test_connections_requires_at_least_one_element() : void + { + $this->expectException(InvalidConfigurationException::class); + + (new Processor())->processConfiguration(new Configuration(), [[ + 'connections' => [], + ]]); + } + + public function test_dsn_is_required() : void + { + $this->expectException(InvalidConfigurationException::class); + + (new Processor())->processConfiguration(new Configuration(), [[ + 'connections' => [ + 'default' => [], + ], + ]]); + } + + public function test_migrations_default_values() : void + { + $config = (new Processor())->processConfiguration(new Configuration(), [[ + 'connections' => [ + 'default' => [ + 'dsn' => 'postgresql://user:pass@localhost:5432/db', + ], + ], + 'migrations' => [ + 'enabled' => true, + ], + ]]); + + self::assertSame('%kernel.project_dir%/migrations', $config['migrations']['directory']); + self::assertSame('App\\Migrations', $config['migrations']['namespace']); + self::assertSame('flow_migrations', $config['migrations']['table_name']); + self::assertSame('public', $config['migrations']['table_schema']); + self::assertFalse($config['migrations']['all_or_nothing']); + self::assertTrue($config['migrations']['generate_rollback']); + } + + public function test_migrations_enabled_without_catalog_providers_is_valid_at_config_level() : void + { + $config = (new Processor())->processConfiguration(new Configuration(), [[ + 'connections' => [ + 'default' => [ + 'dsn' => 'postgresql://user:pass@localhost:5432/db', + ], + ], + 'migrations' => [ + 'enabled' => true, + ], + ]]); + + self::assertTrue($config['migrations']['enabled']); + } + + public function test_multiple_connections() : void + { + $config = (new Processor())->processConfiguration(new Configuration(), [[ + 'connections' => [ + 'default' => [ + 'dsn' => 'postgresql://user:pass@localhost:5432/db1', + ], + 'analytics' => [ + 'dsn' => 'postgresql://user:pass@localhost:5432/db2', + ], + ], + ]]); + + self::assertArrayHasKey('default', $config['connections']); + self::assertArrayHasKey('analytics', $config['connections']); + self::assertSame('postgresql://user:pass@localhost:5432/db1', $config['connections']['default']['dsn']); + self::assertSame('postgresql://user:pass@localhost:5432/db2', $config['connections']['analytics']['dsn']); + } + + public function test_single_connection_with_defaults() : void + { + $config = (new Processor())->processConfiguration(new Configuration(), [[ + 'connections' => [ + 'default' => [ + 'dsn' => 'postgresql://user:pass@localhost:5432/db', + ], + ], + ]]); + + self::assertSame('postgresql://user:pass@localhost:5432/db', $config['connections']['default']['dsn']); + self::assertFalse($config['migrations']['enabled']); + } + + public function test_telemetry_not_present_by_default() : void + { + $config = (new Processor())->processConfiguration(new Configuration(), [[ + 'connections' => [ + 'default' => [ + 'dsn' => 'postgresql://user:pass@localhost:5432/db', + ], + ], + ]]); + + self::assertArrayNotHasKey('telemetry', $config['connections']['default']); + } + + public function test_telemetry_requires_service_id() : void + { + $this->expectException(InvalidConfigurationException::class); + + (new Processor())->processConfiguration(new Configuration(), [[ + 'connections' => [ + 'default' => [ + 'dsn' => 'postgresql://user:pass@localhost:5432/db', + 'telemetry' => [], + ], + ], + ]]); + } + + public function test_telemetry_with_custom_options() : void + { + $config = (new Processor())->processConfiguration(new Configuration(), [[ + 'connections' => [ + 'default' => [ + 'dsn' => 'postgresql://user:pass@localhost:5432/db', + 'telemetry' => [ + 'service_id' => 'my.telemetry', + 'clock_service_id' => 'my.clock', + 'trace_queries' => false, + 'trace_transactions' => false, + 'collect_metrics' => false, + 'log_queries' => true, + 'max_query_length' => 500, + 'include_parameters' => true, + 'max_parameters' => 5, + 'max_parameter_length' => 50, + ], + ], + ], + ]]); + + $telemetry = $config['connections']['default']['telemetry']; + self::assertSame('my.telemetry', $telemetry['service_id']); + self::assertSame('my.clock', $telemetry['clock_service_id']); + self::assertFalse($telemetry['trace_queries']); + self::assertFalse($telemetry['trace_transactions']); + self::assertFalse($telemetry['collect_metrics']); + self::assertTrue($telemetry['log_queries']); + self::assertSame(500, $telemetry['max_query_length']); + self::assertTrue($telemetry['include_parameters']); + self::assertSame(5, $telemetry['max_parameters']); + self::assertSame(50, $telemetry['max_parameter_length']); + } + + public function test_telemetry_with_defaults() : void + { + $config = (new Processor())->processConfiguration(new Configuration(), [[ + 'connections' => [ + 'default' => [ + 'dsn' => 'postgresql://user:pass@localhost:5432/db', + 'telemetry' => [ + 'service_id' => 'flow.telemetry', + ], + ], + ], + ]]); + + $telemetry = $config['connections']['default']['telemetry']; + self::assertSame('flow.telemetry', $telemetry['service_id']); + self::assertNull($telemetry['clock_service_id']); + self::assertTrue($telemetry['trace_queries']); + self::assertTrue($telemetry['trace_transactions']); + self::assertTrue($telemetry['collect_metrics']); + self::assertFalse($telemetry['log_queries']); + self::assertSame(1000, $telemetry['max_query_length']); + self::assertFalse($telemetry['include_parameters']); + self::assertSame(10, $telemetry['max_parameters']); + self::assertSame(100, $telemetry['max_parameter_length']); + } +} diff --git a/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/Generator/TwigMigrationGeneratorTest.php b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/Generator/TwigMigrationGeneratorTest.php new file mode 100644 index 0000000000..6b609fe4bd --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/Generator/TwigMigrationGeneratorTest.php @@ -0,0 +1,132 @@ +path, 'App\\Migrations'), + new FixedVersionGenerator(Version::fromString('20260401120000')), + new Environment(new FilesystemLoader($this->templatesPath())), + new NativeLocalFilesystem(), + ); + + $generator->generateDataMigration('test_migration'); + + self::assertFileExists($tmpDir->path . '/20260401120000_test_migration/migration.php'); + self::assertFileExists($tmpDir->path . '/20260401120000_test_migration/rollback.php'); + self::assertStringContainsString('App\\Migrations', (string) \file_get_contents($tmpDir->path . '/20260401120000_test_migration/migration.php')); + self::assertStringContainsString('App\\Migrations', (string) \file_get_contents($tmpDir->path . '/20260401120000_test_migration/rollback.php')); + } finally { + $tmpDir->cleanUp(); + } + } + + public function test_generate_data_migration_without_rollback_when_disabled() : void + { + $tmpDir = new TemporaryDirectory(); + + try { + $generator = new TwigMigrationGenerator( + new Configuration(new SpyClient(), new FakeCatalogProvider(new Catalog([])), $tmpDir->path, 'App\\Migrations', generateRollback: false), + new FixedVersionGenerator(Version::fromString('20260401120000')), + new Environment(new FilesystemLoader($this->templatesPath())), + new NativeLocalFilesystem(), + ); + + $generator->generateDataMigration('test_migration'); + + self::assertFileExists($tmpDir->path . '/20260401120000_test_migration/migration.php'); + self::assertFileDoesNotExist($tmpDir->path . '/20260401120000_test_migration/rollback.php'); + } finally { + $tmpDir->cleanUp(); + } + } + + public function test_generate_schema_migration_creates_files() : void + { + $tmpDir = new TemporaryDirectory(); + + try { + $generator = new TwigMigrationGenerator( + new Configuration(new SpyClient(), new FakeCatalogProvider(new Catalog([])), $tmpDir->path, 'App\\Migrations'), + new FixedVersionGenerator(Version::fromString('20260401120000')), + new Environment(new FilesystemLoader($this->templatesPath())), + new NativeLocalFilesystem(), + ); + + $generator->generateSchemaMigration('add_table', ['CREATE TABLE test (id INT)'], ['DROP TABLE test']); + + self::assertFileExists($tmpDir->path . '/20260401120000_add_table/migration.php'); + self::assertFileExists($tmpDir->path . '/20260401120000_add_table/rollback.php'); + + $migrationContent = (string) \file_get_contents($tmpDir->path . '/20260401120000_add_table/migration.php'); + self::assertStringContainsString('CREATE TABLE test (id INT)', $migrationContent); + + $rollbackContent = (string) \file_get_contents($tmpDir->path . '/20260401120000_add_table/rollback.php'); + self::assertStringContainsString('DROP TABLE test', $rollbackContent); + } finally { + $tmpDir->cleanUp(); + } + } + + public function test_generate_schema_migration_without_rollback() : void + { + $tmpDir = new TemporaryDirectory(); + + try { + $generator = new TwigMigrationGenerator( + new Configuration(new SpyClient(), new FakeCatalogProvider(new Catalog([])), $tmpDir->path, 'App\\Migrations'), + new FixedVersionGenerator(Version::fromString('20260401120000')), + new Environment(new FilesystemLoader($this->templatesPath())), + new NativeLocalFilesystem(), + ); + + $generator->generateSchemaMigration('add_table', ['CREATE TABLE test (id INT)']); + + self::assertFileExists($tmpDir->path . '/20260401120000_add_table/migration.php'); + self::assertFileDoesNotExist($tmpDir->path . '/20260401120000_add_table/rollback.php'); + } finally { + $tmpDir->cleanUp(); + } + } + + public function test_returns_version_from_generator() : void + { + $tmpDir = new TemporaryDirectory(); + + try { + $generator = new TwigMigrationGenerator( + new Configuration(new SpyClient(), new FakeCatalogProvider(new Catalog([])), $tmpDir->path, 'App\\Migrations'), + new FixedVersionGenerator(Version::fromString('20260401120000')), + new Environment(new FilesystemLoader($this->templatesPath())), + new NativeLocalFilesystem(), + ); + + self::assertTrue(Version::fromString('20260401120000')->equals($generator->generateDataMigration('test'))); + } finally { + $tmpDir->cleanUp(); + } + } +} diff --git a/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/Repository/FilesystemMigrationRepositoryTest.php b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/Repository/FilesystemMigrationRepositoryTest.php new file mode 100644 index 0000000000..3dfb140f05 --- /dev/null +++ b/src/bridge/symfony/postgresql-bundle/tests/Flow/Bridge/Symfony/PostgreSqlBundle/Tests/Unit/Repository/FilesystemMigrationRepositoryTest.php @@ -0,0 +1,163 @@ +fixturesPath()), new Configuration(new SpyClient(), new FakeCatalogProvider(new Catalog([])), $this->fixturesPath(), 'Test')); + + foreach ($repository->all() as $migration) { + self::assertInstanceOf(Migration::class, $migration->migration); + } + } + + public function test_discovers_all_migrations_from_directory() : void + { + $repository = new FilesystemMigrationRepository(native_local_filesystem(), path($this->fixturesPath()), new Configuration(new SpyClient(), new FakeCatalogProvider(new Catalog([])), $this->fixturesPath(), 'Test')); + + self::assertCount(3, $repository->all()); + } + + public function test_get_returns_migration_for_existing_version() : void + { + $repository = new FilesystemMigrationRepository(native_local_filesystem(), path($this->fixturesPath()), new Configuration(new SpyClient(), new FakeCatalogProvider(new Catalog([])), $this->fixturesPath(), 'Test')); + + $migration = $repository->get(Version::fromString('20260401120000')); + + self::assertTrue(Version::fromString('20260401120000')->equals($migration->version)); + } + + public function test_get_throws_on_missing_version() : void + { + $repository = new FilesystemMigrationRepository(native_local_filesystem(), path($this->fixturesPath()), new Configuration(new SpyClient(), new FakeCatalogProvider(new Catalog([])), $this->fixturesPath(), 'Test')); + + $this->expectException(MigrationException::class); + $repository->get(Version::fromString('99999999999999')); + } + + public function test_has_returns_false_for_missing_version() : void + { + $repository = new FilesystemMigrationRepository(native_local_filesystem(), path($this->fixturesPath()), new Configuration(new SpyClient(), new FakeCatalogProvider(new Catalog([])), $this->fixturesPath(), 'Test')); + + self::assertFalse($repository->has(Version::fromString('99999999999999'))); + } + + public function test_has_returns_true_for_existing_version() : void + { + $repository = new FilesystemMigrationRepository(native_local_filesystem(), path($this->fixturesPath()), new Configuration(new SpyClient(), new FakeCatalogProvider(new Catalog([])), $this->fixturesPath(), 'Test')); + + self::assertTrue($repository->has(Version::fromString('20260401120000'))); + } + + public function test_migrations_are_sorted_by_version() : void + { + $repository = new FilesystemMigrationRepository(native_local_filesystem(), path($this->fixturesPath()), new Configuration(new SpyClient(), new FakeCatalogProvider(new Catalog([])), $this->fixturesPath(), 'Test')); + + $items = \iterator_to_array($repository->all()); + + self::assertTrue(Version::fromString('20260401120000')->equals($items[0]->version)); + self::assertTrue(Version::fromString('20260402100000')->equals($items[1]->version)); + self::assertTrue(Version::fromString('20260403090000')->equals($items[2]->version)); + } + + public function test_names_are_parsed_from_entry_names() : void + { + $repository = new FilesystemMigrationRepository(native_local_filesystem(), path($this->fixturesPath()), new Configuration(new SpyClient(), new FakeCatalogProvider(new Catalog([])), $this->fixturesPath(), 'Test')); + + self::assertSame('create_users', $repository->get(Version::fromString('20260401120000'))->name); + self::assertSame('seed_data', $repository->get(Version::fromString('20260402100000'))->name); + self::assertSame('add_column', $repository->get(Version::fromString('20260403090000'))->name); + } + + public function test_rollback_is_loaded_when_present() : void + { + $repository = new FilesystemMigrationRepository(native_local_filesystem(), path($this->fixturesPath()), new Configuration(new SpyClient(), new FakeCatalogProvider(new Catalog([])), $this->fixturesPath(), 'Test')); + + self::assertInstanceOf(Rollback::class, $repository->get(Version::fromString('20260401120000'))->rollback); + } + + public function test_rollback_is_null_when_absent() : void + { + $repository = new FilesystemMigrationRepository(native_local_filesystem(), path($this->fixturesPath()), new Configuration(new SpyClient(), new FakeCatalogProvider(new Catalog([])), $this->fixturesPath(), 'Test')); + + self::assertNull($repository->get(Version::fromString('20260403090000'))->rollback); + } + + public function test_throws_on_invalid_migration() : void + { + $tmpDir = new TemporaryDirectory(); + + try { + \mkdir($tmpDir->path . '/20260401120000_test', 0777, true); + \file_put_contents($tmpDir->path . '/20260401120000_test/migration.php', 'path), new Configuration(new SpyClient(), new FakeCatalogProvider(new Catalog([])), $tmpDir->path, 'Test')); + + $this->expectException(MigrationException::class); + $repository->all(); + } finally { + $tmpDir->cleanUp(); + } + } + + public function test_throws_on_invalid_rollback() : void + { + $tmpDir = new TemporaryDirectory(); + + try { + \mkdir($tmpDir->path . '/20260401120000_test', 0777, true); + \file_put_contents($tmpDir->path . '/20260401120000_test/migration.php', 'path . '/20260401120000_test/rollback.php', 'path), new Configuration(new SpyClient(), new FakeCatalogProvider(new Catalog([])), $tmpDir->path, 'Test')); + + $this->expectException(MigrationException::class); + $repository->all(); + } finally { + $tmpDir->cleanUp(); + } + } + + public function test_throws_on_missing_migration_file() : void + { + $tmpDir = new TemporaryDirectory(); + + try { + \mkdir($tmpDir->path . '/20260401120000_test', 0777, true); + + $repository = new FilesystemMigrationRepository(native_local_filesystem(), path($tmpDir->path), new Configuration(new SpyClient(), new FakeCatalogProvider(new Catalog([])), $tmpDir->path, 'Test')); + + $this->expectException(MigrationException::class); + $repository->all(); + } finally { + $tmpDir->cleanUp(); + } + } + + public function test_versions_are_parsed_from_entry_names() : void + { + $repository = new FilesystemMigrationRepository(native_local_filesystem(), path($this->fixturesPath()), new Configuration(new SpyClient(), new FakeCatalogProvider(new Catalog([])), $this->fixturesPath(), 'Test')); + + self::assertTrue($repository->has(Version::fromString('20260401120000'))); + self::assertTrue($repository->has(Version::fromString('20260402100000'))); + self::assertTrue($repository->has(Version::fromString('20260403090000'))); + } +} diff --git a/src/bridge/symfony/telemetry-bundle/composer.json b/src/bridge/symfony/telemetry-bundle/composer.json index 6fe56f9201..83e60f146b 100644 --- a/src/bridge/symfony/telemetry-bundle/composer.json +++ b/src/bridge/symfony/telemetry-bundle/composer.json @@ -19,11 +19,11 @@ "flow-php/telemetry": "self.version", "flow-php/symfony-http-foundation-telemetry-bridge": "self.version", "psr/clock": "^1.0", - "symfony/config": "^6.4 || ^7.3 || ^8.0", - "symfony/console": "^6.4 || ^7.3 || ^8.0", - "symfony/dependency-injection": "^6.4 || ^7.3 || ^8.0", + "symfony/config": "^6.4 || ^7.4 || ^8.0", + "symfony/console": "^6.4 || ^7.4 || ^8.0", + "symfony/dependency-injection": "^6.4 || ^7.4 || ^8.0", "symfony/http-client-contracts": "^3.0", - "symfony/http-kernel": "^6.4 || ^7.3 || ^8.0", + "symfony/http-kernel": "^6.4 || ^7.4 || ^8.0", "symfony/polyfill-mbstring": "^1.33" }, "require-dev": { @@ -31,9 +31,9 @@ "flow-php/psr18-telemetry-bridge": "self.version", "flow-php/telemetry-otlp-bridge": "self.version", "nyholm/psr7": "^1.8", - "symfony/framework-bundle": "^6.4 || ^7.3 || ^8.0", - "symfony/messenger": "^6.4 || ^7.3 || ^8.0", - "symfony/routing": "^6.4 || ^7.3 || ^8.0", + "symfony/framework-bundle": "^6.4 || ^7.4 || ^8.0", + "symfony/messenger": "^6.4 || ^7.4 || ^8.0", + "symfony/routing": "^6.4 || ^7.4 || ^8.0", "twig/twig": "^3.0" }, "suggest": { diff --git a/src/bridge/telemetry/otlp/composer.json b/src/bridge/telemetry/otlp/composer.json index 0e656db711..7cb4641403 100644 --- a/src/bridge/telemetry/otlp/composer.json +++ b/src/bridge/telemetry/otlp/composer.json @@ -25,7 +25,7 @@ "open-telemetry/gen-otlp-protobuf": "^1.8", "google/protobuf": "^4.0", "nyholm/psr7": "^1.8", - "symfony/http-client": "^6.4 || ^7.3 || ^8.0" + "symfony/http-client": "^6.4 || ^7.4 || ^8.0" }, "suggest": { "ext-grpc": "Required for gRPC transport", diff --git a/src/cli/composer.json b/src/cli/composer.json index 2bcb38ca16..10fa38a310 100644 --- a/src/cli/composer.json +++ b/src/cli/composer.json @@ -9,10 +9,10 @@ ], "require": { "php": "~8.3.0 || ~8.4.0 || ~8.5.0", - "symfony/console": "^6.4 || ^7.3 || ^8.0", - "symfony/http-client": "^6.4 || ^7.3 || ^8.0", + "symfony/console": "^6.4 || ^7.4 || ^8.0", + "symfony/http-client": "^6.4 || ^7.4 || ^8.0", "nyholm/psr7": "^1.8", - "symfony/uid": "^6.4 || ^7.3 || ^8.0", + "symfony/uid": "^6.4 || ^7.4 || ^8.0", "flow-php/etl": "self.version", "flow-php/etl-adapter-csv": "self.version", "flow-php/etl-adapter-parquet": "self.version", diff --git a/src/core/etl/composer.json b/src/core/etl/composer.json index a589a8cf58..29b97cd0ca 100644 --- a/src/core/etl/composer.json +++ b/src/core/etl/composer.json @@ -13,14 +13,14 @@ "ext-json": "*", "psr/clock": "^1.0", "brick/math": "^0.12 || ^0.13 || ^0.14", - "composer-runtime-api": "^2.0", + "composer-runtime-api": "^2.2", "flow-php/telemetry": "self.version", "flow-php/types": "self.version", "flow-php/array-dot": "self.version", "flow-php/filesystem": "self.version", "psr/simple-cache": "^1.0 || ^2.0 || ^3.0", "webmozart/glob": "^3.0 || ^4.0", - "symfony/string": "^6.4 || ^7.3 || ^8.0" + "symfony/string": "^6.4 || ^7.4 || ^8.0" }, "suggest": { "ext-bcmath": "BCMath extension for PHP for more precise calculations" @@ -28,7 +28,7 @@ "require-dev": { "ramsey/uuid": "^4.5", "symfony/polyfill-mbstring": "^1.33", - "symfony/uid": "^6.4 || ^7.3 || ^8.0" + "symfony/uid": "^6.4 || ^7.4 || ^8.0" }, "config": { "optimize-autoloader": true, diff --git a/src/core/etl/src/Flow/ETL/Attribute/Module.php b/src/core/etl/src/Flow/ETL/Attribute/Module.php index a9a47280c2..f4fdeda92d 100644 --- a/src/core/etl/src/Flow/ETL/Attribute/Module.php +++ b/src/core/etl/src/Flow/ETL/Attribute/Module.php @@ -25,6 +25,7 @@ enum Module : string case PARQUET = 'PARQUET'; case PG_QUERY = 'PG_QUERY'; case POSTGRESQL = 'POSTGRESQL'; + case POSTGRESQL_MIGRATIONS = 'POSTGRESQL_MIGRATIONS'; case PSR18_TELEMETRY_BRIDGE = 'PSR18_TELEMETRY_BRIDGE'; case PSR7_TELEMETRY_BRIDGE = 'PSR7_TELEMETRY_BRIDGE'; case S3_FILESYSTEM = 'S3_FILESYSTEM'; diff --git a/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/BinaryComparisonsTest.php b/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/BinaryComparisonsTest.php index c3c491784d..e923c81d3a 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/BinaryComparisonsTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Integration/Function/BinaryComparisonsTest.php @@ -26,7 +26,7 @@ public function test_all_comparisons() : void when(ref('a')->equals(ref('b')), lit(true), lit(false)) ) ->withEntry( - 'neq', + 'ne', when(ref('a')->notEquals(ref('c')), lit(true), lit(false)) ) ->withEntry( @@ -34,7 +34,7 @@ public function test_all_comparisons() : void when(ref('a')->greaterThan(ref('b')), lit(true), lit(false)) ) ->withEntry( - 'gte', + 'ge', when(ref('a')->greaterThanEqual(ref('b')), lit(true), lit(false)) ) ->withEntry( @@ -42,7 +42,7 @@ public function test_all_comparisons() : void when(ref('a')->lessThan(ref('b')), lit(true), lit(false)) ) ->withEntry( - 'lte', + 'le', when(ref('a')->lessThanEqual(ref('b')), lit(true), lit(false)) ) ->withEntry( @@ -89,11 +89,11 @@ public function test_all_comparisons() : void 'c' => 10, 'd' => 'value', 'eq' => true, - 'neq' => true, + 'ne' => true, 'gt' => false, - 'gte' => true, + 'ge' => true, 'lt' => false, - 'lte' => true, + 'le' => true, 'in' => true, 'same' => true, 'not_same' => false, diff --git a/src/lib/parquet-viewer/composer.json b/src/lib/parquet-viewer/composer.json index a9a4279f24..9814cb7777 100644 --- a/src/lib/parquet-viewer/composer.json +++ b/src/lib/parquet-viewer/composer.json @@ -15,7 +15,7 @@ "coduo/php-humanizer": "^5.0", "flow-php/etl": "self.version", "flow-php/parquet": "self.version", - "symfony/console": "^6.4 || ^7.3 || ^8.0" + "symfony/console": "^6.4 || ^7.4 || ^8.0" }, "config": { "optimize-autoloader": true, diff --git a/src/lib/parquet/composer.json b/src/lib/parquet/composer.json index a3266fce06..1b9ac084cc 100644 --- a/src/lib/parquet/composer.json +++ b/src/lib/parquet/composer.json @@ -14,7 +14,7 @@ "php": "~8.3.0 || ~8.4.0 || ~8.5.0", "ext-bcmath": "*", "ext-zlib": "*", - "composer-runtime-api": "^2.0", + "composer-runtime-api": "^2.2", "flow-php/snappy": "self.version", "flow-php/filesystem": "self.version", "packaged/thrift": "^0.15.0", diff --git a/src/lib/postgresql/composer.json b/src/lib/postgresql/composer.json index 1dbba0d983..4d8d05ea8c 100644 --- a/src/lib/postgresql/composer.json +++ b/src/lib/postgresql/composer.json @@ -13,6 +13,7 @@ "require": { "php": "~8.3.0 || ~8.4.0 || ~8.5.0", "flow-php/telemetry": "self.version", + "flow-php/types": "self.version", "google/protobuf": "^4.0", "psr/clock": "^1.0" }, @@ -37,8 +38,13 @@ ] }, "files": [ - "src/Flow/PostgreSql/DSL/functions.php", - "src/stubs.php" + "src/Flow/PostgreSql/DSL/client.php", + "src/Flow/PostgreSql/DSL/condition.php", + "src/Flow/PostgreSql/DSL/parser.php", + "src/Flow/PostgreSql/DSL/query.php", + "src/Flow/PostgreSql/DSL/schema.php", + "src/stubs.php", + "src/Flow/PostgreSql/Migrations/DSL/functions.php" ] }, "autoload-dev": { diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Client/Client.php b/src/lib/postgresql/src/Flow/PostgreSql/Client/Client.php index 9ee45d7b17..36aa1557bd 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/Client/Client.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/Client/Client.php @@ -8,7 +8,7 @@ use Flow\PostgreSql\Client\Exception\{QueryException, TransactionException}; use Flow\PostgreSql\Client\Types\ValueConverters; use Flow\PostgreSql\Explain\Plan\Plan; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; interface Client { @@ -43,190 +43,184 @@ public function converters() : ValueConverters; * Memory efficient - rows are fetched one at a time. * Use cursor->map() to map rows to objects. * - * @param SqlQuery|string $sql SQL query or query builder with $1, $2, ... placeholders + * @param Sql|string $sql SQL query or query builder with $1, $2, ... placeholders * @param array $parameters Positional parameters * * @throws QueryException */ - public function cursor(SqlQuery|string $sql, array $parameters = []) : Cursor; + public function cursor(Sql|string $sql, array $parameters = []) : Cursor; /** * Execute a statement that modifies data (INSERT, UPDATE, DELETE). * Returns the number of affected rows. * - * @param SqlQuery|string $sql SQL statement or query builder with $1, $2, ... placeholders + * @param Sql|string $sql SQL statement or query builder with $1, $2, ... placeholders * @param array $parameters Positional parameters * * @throws QueryException */ - public function execute(SqlQuery|string $sql, array $parameters = []) : int; + public function execute(Sql|string $sql, array $parameters = []) : int; /** * Execute EXPLAIN ANALYZE on a query and return the execution plan. * Useful for analyzing query performance. * - * @param SqlQuery|string $sql SQL query to explain + * @param Sql|string $sql SQL query to explain * @param array $parameters Positional parameters * @param null|ExplainConfig $config EXPLAIN configuration (defaults to forAnalysis()) * * @throws QueryException */ - public function explain(SqlQuery|string $sql, array $parameters = [], ?ExplainConfig $config = null) : Plan; + public function explain(Sql|string $sql, array $parameters = [], ?ExplainConfig $config = null) : Plan; /** * Fetch the first row from query result. * Returns null if no rows found. * - * @param SqlQuery|string $sql SQL query or query builder with $1, $2, ... placeholders + * @param Sql|string $sql SQL query or query builder with $1, $2, ... placeholders * @param array $parameters Positional parameters * * @throws QueryException * * @return null|array */ - public function fetch(SqlQuery|string $sql, array $parameters = []) : ?array; + public function fetch(Sql|string $sql, array $parameters = []) : ?array; /** * Fetch all rows from query result. * - * @param SqlQuery|string $sql SQL query or query builder with $1, $2, ... placeholders + * @param Sql|string $sql SQL query or query builder with $1, $2, ... placeholders * @param array $parameters Positional parameters * * @throws QueryException * * @return array> */ - public function fetchAll(SqlQuery|string $sql, array $parameters = []) : array; + public function fetchAll(Sql|string $sql, array $parameters = []) : array; /** - * Fetch all rows and map to objects. + * Fetch all rows and map using the provided mapper. * - * @template T of object + * @template T * - * @param class-string $class Target class for mapping - * @param SqlQuery|string $sql SQL query or query builder with $1, $2, ... placeholders + * @param RowMapper $mapper Mapper to apply to each row + * @param Sql|string $sql SQL query or query builder with $1, $2, ... placeholders * @param array $parameters Positional parameters - * @param null|RowMapper $mapper Override default mapper for this call * * @throws QueryException * - * @return array + * @return list */ public function fetchAllInto( - string $class, - SqlQuery|string $sql, + RowMapper $mapper, + Sql|string $sql, array $parameters = [], - ?RowMapper $mapper = null, ) : array; /** - * Fetch the first row and map to object. + * Fetch the first row and map using the provided mapper. * Returns null if no rows found. * - * @template T of object + * @template T * - * @param class-string $class Target class for mapping - * @param SqlQuery|string $sql SQL query or query builder with $1, $2, ... placeholders + * @param RowMapper $mapper Mapper to apply to the row + * @param Sql|string $sql SQL query or query builder with $1, $2, ... placeholders * @param array $parameters Positional parameters - * @param null|RowMapper $mapper Override default mapper for this call * * @throws QueryException * * @return null|T */ public function fetchInto( - string $class, - SqlQuery|string $sql, + RowMapper $mapper, + Sql|string $sql, array $parameters = [], - ?RowMapper $mapper = null, - ) : ?object; + ) : mixed; /** * Fetch exactly one row. Throws if result has 0 or more than 1 row. * Use when you expect precisely one result (e.g., SELECT by primary key). * - * @param SqlQuery|string $sql SQL query or query builder with $1, $2, ... placeholders + * @param Sql|string $sql SQL query or query builder with $1, $2, ... placeholders * @param array $parameters Positional parameters * * @throws QueryException When row count is not exactly 1 * * @return array */ - public function fetchOne(SqlQuery|string $sql, array $parameters = []) : array; + public function fetchOne(Sql|string $sql, array $parameters = []) : array; /** - * Fetch exactly one row and map to object. + * Fetch exactly one row and map using the provided mapper. * Throws if result has 0 or more than 1 row. * - * @template T of object + * @template T * - * @param class-string $class Target class for mapping - * @param SqlQuery|string $sql SQL query or query builder with $1, $2, ... placeholders + * @param RowMapper $mapper Mapper to apply to the row + * @param Sql|string $sql SQL query or query builder with $1, $2, ... placeholders * @param array $parameters Positional parameters - * @param null|RowMapper $mapper Override default mapper for this call * * @throws QueryException When row count is not exactly 1 * * @return T */ public function fetchOneInto( - string $class, - SqlQuery|string $sql, + RowMapper $mapper, + Sql|string $sql, array $parameters = [], - ?RowMapper $mapper = null, - ) : object; + ) : mixed; /** * Fetch a single scalar value from the first column of first row. * Ideal for COUNT(*), MAX(), MIN(), etc. * - * @param SqlQuery|string $sql SQL query or query builder with $1, $2, ... placeholders + * @param Sql|string $sql SQL query or query builder with $1, $2, ... placeholders * @param array $parameters Positional parameters * * @throws QueryException */ - public function fetchScalar(SqlQuery|string $sql, array $parameters = []) : mixed; + public function fetchScalar(Sql|string $sql, array $parameters = []) : mixed; /** * Fetch a single boolean value from the first column of first row. * - * @param SqlQuery|string $sql SQL query or query builder with $1, $2, ... placeholders + * @param Sql|string $sql SQL query or query builder with $1, $2, ... placeholders * @param array $parameters Positional parameters * * @throws QueryException */ - public function fetchScalarBool(SqlQuery|string $sql, array $parameters = []) : bool; + public function fetchScalarBool(Sql|string $sql, array $parameters = []) : bool; /** * Fetch a single float value from the first column of first row. * - * @param SqlQuery|string $sql SQL query or query builder with $1, $2, ... placeholders + * @param Sql|string $sql SQL query or query builder with $1, $2, ... placeholders * @param array $parameters Positional parameters * * @throws QueryException */ - public function fetchScalarFloat(SqlQuery|string $sql, array $parameters = []) : float; + public function fetchScalarFloat(Sql|string $sql, array $parameters = []) : float; /** * Fetch a single integer value from the first column of first row. * Ideal for COUNT(*), MAX(), MIN(), etc. * - * @param SqlQuery|string $sql SQL query or query builder with $1, $2, ... placeholders + * @param Sql|string $sql SQL query or query builder with $1, $2, ... placeholders * @param array $parameters Positional parameters * * @throws QueryException */ - public function fetchScalarInt(SqlQuery|string $sql, array $parameters = []) : int; + public function fetchScalarInt(Sql|string $sql, array $parameters = []) : int; /** * Fetch a single string value from the first column of first row. * - * @param SqlQuery|string $sql SQL query or query builder with $1, $2, ... placeholders + * @param Sql|string $sql SQL query or query builder with $1, $2, ... placeholders * @param array $parameters Positional parameters * * @throws QueryException */ - public function fetchScalarString(SqlQuery|string $sql, array $parameters = []) : string; + public function fetchScalarString(Sql|string $sql, array $parameters = []) : string; /** * Get the current transaction nesting level. diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Client/Cursor.php b/src/lib/postgresql/src/Flow/PostgreSql/Client/Cursor.php index fcb2089805..aeea6672f2 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/Client/Cursor.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/Client/Cursor.php @@ -34,19 +34,16 @@ public function free() : void; public function iterate() : \Generator; /** - * Iterate all remaining rows, mapping each to an object. - * Memory efficient - one object at a time. + * Iterate all remaining rows, mapping each using the provided mapper. + * Memory efficient - one result at a time. * - * Uses the client's default mapper unless overridden. + * @template T * - * @template T of object - * - * @param class-string $class Target class for mapping - * @param null|RowMapper $mapper Override default mapper for this iteration + * @param RowMapper $mapper Mapper to apply to each row * * @return \Generator */ - public function map(string $class, ?RowMapper $mapper = null) : \Generator; + public function map(RowMapper $mapper) : \Generator; /** * Fetch the next row. Returns null when exhausted. diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Client/Exception/MappingException.php b/src/lib/postgresql/src/Flow/PostgreSql/Client/Exception/MappingException.php index 836ebb5550..3562848508 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/Client/Exception/MappingException.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/Client/Exception/MappingException.php @@ -11,13 +11,6 @@ public static function mappingFailed(string $class, string $reason) : self return new self(\sprintf('Failed to map row to "%s": %s', $class, $reason)); } - public static function noMapperConfigured() : self - { - return new self( - 'No RowMapper configured. Pass a mapper to the method or set a default mapper on the client.' - ); - } - public static function propertyNotFound(string $class, string $property) : self { return new self(\sprintf('Property "%s" not found on class "%s"', $property, $class)); diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Client/Exception/ValueConversionException.php b/src/lib/postgresql/src/Flow/PostgreSql/Client/Exception/ValueConversionException.php index f70c2fe776..d1363f74ba 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/Client/Exception/ValueConversionException.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/Client/Exception/ValueConversionException.php @@ -8,7 +8,7 @@ final class ValueConversionException extends ClientException { public static function ambiguousArrayType() : self { - return new self('Array parameters require explicit type specification. Use typed($array, PostgreSqlType::INT4_ARRAY) or similar to specify the target array type.'); + return new self('Array parameters require explicit type specification. Use typed($array, ValueType::INT4_ARRAY) or similar to specify the target array type.'); } public static function cannotConvert(mixed $value, string $targetType) : self diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Client/Infrastructure/PgSql/PgCatalogProvider.php b/src/lib/postgresql/src/Flow/PostgreSql/Client/Infrastructure/PgSql/PgCatalogProvider.php new file mode 100644 index 0000000000..15b8dca074 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Client/Infrastructure/PgSql/PgCatalogProvider.php @@ -0,0 +1,1136 @@ + $schemaNames + * @param list $excludeTables + */ + public function __construct( + private Client $client, + private ?array $schemaNames = null, + private array $excludeTables = [], + ) { + $this->columnTypeParser = new ColumnTypeParser(); + $this->expressionParser = new ExpressionParser(new Parser()); + } + + public function get() : Catalog + { + $schemas = []; + + foreach ($this->resolveSchemaNames() as $schemaName) { + $schemas[] = $this->readSchema($schemaName); + } + + return new Catalog($schemas); + } + + private function mapIndexMethod(string $amname) : IndexMethod + { + return IndexMethod::tryFrom($amname) ?? IndexMethod::BTREE; + } + + private function mapReferentialAction(string $code) : ReferentialAction + { + return ReferentialAction::tryFrom($code) ?? ReferentialAction::NO_ACTION; + } + + /** + * Strip implicit type casts from default values that PostgreSQL adds for storage. + * + * PostgreSQL stores `'pending'` as `'pending'::character varying` — the cast is implicit + * and redundant since the column type is already known. This method parses the expression + * and removes the outer TypeCast when it wraps a simple constant. + */ + private function normalizeDefault(?string $default) : ?string + { + if ($default === null) { + return null; + } + + $node = $this->expressionParser->parse($default); + $typeCast = $node->getTypeCast(); + + if ($typeCast === null) { + return $default; + } + + $inner = $typeCast->getArg(); + + if ($inner === null || $inner->getAConst() === null) { + return $default; + } + + $aConst = $inner->getAConst(); + $sval = $aConst->getSval(); + + if ($sval !== null) { + return "'" . \str_replace("'", "''", $sval->getSval()) . "'"; + } + + $ival = $aConst->getIval(); + + if ($ival !== null) { + /** @phpstan-ignore method.nonObject */ + return (string) $ival->getIval(); + } + + $fval = $aConst->getFval(); + + if ($fval !== null) { + return $fval->getFval(); + } + + return $default; + } + + /** + * @return list + */ + private function parseArgumentTypes(string $arguments) : array + { + if ($arguments === '') { + return []; + } + + $types = []; + + foreach (\explode(', ', $arguments) as $arg) { + $parts = \explode(' ', \trim($arg)); + $types[] = \end($parts); + } + + return $types; + } + + /** + * @return non-empty-list + */ + private function parseArrayLiteral(string $literal) : array + { + $trimmed = \trim($literal, '{}'); + + if ($trimmed === '') { + throw new \RuntimeException(\sprintf('Expected non-empty array literal, got "%s".', $literal)); + } + + return \array_values(\array_map('trim', \explode(',', $trimmed))); + } + + /** + * @return list + */ + private function readCheckConstraints(string $tableName, string $schemaName) : array + { + $rows = $this->client->fetchAllInto( + type_mapper(type_structure([ + 'name' => type_string(), + 'definition' => type_string(), + 'no_inherit' => type_boolean(), + ])), + select( + col('conname', 'con')->as('name'), + func('pg_catalog.pg_get_constraintdef', [col('oid', 'con')])->as('definition'), + col('connoinherit', 'con')->as('no_inherit'), + ) + ->from(table('pg_constraint', 'pg_catalog')->as('con')) + ->join(table('pg_class', 'pg_catalog')->as('c'), eq(col('oid', 'c'), col('conrelid', 'con'))) + ->join(table('pg_namespace', 'pg_catalog')->as('n'), eq(col('oid', 'n'), col('relnamespace', 'c'))) + ->where(and_( + eq(col('relname', 'c'), param(1)), + eq(col('nspname', 'n'), param(2)), + eq(col('contype', 'con'), literal('c')), + )) + ->orderBy(asc(col('conname', 'con'))), + [$tableName, $schemaName], + ); + + $constraints = []; + + foreach ($rows as $row) { + $constraints[] = new CheckConstraint( + $this->stripCheckWrapper($row['definition']), + $row['name'], + $row['no_inherit'], + ); + } + + return $constraints; + } + + /** + * @return non-empty-list + */ + private function readColumns(string $tableName, string $schemaName) : array + { + $rows = $this->client->fetchAllInto( + type_mapper(type_structure([ + 'name' => type_string(), + 'type_name' => type_string(), + 'nullable' => type_boolean(), + 'identity' => type_string(), + 'generated' => type_string(), + 'ordinal_position' => type_integer(), + ], [ + 'default_value' => type_union(type_string(), type_null()), + ])), + select( + col('attname', 'a')->as('name'), + func('pg_catalog.format_type', [col('atttypid', 'a'), col('atttypmod', 'a')])->as('type_name'), + not_(col('attnotnull', 'a'))->as('nullable'), + func('pg_catalog.pg_get_expr', [col('adbin', 'd'), col('adrelid', 'd')])->as('default_value'), + col('attidentity', 'a')->as('identity'), + col('attgenerated', 'a')->as('generated'), + col('attnum', 'a')->as('ordinal_position'), + ) + ->from(table('pg_attribute', 'pg_catalog')->as('a')) + ->leftJoin( + table('pg_attrdef', 'pg_catalog')->as('d'), + and_( + eq(col('adrelid', 'd'), col('attrelid', 'a')), + eq(col('adnum', 'd'), col('attnum', 'a')), + ), + ) + ->where(and_( + eq( + col('attrelid', 'a'), + sub_select( + select(col('oid', 'c')) + ->from(table('pg_class', 'pg_catalog')->as('c')) + ->join(table('pg_namespace', 'pg_catalog')->as('n'), eq(col('oid', 'n'), col('relnamespace', 'c'))) + ->where(and_( + eq(col('relname', 'c'), param(1)), + eq(col('nspname', 'n'), param(2)), + )) + ), + ), + gt(col('attnum', 'a'), literal(0)), + not_(is_true(col('attisdropped', 'a'))), + )) + ->orderBy(asc(col('attnum', 'a'))), + [$tableName, $schemaName], + ); + + $columns = []; + + foreach ($rows as $row) { + $isIdentity = $row['identity'] !== ''; + $isGenerated = $row['generated'] !== ''; + + $defaultValue = $row['default_value'] ?? null; + + $columns[] = new Column( + $row['name'], + $this->columnTypeParser->parse($row['type_name']), + $row['nullable'], + $isGenerated ? null : $this->normalizeDefault($defaultValue), + $isIdentity, + $isIdentity ? IdentityGeneration::from($row['identity']) : null, + $isGenerated, + $isGenerated ? $this->normalizeDefault($defaultValue) : null, + $row['ordinal_position'], + ); + } + + if ($columns === []) { + throw new \RuntimeException(\sprintf('Table "%s"."%s" has no columns.', $schemaName, $tableName)); + } + + return $columns; + } + + /** + * @return list + */ + private function readDomainCheckConstraints(string $domainName, string $schemaName) : array + { + $rows = $this->client->fetchAllInto( + type_mapper(type_structure([ + 'name' => type_string(), + 'definition' => type_string(), + ])), + select( + col('conname', 'con')->as('name'), + func('pg_catalog.pg_get_constraintdef', [col('oid', 'con')])->as('definition'), + ) + ->from(table('pg_constraint', 'pg_catalog')->as('con')) + ->join(table('pg_type', 'pg_catalog')->as('t'), eq(col('oid', 't'), col('contypid', 'con'))) + ->join(table('pg_namespace', 'pg_catalog')->as('n'), eq(col('oid', 'n'), col('typnamespace', 't'))) + ->where(and_( + eq(col('typname', 't'), param(1)), + eq(col('nspname', 'n'), param(2)), + eq(col('contype', 'con'), literal('c')), + )) + ->orderBy(asc(col('conname', 'con'))), + [$domainName, $schemaName], + ); + + $constraints = []; + + foreach ($rows as $row) { + $constraints[] = new CheckConstraint( + $this->stripCheckWrapper($row['definition']), + $row['name'], + ); + } + + return $constraints; + } + + /** + * @return list + */ + private function readDomains(string $schemaName) : array + { + $rows = $this->client->fetchAllInto( + type_mapper(type_structure([ + 'name' => type_string(), + 'base_type' => type_string(), + 'nullable' => type_boolean(), + ], [ + 'default_value' => type_union(type_string(), type_null()), + ])), + select( + col('typname', 't')->as('name'), + func('pg_catalog.format_type', [col('typbasetype', 't'), col('typtypmod', 't')])->as('base_type'), + not_(col('typnotnull', 't'))->as('nullable'), + func('pg_catalog.pg_get_expr', [col('typdefaultbin', 't'), literal(0)])->as('default_value'), + ) + ->from(table('pg_type', 'pg_catalog')->as('t')) + ->join(table('pg_namespace', 'pg_catalog')->as('n'), eq(col('oid', 'n'), col('typnamespace', 't'))) + ->where(and_( + eq(col('nspname', 'n'), param(1)), + eq(col('typtype', 't'), literal('d')), + )) + ->orderBy(asc(col('typname', 't'))), + [$schemaName], + ); + + $domains = []; + + foreach ($rows as $row) { + $domains[] = new Domain( + $row['name'], + $this->columnTypeParser->parse($row['base_type']), + $row['nullable'], + $row['default_value'] ?? null, + $this->readDomainCheckConstraints($row['name'], $schemaName), + ); + } + + return $domains; + } + + /** + * @return list + */ + private function readExcludeConstraints(string $tableName, string $schemaName) : array + { + $rows = $this->client->fetchAllInto( + type_mapper(type_structure([ + 'name' => type_string(), + 'definition' => type_string(), + ])), + select( + col('conname', 'con')->as('name'), + func('pg_catalog.pg_get_constraintdef', [col('oid', 'con')])->as('definition'), + ) + ->from(table('pg_constraint', 'pg_catalog')->as('con')) + ->join(table('pg_class', 'pg_catalog')->as('c'), eq(col('oid', 'c'), col('conrelid', 'con'))) + ->join(table('pg_namespace', 'pg_catalog')->as('n'), eq(col('oid', 'n'), col('relnamespace', 'c'))) + ->where(and_( + eq(col('relname', 'c'), param(1)), + eq(col('nspname', 'n'), param(2)), + eq(col('contype', 'con'), literal('x')), + )) + ->orderBy(asc(col('conname', 'con'))), + [$tableName, $schemaName], + ); + + $constraints = []; + + foreach ($rows as $row) { + $constraints[] = new ExcludeConstraint($row['definition'], $row['name']); + } + + return $constraints; + } + + /** + * @return list + */ + private function readExtensions(string $schemaName) : array + { + $rows = $this->client->fetchAllInto( + type_mapper(type_structure([ + 'name' => type_string(), + ], [ + 'version' => type_union(type_string(), type_null()), + ])), + select( + col('extname', 'e')->as('name'), + col('extversion', 'e')->as('version'), + ) + ->from(table('pg_extension', 'pg_catalog')->as('e')) + ->join(table('pg_namespace', 'pg_catalog')->as('n'), eq(col('oid', 'n'), col('extnamespace', 'e'))) + ->where(eq(col('nspname', 'n'), param(1))) + ->orderBy(asc(col('extname', 'e'))), + [$schemaName], + ); + + $extensions = []; + + foreach ($rows as $row) { + $extensions[] = new Extension($row['name'], $row['version'] ?? null); + } + + return $extensions; + } + + /** + * @return list + */ + private function readForeignKeys(string $tableName, string $schemaName) : array + { + $rows = $this->client->fetchAllInto( + type_mapper(type_structure([ + 'name' => type_string(), + 'columns' => type_string(), + 'reference_schema' => type_string(), + 'reference_table' => type_string(), + 'reference_columns' => type_string(), + 'on_update' => type_string(), + 'on_delete' => type_string(), + 'deferrable' => type_boolean(), + 'initially_deferred' => type_boolean(), + ])), + select( + col('conname', 'con')->as('name'), + agg('array_agg', [col('attname', 'a')], distinct: true)->withOrderBy(asc(col('attname', 'a')))->as('columns'), + col('nspname', 'nf')->as('reference_schema'), + col('relname', 'cf')->as('reference_table'), + agg('array_agg', [col('attname', 'af')], distinct: true)->withOrderBy(asc(col('attname', 'af')))->as('reference_columns'), + col('confupdtype', 'con')->as('on_update'), + col('confdeltype', 'con')->as('on_delete'), + col('condeferrable', 'con')->as('deferrable'), + col('condeferred', 'con')->as('initially_deferred'), + ) + ->from(table('pg_constraint', 'pg_catalog')->as('con')) + ->join(table('pg_class', 'pg_catalog')->as('c'), eq(col('oid', 'c'), col('conrelid', 'con'))) + ->join(table('pg_namespace', 'pg_catalog')->as('n'), eq(col('oid', 'n'), col('relnamespace', 'c'))) + ->join(table('pg_attribute', 'pg_catalog')->as('a'), and_( + eq(col('attrelid', 'a'), col('conrelid', 'con')), + any_(col('attnum', 'a'), ComparisonOperator::EQ, col('conkey', 'con')), + )) + ->join(table('pg_class', 'pg_catalog')->as('cf'), eq(col('oid', 'cf'), col('confrelid', 'con'))) + ->join(table('pg_namespace', 'pg_catalog')->as('nf'), eq(col('oid', 'nf'), col('relnamespace', 'cf'))) + ->join(table('pg_attribute', 'pg_catalog')->as('af'), and_( + eq(col('attrelid', 'af'), col('confrelid', 'con')), + any_(col('attnum', 'af'), ComparisonOperator::EQ, col('confkey', 'con')), + )) + ->where(and_( + eq(col('relname', 'c'), param(1)), + eq(col('nspname', 'n'), param(2)), + eq(col('contype', 'con'), literal('f')), + )) + ->groupBy( + col('conname', 'con'), + col('nspname', 'nf'), + col('relname', 'cf'), + col('confupdtype', 'con'), + col('confdeltype', 'con'), + col('condeferrable', 'con'), + col('condeferred', 'con'), + ), + [$tableName, $schemaName], + ); + + $foreignKeys = []; + + foreach ($rows as $row) { + $foreignKeys[] = new ForeignKey( + $row['name'], + $this->parseArrayLiteral($row['columns']), + $row['reference_schema'], + $row['reference_table'], + $this->parseArrayLiteral($row['reference_columns']), + $this->mapReferentialAction($row['on_update']), + $this->mapReferentialAction($row['on_delete']), + $row['deferrable'], + $row['initially_deferred'], + ); + } + + return $foreignKeys; + } + + /** + * @return list + */ + private function readFunctions(string $schemaName) : array + { + $rows = $this->client->fetchAllInto( + type_mapper(type_structure([ + 'name' => type_string(), + 'return_type' => type_string(), + 'arguments' => type_string(), + 'language' => type_string(), + 'definition' => type_string(), + 'is_strict' => type_boolean(), + ], [ + 'volatility' => type_union(type_string(), type_null()), + ])), + select( + col('proname', 'p')->as('name'), + func('pg_catalog.pg_get_function_result', [col('oid', 'p')])->as('return_type'), + func('pg_catalog.pg_get_function_arguments', [col('oid', 'p')])->as('arguments'), + col('lanname', 'l')->as('language'), + col('prosrc', 'p')->as('definition'), + col('proisstrict', 'p')->as('is_strict'), + case_when( + [when(literal('i'), literal('immutable')), when(literal('s'), literal('stable')), when(literal('v'), literal('volatile'))], + operand: col('provolatile', 'p'), + )->as('volatility'), + ) + ->from(table('pg_proc', 'pg_catalog')->as('p')) + ->join(table('pg_namespace', 'pg_catalog')->as('n'), eq(col('oid', 'n'), col('pronamespace', 'p'))) + ->join(table('pg_language', 'pg_catalog')->as('l'), eq(col('oid', 'l'), col('prolang', 'p'))) + ->where(and_( + eq(col('nspname', 'n'), param(1)), + eq(col('prokind', 'p'), literal('f')), + )) + ->orderBy(asc(col('proname', 'p'))), + [$schemaName], + ); + + $functions = []; + + foreach ($rows as $row) { + $functions[] = new Func( + $row['name'], + $row['return_type'], + $this->parseArgumentTypes($row['arguments']), + $row['language'], + $row['definition'], + $row['is_strict'], + array_key_exists('volatility', $row) && $row['volatility'] !== null ? FunctionVolatility::from($row['volatility']) : null, + ); + } + + return $functions; + } + + /** + * @return list + */ + private function readIndexes(string $tableName, string $schemaName) : array + { + $rows = $this->client->fetchAllInto( + type_mapper(type_structure([ + 'name' => type_string(), + 'is_unique' => type_boolean(), + 'is_primary' => type_boolean(), + 'method' => type_string(), + 'columns' => type_string(), + ], [ + 'predicate' => type_union(type_string(), type_null()), + ])), + select( + col('relname', 'i')->as('name'), + col('indisunique', 'ix')->as('is_unique'), + col('indisprimary', 'ix')->as('is_primary'), + col('amname', 'am')->as('method'), + agg('array_agg', [col('attname', 'a')])->withOrderBy(asc(func('array_position', [cast(col('indkey', 'ix'), ColumnType::array(ColumnType::integer())), col('attnum', 'a')])))->as('columns'), + func('pg_catalog.pg_get_expr', [col('indpred', 'ix'), col('indrelid', 'ix')])->as('predicate'), + ) + ->from(table('pg_index', 'pg_catalog')->as('ix')) + ->join(table('pg_class', 'pg_catalog')->as('i'), eq(col('oid', 'i'), col('indexrelid', 'ix'))) + ->join(table('pg_class', 'pg_catalog')->as('t'), eq(col('oid', 't'), col('indrelid', 'ix'))) + ->join(table('pg_namespace', 'pg_catalog')->as('n'), eq(col('oid', 'n'), col('relnamespace', 't'))) + ->join(table('pg_am', 'pg_catalog')->as('am'), eq(col('oid', 'am'), col('relam', 'i'))) + ->join(table('pg_attribute', 'pg_catalog')->as('a'), and_( + eq(col('attrelid', 'a'), col('oid', 't')), + any_(col('attnum', 'a'), ComparisonOperator::EQ, col('indkey', 'ix')), + )) + ->leftJoin( + table('pg_constraint', 'pg_catalog')->as('con'), + eq(col('conindid', 'con'), col('indexrelid', 'ix')), + ) + ->where(and_( + eq(col('relname', 't'), param(1)), + eq(col('nspname', 'n'), param(2)), + gt(col('attnum', 'a'), literal(0)), + is_null(col('conindid', 'con')), + )) + ->groupBy( + col('relname', 'i'), + col('indisunique', 'ix'), + col('indisprimary', 'ix'), + col('amname', 'am'), + col('indpred', 'ix'), + col('indrelid', 'ix'), + ) + ->orderBy(asc(col('relname', 'i'))), + [$tableName, $schemaName], + ); + + $indexes = []; + + foreach ($rows as $row) { + $indexes[] = new Index( + $row['name'], + $this->parseArrayLiteral($row['columns']), + $row['is_unique'], + $this->mapIndexMethod($row['method']), + $row['is_primary'], + $row['predicate'] ?? null, + ); + } + + return $indexes; + } + + /** + * @return list + */ + private function readInherits(string $tableName, string $schemaName) : array + { + $rows = $this->client->fetchAllInto( + type_mapper(type_structure(['parent' => type_string()])), + select( + concat(col('nspname', 'pn'), literal('.'), col('relname', 'pc'))->as('parent'), + ) + ->from(table('pg_inherits', 'pg_catalog')->as('i')) + ->join(table('pg_class', 'pg_catalog')->as('c'), eq(col('oid', 'c'), col('inhrelid', 'i'))) + ->join(table('pg_namespace', 'pg_catalog')->as('n'), eq(col('oid', 'n'), col('relnamespace', 'c'))) + ->join(table('pg_class', 'pg_catalog')->as('pc'), eq(col('oid', 'pc'), col('inhparent', 'i'))) + ->join(table('pg_namespace', 'pg_catalog')->as('pn'), eq(col('oid', 'pn'), col('relnamespace', 'pc'))) + ->where(and_( + eq(col('relname', 'c'), param(1)), + eq(col('nspname', 'n'), param(2)), + )) + ->orderBy(asc(col('inhseqno', 'i'))), + [$tableName, $schemaName], + ); + + return \array_map(static fn (array $row) : string => $row['parent'], $rows); + } + + /** + * @return list + */ + private function readMaterializedViews(string $schemaName) : array + { + $rows = $this->client->fetchAllInto( + type_mapper(type_structure([ + 'name' => type_string(), + 'definition' => type_string(), + ])), + select( + col('matviewname')->as('name'), + col('definition'), + ) + ->from(table('pg_matviews', 'pg_catalog')) + ->where(eq(col('schemaname'), param(1))) + ->orderBy(asc(col('matviewname'))), + [$schemaName], + ); + + $views = []; + + foreach ($rows as $row) { + $views[] = new MaterializedView($row['name'], $row['definition']); + } + + return $views; + } + + /** + * @return array{0: PartitionStrategy, 1: list} + */ + private function readPartitionInfo(string $tableName, string $schemaName) : array + { + $rows = $this->client->fetchAllInto( + type_mapper(type_structure(['partdef' => type_string()])), + select( + func('pg_catalog.pg_get_partkeydef', [col('oid', 'c')])->as('partdef'), + ) + ->from(table('pg_class', 'pg_catalog')->as('c')) + ->join(table('pg_namespace', 'pg_catalog')->as('n'), eq(col('oid', 'n'), col('relnamespace', 'c'))) + ->where(and_( + eq(col('relname', 'c'), param(1)), + eq(col('nspname', 'n'), param(2)), + )), + [$tableName, $schemaName], + ); + + if ($rows === [] || $rows[0]['partdef'] === '') { + throw new \RuntimeException(\sprintf('Could not read partition info for table "%s"."%s".', $schemaName, $tableName)); + } + + $partdef = $rows[0]['partdef']; + + if (!\preg_match('/^(HASH|LIST|RANGE)\s*\((.+)\)$/i', $partdef, $matches)) { + throw new \RuntimeException(\sprintf('Could not parse partition definition: "%s".', $partdef)); + } + + return [ + PartitionStrategy::from(\strtolower($matches[1])), + \array_map('trim', \explode(',', $matches[2])), + ]; + } + + private function readPrimaryKey(string $tableName, string $schemaName) : ?PrimaryKey + { + $rows = $this->client->fetchAllInto( + type_mapper(type_structure([ + 'name' => type_string(), + 'columns' => type_string(), + ])), + select( + col('conname', 'con')->as('name'), + agg('array_agg', [col('attname', 'a')])->withOrderBy(asc(func('array_position', [col('conkey', 'con'), col('attnum', 'a')])))->as('columns'), + ) + ->from(table('pg_constraint', 'pg_catalog')->as('con')) + ->join(table('pg_class', 'pg_catalog')->as('c'), eq(col('oid', 'c'), col('conrelid', 'con'))) + ->join(table('pg_namespace', 'pg_catalog')->as('n'), eq(col('oid', 'n'), col('relnamespace', 'c'))) + ->join(table('pg_attribute', 'pg_catalog')->as('a'), and_( + eq(col('attrelid', 'a'), col('conrelid', 'con')), + any_(col('attnum', 'a'), ComparisonOperator::EQ, col('conkey', 'con')), + )) + ->where(and_( + eq(col('relname', 'c'), param(1)), + eq(col('nspname', 'n'), param(2)), + eq(col('contype', 'con'), literal('p')), + )) + ->groupBy(col('conname', 'con')), + [$tableName, $schemaName], + ); + + if ($rows === []) { + return null; + } + + return new PrimaryKey( + $this->parseArrayLiteral($rows[0]['columns']), + $rows[0]['name'], + ); + } + + /** + * @return list + */ + private function readProcedures(string $schemaName) : array + { + $rows = $this->client->fetchAllInto( + type_mapper(type_structure([ + 'name' => type_string(), + 'arguments' => type_string(), + 'language' => type_string(), + ], [ + 'definition' => type_union(type_string(), type_null()), + ])), + select( + col('proname', 'p')->as('name'), + func('pg_catalog.pg_get_function_arguments', [col('oid', 'p')])->as('arguments'), + col('lanname', 'l')->as('language'), + col('prosrc', 'p')->as('definition'), + ) + ->from(table('pg_proc', 'pg_catalog')->as('p')) + ->join(table('pg_namespace', 'pg_catalog')->as('n'), eq(col('oid', 'n'), col('pronamespace', 'p'))) + ->join(table('pg_language', 'pg_catalog')->as('l'), eq(col('oid', 'l'), col('prolang', 'p'))) + ->where(and_( + eq(col('nspname', 'n'), param(1)), + eq(col('prokind', 'p'), literal('p')), + )) + ->orderBy(asc(col('proname', 'p'))), + [$schemaName], + ); + + $procedures = []; + + foreach ($rows as $row) { + $procedures[] = new Procedure( + $row['name'], + $this->parseArgumentTypes($row['arguments']), + $row['language'], + $row['definition'] ?? null, + ); + } + + return $procedures; + } + + private function readSchema(string $schemaName) : Schema + { + $tables = []; + + foreach ($this->readTableNames($schemaName) as $tableInfo) { + $tables[] = $this->readTable( + $tableInfo['relname'], + $schemaName, + $tableInfo['relpersistence'] === 'u', + $tableInfo['relkind'], + $tableInfo['tablespace'] ?? null, + ); + } + + return new Schema( + $schemaName, + $tables, + $this->readSequences($schemaName), + $this->readViews($schemaName), + $this->readMaterializedViews($schemaName), + $this->readFunctions($schemaName), + $this->readProcedures($schemaName), + $this->readDomains($schemaName), + $this->readExtensions($schemaName), + ); + } + + /** + * @return list + */ + private function readSequences(string $schemaName) : array + { + $intOrString = type_union(type_integer(), type_string()); + + $rows = $this->client->fetchAllInto( + type_mapper(type_structure([ + 'name' => type_string(), + 'data_type' => type_string(), + 'start_value' => $intOrString, + 'min_value' => $intOrString, + 'increment_by' => $intOrString, + 'cycle' => type_boolean(), + 'cache_value' => $intOrString, + ], [ + 'max_value' => type_union(type_integer(), type_string(), type_null()), + 'owned_by_table' => type_union(type_string(), type_null()), + 'owned_by_column' => type_union(type_string(), type_null()), + ])), + select( + col('relname', 'c')->as('name'), + func('pg_catalog.format_type', [col('seqtypid', 's'), literal(null)])->as('data_type'), + col('seqstart', 's')->as('start_value'), + col('seqmin', 's')->as('min_value'), + col('seqmax', 's')->as('max_value'), + col('seqincrement', 's')->as('increment_by'), + col('seqcycle', 's')->as('cycle'), + col('seqcache', 's')->as('cache_value'), + col('relname', 'dep_c')->as('owned_by_table'), + col('attname', 'dep_a')->as('owned_by_column'), + ) + ->from(table('pg_sequence', 'pg_catalog')->as('s')) + ->join(table('pg_class', 'pg_catalog')->as('c'), eq(col('oid', 'c'), col('seqrelid', 's'))) + ->join(table('pg_namespace', 'pg_catalog')->as('n'), eq(col('oid', 'n'), col('relnamespace', 'c'))) + ->leftJoin(table('pg_depend', 'pg_catalog')->as('d'), and_( + eq(col('objid', 'd'), col('seqrelid', 's')), + eq(col('deptype', 'd'), literal('a')), + )) + ->leftJoin(table('pg_class', 'pg_catalog')->as('dep_c'), eq(col('oid', 'dep_c'), col('refobjid', 'd'))) + ->leftJoin(table('pg_attribute', 'pg_catalog')->as('dep_a'), and_( + eq(col('attrelid', 'dep_a'), col('refobjid', 'd')), + eq(col('attnum', 'dep_a'), col('refobjsubid', 'd')), + )) + ->where(eq(col('nspname', 'n'), param(1))) + ->orderBy(asc(col('relname', 'c'))), + [$schemaName], + ); + + $sequences = []; + + foreach ($rows as $row) { + if (($row['owned_by_table'] ?? null) !== null) { + continue; + } + + $sequences[] = new Sequence( + $row['name'], + $row['data_type'], + $row['start_value'], + $row['min_value'], + $row['max_value'] ?? null, + $row['increment_by'], + $row['cycle'], + $row['cache_value'], + null, + null, + ); + } + + return $sequences; + } + + private function readTable(string $tableName, string $schemaName, bool $unlogged = false, string $relkind = 'r', ?string $tablespace = null) : Table + { + $partitionStrategy = null; + $partitionColumns = []; + + if ($relkind === 'p') { + [$partitionStrategy, $partitionColumns] = $this->readPartitionInfo($tableName, $schemaName); + } + + $inherits = $relkind === 'r' ? $this->readInherits($tableName, $schemaName) : []; + + return new Table( + $schemaName, + $tableName, + $this->readColumns($tableName, $schemaName), + $this->readPrimaryKey($tableName, $schemaName), + $this->readIndexes($tableName, $schemaName), + $this->readForeignKeys($tableName, $schemaName), + $this->readUniqueConstraints($tableName, $schemaName), + $this->readCheckConstraints($tableName, $schemaName), + $this->readExcludeConstraints($tableName, $schemaName), + $this->readTriggers($tableName, $schemaName), + $unlogged, + $partitionStrategy, + $partitionColumns, + $inherits, + $tablespace, + ); + } + + /** + * @return list + */ + private function readTableNames(string $schemaName) : array + { + $conditions = and_( + eq(col('nspname', 'n'), param(1)), + in_(col('relkind', 'c'), [literal('r'), literal('p')]), + ); + + if ($this->excludeTables !== []) { + $conditions = and_( + $conditions, + not_(in_(col('relname', 'c'), \array_map(static fn (string $t) : Literal => literal($t), $this->excludeTables))), + ); + } + + return \array_values($this->client->fetchAllInto( + type_mapper(type_structure([ + 'relname' => type_string(), + 'relpersistence' => type_string(), + 'relkind' => type_string(), + ], [ + 'tablespace' => type_union(type_string(), type_null()), + ])), + select( + col('relname', 'c'), + col('relpersistence', 'c'), + col('relkind', 'c'), + case_when( + [when(eq(col('reltablespace', 'c'), literal(0)), Literal::null())], + elseResult: col('spcname', 'ts'), + )->as('tablespace'), + ) + ->from(table('pg_class', 'pg_catalog')->as('c')) + ->join(table('pg_namespace', 'pg_catalog')->as('n'), eq(col('oid', 'n'), col('relnamespace', 'c'))) + ->leftJoin(table('pg_tablespace', 'pg_catalog')->as('ts'), eq(col('oid', 'ts'), col('reltablespace', 'c'))) + ->where($conditions) + ->orderBy(asc(col('relname', 'c'))), + [$schemaName], + )); + } + + /** + * @return list + */ + private function readTriggers(string $tableName, string $schemaName) : array + { + $rows = $this->client->fetchAllInto( + type_mapper(type_structure([ + 'name' => type_string(), + 'function_name' => type_string(), + 'type' => type_integer(), + ])), + select( + col('tgname', 't')->as('name'), + col('proname', 'p')->as('function_name'), + col('tgtype', 't')->as('type'), + ) + ->from(table('pg_trigger', 'pg_catalog')->as('t')) + ->join(table('pg_class', 'pg_catalog')->as('c'), eq(col('oid', 'c'), col('tgrelid', 't'))) + ->join(table('pg_namespace', 'pg_catalog')->as('n'), eq(col('oid', 'n'), col('relnamespace', 'c'))) + ->join(table('pg_proc', 'pg_catalog')->as('p'), eq(col('oid', 'p'), col('tgfoid', 't'))) + ->where(and_( + eq(col('relname', 'c'), param(1)), + eq(col('nspname', 'n'), param(2)), + not_(is_true(col('tgisinternal', 't'))), + )) + ->orderBy(asc(col('tgname', 't'))), + [$tableName, $schemaName], + ); + + $triggers = []; + + foreach ($rows as $row) { + $tgtype = $row['type']; + + if ($tgtype & 64) { + $timing = TriggerTiming::INSTEAD_OF; + } elseif ($tgtype & 2) { + $timing = TriggerTiming::BEFORE; + } else { + $timing = TriggerTiming::AFTER; + } + + $events = []; + + if ($tgtype & 4) { + $events[] = TriggerEvent::INSERT; + } + + if ($tgtype & 8) { + $events[] = TriggerEvent::DELETE; + } + + if ($tgtype & 16) { + $events[] = TriggerEvent::UPDATE; + } + + if ($tgtype & 32) { + $events[] = TriggerEvent::TRUNCATE; + } + + if ($events === []) { + continue; + } + + $triggers[] = new Trigger( + $row['name'], + $tableName, + $timing, + $events, + $row['function_name'], + ($tgtype & 1) !== 0, + ); + } + + return $triggers; + } + + /** + * @return list + */ + private function readUniqueConstraints(string $tableName, string $schemaName) : array + { + $rows = $this->client->fetchAllInto( + type_mapper(type_structure([ + 'name' => type_string(), + 'columns' => type_string(), + ])), + select( + col('conname', 'con')->as('name'), + agg('array_agg', [col('attname', 'a')])->withOrderBy(asc(func('array_position', [col('conkey', 'con'), col('attnum', 'a')])))->as('columns'), + ) + ->from(table('pg_constraint', 'pg_catalog')->as('con')) + ->join(table('pg_class', 'pg_catalog')->as('c'), eq(col('oid', 'c'), col('conrelid', 'con'))) + ->join(table('pg_namespace', 'pg_catalog')->as('n'), eq(col('oid', 'n'), col('relnamespace', 'c'))) + ->join(table('pg_attribute', 'pg_catalog')->as('a'), and_( + eq(col('attrelid', 'a'), col('conrelid', 'con')), + any_(col('attnum', 'a'), ComparisonOperator::EQ, col('conkey', 'con')), + )) + ->where(and_( + eq(col('relname', 'c'), param(1)), + eq(col('nspname', 'n'), param(2)), + eq(col('contype', 'con'), literal('u')), + )) + ->groupBy(col('conname', 'con')), + [$tableName, $schemaName], + ); + + $constraints = []; + + foreach ($rows as $row) { + $constraints[] = new UniqueConstraint( + $this->parseArrayLiteral($row['columns']), + $row['name'], + ); + } + + return $constraints; + } + + /** + * @return list + */ + private function readViews(string $schemaName) : array + { + $rows = $this->client->fetchAllInto( + type_mapper(type_structure([ + 'name' => type_string(), + 'definition' => type_string(), + ])), + select( + col('viewname')->as('name'), + col('definition'), + ) + ->from(table('pg_views', 'pg_catalog')) + ->where(eq(col('schemaname'), param(1))) + ->orderBy(asc(col('viewname'))), + [$schemaName], + ); + + $views = []; + + foreach ($rows as $row) { + $views[] = new View($row['name'], $row['definition']); + } + + return $views; + } + + /** + * @return list + */ + private function resolveSchemaNames() : array + { + return $this->schemaNames ?? \array_values(\array_map( + static fn (array $row) : string => $row['nspname'], + $this->client->fetchAllInto( + type_mapper(type_structure(['nspname' => type_string()])), + select(col('nspname')) + ->from(table('pg_namespace', 'pg_catalog')) + ->where(and_( + not_like(col('nspname'), literal('pg_%')), + ne(col('nspname'), literal('information_schema')), + )) + ->orderBy(asc(col('nspname'))), + ), + )); + } + + private function stripCheckWrapper(string $definition) : string + { + if (\str_starts_with($definition, 'CHECK (') && \str_ends_with($definition, ')')) { + return \substr($definition, 7, -1); + } + + return $definition; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Client/Infrastructure/PgSql/PgSqlClient.php b/src/lib/postgresql/src/Flow/PostgreSql/Client/Infrastructure/PgSql/PgSqlClient.php index 7958f79229..bd69aa7cc3 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/Client/Infrastructure/PgSql/PgSqlClient.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/Client/Infrastructure/PgSql/PgSqlClient.php @@ -7,12 +7,12 @@ use function Flow\PostgreSql\DSL\{begin, commit, release_savepoint, rollback, savepoint}; use Flow\PostgreSql\AST\Transformers\{ExplainConfig, ExplainModifier}; use Flow\PostgreSql\Client\{Client, ConnectionParameters, Cursor, RowMapper, TransactionContext, TypedValue}; -use Flow\PostgreSql\Client\Exception\{ConnectionException, MappingException, PostgreSqlError, QueryException, ResultException, TransactionException, ValueConversionException}; -use Flow\PostgreSql\Client\Types\{PostgreSqlType, ResultCaster, ValueConverters}; +use Flow\PostgreSql\Client\Exception\{ConnectionException, PostgreSqlError, QueryException, ResultException, TransactionException, ValueConversionException}; +use Flow\PostgreSql\Client\Types\{ResultCaster, ValueConverters, ValueType}; use Flow\PostgreSql\Explain\ExplainParser; use Flow\PostgreSql\Explain\Plan\Plan; use Flow\PostgreSql\Parser; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; use PgSql\{Connection, Result}; final class PgSqlClient implements Client @@ -27,7 +27,6 @@ private function __construct( private ?Connection $connection, private readonly ConnectionParameters $connectionParameters, private readonly ValueConverters $valueConverters, - private readonly ?RowMapper $defaultMapper = null, ) { $this->resultCaster = new ResultCaster(); $this->transactionContext = new TransactionContext(); @@ -39,14 +38,13 @@ private function __construct( public static function connect( ConnectionParameters $params, ?ValueConverters $valueConverters = null, - ?RowMapper $mapper = null, ) : self { if (!\extension_loaded('pgsql')) { throw ConnectionException::extensionNotLoaded('pgsql'); } \error_clear_last(); - $connection = @\pg_connect($params->toString()); + $connection = @\pg_connect($params->toString(), \PGSQL_CONNECT_FORCE_NEW); if ($connection === false) { $error = \error_get_last(); @@ -58,7 +56,6 @@ public static function connect( $connection, $params, $valueConverters ?? ValueConverters::create(), - $mapper, ); } @@ -107,14 +104,14 @@ public function converters() : ValueConverters return $this->valueConverters; } - public function cursor(SqlQuery|string $sql, array $parameters = []) : Cursor + public function cursor(Sql|string $sql, array $parameters = []) : Cursor { $result = $this->query($sql, $parameters); - return new PgSqlCursor($result, $this->defaultMapper); + return new PgSqlCursor($result); } - public function execute(SqlQuery|string $sql, array $parameters = []) : int + public function execute(Sql|string $sql, array $parameters = []) : int { $result = $this->query($sql, $parameters); $affected = \pg_affected_rows($result); @@ -123,10 +120,10 @@ public function execute(SqlQuery|string $sql, array $parameters = []) : int return $affected; } - public function explain(SqlQuery|string $sql, array $parameters = [], ?ExplainConfig $config = null) : Plan + public function explain(Sql|string $sql, array $parameters = [], ?ExplainConfig $config = null) : Plan { $config ??= ExplainConfig::forAnalysis(); - $query = $sql instanceof SqlQuery ? $sql->toSql() : $sql; + $query = $sql instanceof Sql ? $sql->toSql() : $sql; $parsed = (new Parser())->parse($query); $parsed->traverse(new ExplainModifier($config)); @@ -137,7 +134,7 @@ public function explain(SqlQuery|string $sql, array $parameters = [], ?ExplainCo return (new ExplainParser())->parse($jsonOutput); } - public function fetch(SqlQuery|string $sql, array $parameters = []) : ?array + public function fetch(Sql|string $sql, array $parameters = []) : ?array { $result = $this->query($sql, $parameters); $row = \pg_fetch_assoc($result); @@ -154,7 +151,7 @@ public function fetch(SqlQuery|string $sql, array $parameters = []) : ?array return $converted; } - public function fetchAll(SqlQuery|string $sql, array $parameters = []) : array + public function fetchAll(Sql|string $sql, array $parameters = []) : array { $result = $this->query($sql, $parameters); $rows = \pg_fetch_all($result) ?: []; @@ -172,41 +169,31 @@ public function fetchAll(SqlQuery|string $sql, array $parameters = []) : array } public function fetchAllInto( - string $class, - SqlQuery|string $sql, + RowMapper $mapper, + Sql|string $sql, array $parameters = [], - ?RowMapper $mapper = null, ) : array { - $rows = $this->fetchAll($sql, $parameters); - - if ($rows === []) { - return []; - } - - $mapper = $this->resolveMapper($mapper); - - return \array_map( - static fn (array $row) => $mapper->map($class, $row), - $rows, - ); + return \array_values(\array_map( + static fn (array $row) => $mapper->map($row), + $this->fetchAll($sql, $parameters), + )); } public function fetchInto( - string $class, - SqlQuery|string $sql, + RowMapper $mapper, + Sql|string $sql, array $parameters = [], - ?RowMapper $mapper = null, - ) : ?object { + ) : mixed { $row = $this->fetch($sql, $parameters); if ($row === null) { return null; } - return $this->resolveMapper($mapper)->map($class, $row); + return $mapper->map($row); } - public function fetchOne(SqlQuery|string $sql, array $parameters = []) : array + public function fetchOne(Sql|string $sql, array $parameters = []) : array { $result = $this->query($sql, $parameters); $count = \pg_num_rows($result); @@ -238,15 +225,14 @@ public function fetchOne(SqlQuery|string $sql, array $parameters = []) : array } public function fetchOneInto( - string $class, - SqlQuery|string $sql, + RowMapper $mapper, + Sql|string $sql, array $parameters = [], - ?RowMapper $mapper = null, - ) : object { - return $this->resolveMapper($mapper)->map($class, $this->fetchOne($sql, $parameters)); + ) : mixed { + return $mapper->map($this->fetchOne($sql, $parameters)); } - public function fetchScalar(SqlQuery|string $sql, array $parameters = []) : mixed + public function fetchScalar(Sql|string $sql, array $parameters = []) : mixed { $result = $this->query($sql, $parameters); @@ -273,7 +259,7 @@ public function fetchScalar(SqlQuery|string $sql, array $parameters = []) : mixe return $value; } - public function fetchScalarBool(SqlQuery|string $sql, array $parameters = []) : bool + public function fetchScalarBool(Sql|string $sql, array $parameters = []) : bool { $value = $this->fetchScalar($sql, $parameters); @@ -284,7 +270,7 @@ public function fetchScalarBool(SqlQuery|string $sql, array $parameters = []) : return $value; } - public function fetchScalarFloat(SqlQuery|string $sql, array $parameters = []) : float + public function fetchScalarFloat(Sql|string $sql, array $parameters = []) : float { $value = $this->fetchScalar($sql, $parameters); @@ -295,7 +281,7 @@ public function fetchScalarFloat(SqlQuery|string $sql, array $parameters = []) : return $value; } - public function fetchScalarInt(SqlQuery|string $sql, array $parameters = []) : int + public function fetchScalarInt(Sql|string $sql, array $parameters = []) : int { $value = $this->fetchScalar($sql, $parameters); @@ -306,7 +292,7 @@ public function fetchScalarInt(SqlQuery|string $sql, array $parameters = []) : i return $value; } - public function fetchScalarString(SqlQuery|string $sql, array $parameters = []) : string + public function fetchScalarString(Sql|string $sql, array $parameters = []) : string { $value = $this->fetchScalar($sql, $parameters); @@ -427,14 +413,14 @@ private function convertParameters(array $parameters) : array if ($value === null) { $converted[] = null; } elseif ($value instanceof TypedValue) { - $converter = $this->valueConverters->forPostgreSqlType($value->targetType); + $converter = $this->valueConverters->forValueType($value->targetType); $converted[] = $converter->toDatabase($value->value); } else { if (\is_array($value)) { throw ValueConversionException::ambiguousArrayType(); } - $converted[] = $this->valueConverters->forPostgreSqlType(PostgreSqlType::TEXT)->toDatabase($value); + $converted[] = $this->valueConverters->forValueType(ValueType::TEXT)->toDatabase($value); } } @@ -466,7 +452,7 @@ private function convertRow(Result $result, array $row) : array return $converted; } - private function executeTransactionCommand(SqlQuery $query, callable $exceptionFactory) : void + private function executeTransactionCommand(Sql $query, callable $exceptionFactory) : void { /** @var Connection $connection */ $connection = $this->connection; @@ -518,14 +504,14 @@ private function extractError(Connection $connection, ?Result $result) : Postgre /** * @param array $parameters */ - private function query(SqlQuery|string $sql, array $parameters) : Result + private function query(Sql|string $sql, array $parameters) : Result { $this->assertConnected(); /** @var Connection $connection */ $connection = $this->connection; - $query = $sql instanceof SqlQuery ? $sql->toSql() : $sql; + $query = $sql instanceof Sql ? $sql->toSql() : $sql; $convertedParams = $this->convertParameters($parameters); $success = @\pg_send_query_params($connection, $query, $convertedParams); @@ -557,15 +543,4 @@ private function query(SqlQuery|string $sql, array $parameters) : Result return $result; } - - private function resolveMapper(?RowMapper $mapper) : RowMapper - { - $resolved = $mapper ?? $this->defaultMapper; - - if ($resolved === null) { - throw MappingException::noMapperConfigured(); - } - - return $resolved; - } } diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Client/Infrastructure/PgSql/PgSqlCursor.php b/src/lib/postgresql/src/Flow/PostgreSql/Client/Infrastructure/PgSql/PgSqlCursor.php index 1818c5affd..aa25d0a011 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/Client/Infrastructure/PgSql/PgSqlCursor.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/Client/Infrastructure/PgSql/PgSqlCursor.php @@ -5,7 +5,6 @@ namespace Flow\PostgreSql\Client\Infrastructure\PgSql; use Flow\PostgreSql\Client\{Cursor, RowMapper}; -use Flow\PostgreSql\Client\Exception\MappingException; use Flow\PostgreSql\Client\Types\ResultCaster; use PgSql\Result; @@ -20,7 +19,7 @@ final class PgSqlCursor implements Cursor private readonly ResultCaster $resultCaster; - public function __construct(private ?Result $result, private readonly ?RowMapper $defaultMapper = null) + public function __construct(private ?Result $result) { $this->resultCaster = new ResultCaster(); } @@ -59,16 +58,10 @@ public function iterate() : \Generator $this->free(); } - public function map(string $class, ?RowMapper $mapper = null) : \Generator + public function map(RowMapper $mapper) : \Generator { - $resolved = $mapper ?? $this->defaultMapper; - - if ($resolved === null) { - throw MappingException::noMapperConfigured(); - } - foreach ($this->iterate() as $row) { - yield $resolved->map($class, $row); + yield $mapper->map($row); } } diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Client/RowMapper.php b/src/lib/postgresql/src/Flow/PostgreSql/Client/RowMapper.php index 1bb72c7847..80ca9dd0a9 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/Client/RowMapper.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/Client/RowMapper.php @@ -5,30 +5,20 @@ namespace Flow\PostgreSql\Client; /** - * Contract for mapping database rows to objects. + * Contract for mapping database rows to typed results. * - * Implementations can provide various hydration strategies: - * - Reflection-based mapping - * - Constructor mapping - * - Named arguments mapping - * - Custom attribute-based mapping - * - * External libraries (like Symfony Serializer, JMS Serializer, etc.) - * can implement this interface to integrate with the client. + * @template T */ interface RowMapper { /** - * Map a database row to an object of the specified class. - * - * @template T of object + * Map a database row to a typed result. * - * @param class-string $class Target class for mapping * @param array $row Database row as associative array * * @throws Exception\MappingException When mapping fails * - * @return T Instance of the target class + * @return T */ - public function map(string $class, array $row) : object; + public function map(array $row) : mixed; } diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Client/RowMapper/ConstructorMapper.php b/src/lib/postgresql/src/Flow/PostgreSql/Client/RowMapper/ConstructorMapper.php index f1ddd96a99..da321f8fa5 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/Client/RowMapper/ConstructorMapper.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/Client/RowMapper/ConstructorMapper.php @@ -8,7 +8,7 @@ use Flow\PostgreSql\Client\RowMapper; /** - * Default mapper that maps database rows directly to constructor parameters. + * Maps database rows directly to constructor parameters. * * Requirements: * - SQL column names must match constructor parameter names exactly (1:1) @@ -16,23 +16,34 @@ * - Use SQL aliases if column names differ from parameter names: * SELECT created_at AS createdAt FROM users * - * For advanced mapping (case conversion, nested objects, attributes), - * use the Valinor bridge. + * @template T of object + * + * @implements RowMapper */ final readonly class ConstructorMapper implements RowMapper { - public function map(string $class, array $row) : object + /** + * @param class-string $class + */ + public function __construct(private string $class) + { + } + + /** + * @return T + */ + public function map(array $row) : object { - if (!\class_exists($class)) { - throw MappingException::mappingFailed($class, 'Class does not exist'); + if (!\class_exists($this->class)) { + throw MappingException::mappingFailed($this->class, 'Class does not exist'); } - $reflection = new \ReflectionClass($class); + $reflection = new \ReflectionClass($this->class); $constructor = $reflection->getConstructor(); if ($constructor === null) { - throw MappingException::mappingFailed($class, 'Class has no constructor'); + throw MappingException::mappingFailed($this->class, 'Class has no constructor'); } $args = []; @@ -47,14 +58,14 @@ public function map(string $class, array $row) : object } elseif ($param->allowsNull()) { $args[$paramName] = null; } else { - throw MappingException::propertyNotFound($class, $paramName); + throw MappingException::propertyNotFound($this->class, $paramName); } } try { return $reflection->newInstanceArgs($args); } catch (\Throwable $e) { - throw MappingException::mappingFailed($class, $e->getMessage()); + throw MappingException::mappingFailed($this->class, $e->getMessage()); } } } diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Client/RowMapper/TypeMapper.php b/src/lib/postgresql/src/Flow/PostgreSql/Client/RowMapper/TypeMapper.php new file mode 100644 index 0000000000..b0b1bbf2d1 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Client/RowMapper/TypeMapper.php @@ -0,0 +1,33 @@ + + */ +final readonly class TypeMapper implements RowMapper +{ + /** + * @param Type $type + */ + public function __construct(private Type $type) + { + } + + /** + * @return T + */ + public function map(array $row) : mixed + { + return $this->type->assert($row); + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Client/Telemetry/TraceableClient.php b/src/lib/postgresql/src/Flow/PostgreSql/Client/Telemetry/TraceableClient.php index 31d557686c..ad78a2b2b5 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/Client/Telemetry/TraceableClient.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/Client/Telemetry/TraceableClient.php @@ -9,7 +9,7 @@ use Flow\PostgreSql\Client\Exception\QueryException; use Flow\PostgreSql\Client\Types\ValueConverters; use Flow\PostgreSql\Explain\Plan\Plan; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; use Flow\Telemetry\Logger\Logger; use Flow\Telemetry\Meter\Instrument\Histogram; use Flow\Telemetry\PackageVersion; @@ -132,9 +132,9 @@ public function converters() : ValueConverters return $this->client->converters(); } - public function cursor(SqlQuery|string $sql, array $parameters = []) : Cursor + public function cursor(Sql|string $sql, array $parameters = []) : Cursor { - $query = $sql instanceof SqlQuery ? $sql->toSql() : $sql; + $query = $sql instanceof Sql ? $sql->toSql() : $sql; $cursor = $this->client->cursor($sql, $parameters); if (!$this->telemetryConfig->options->traceQueries && !$this->telemetryConfig->options->collectMetrics) { @@ -146,9 +146,9 @@ public function cursor(SqlQuery|string $sql, array $parameters = []) : Cursor return new TraceableCursor($cursor, $this->telemetryConfig, $this->client->parameters(), $query, $parameters); } - public function execute(SqlQuery|string $sql, array $parameters = []) : int + public function execute(Sql|string $sql, array $parameters = []) : int { - $query = $sql instanceof SqlQuery ? $sql->toSql() : $sql; + $query = $sql instanceof Sql ? $sql->toSql() : $sql; return $this->traceQuery( $query, @@ -162,9 +162,9 @@ function () use ($sql, $parameters, $query) : int { ); } - public function explain(SqlQuery|string $sql, array $parameters = [], ?ExplainConfig $config = null) : Plan + public function explain(Sql|string $sql, array $parameters = [], ?ExplainConfig $config = null) : Plan { - $query = $sql instanceof SqlQuery ? $sql->toSql() : $sql; + $query = $sql instanceof Sql ? $sql->toSql() : $sql; return $this->traceQuery( $query, @@ -173,9 +173,9 @@ public function explain(SqlQuery|string $sql, array $parameters = [], ?ExplainCo ); } - public function fetch(SqlQuery|string $sql, array $parameters = []) : ?array + public function fetch(Sql|string $sql, array $parameters = []) : ?array { - $query = $sql instanceof SqlQuery ? $sql->toSql() : $sql; + $query = $sql instanceof Sql ? $sql->toSql() : $sql; return $this->traceQuery( $query, @@ -189,9 +189,9 @@ function () use ($sql, $parameters, $query) : ?array { ); } - public function fetchAll(SqlQuery|string $sql, array $parameters = []) : array + public function fetchAll(Sql|string $sql, array $parameters = []) : array { - $query = $sql instanceof SqlQuery ? $sql->toSql() : $sql; + $query = $sql instanceof Sql ? $sql->toSql() : $sql; return $this->traceQuery( $query, @@ -206,48 +206,46 @@ function () use ($sql, $parameters, $query) : array { } public function fetchAllInto( - string $class, - SqlQuery|string $sql, + RowMapper $mapper, + Sql|string $sql, array $parameters = [], - ?RowMapper $mapper = null, ) : array { - $query = $sql instanceof SqlQuery ? $sql->toSql() : $sql; + $query = $sql instanceof Sql ? $sql->toSql() : $sql; return $this->traceQuery( $query, $parameters, - function () use ($class, $sql, $parameters, $mapper, $query) : array { + function () use ($mapper, $sql, $parameters, $query) : array { $this->logQuery($query, $parameters); - return $this->client->fetchAllInto($class, $sql, $parameters, $mapper); + return $this->client->fetchAllInto($mapper, $sql, $parameters); }, static fn (array $rows) => \count($rows), ); } public function fetchInto( - string $class, - SqlQuery|string $sql, + RowMapper $mapper, + Sql|string $sql, array $parameters = [], - ?RowMapper $mapper = null, - ) : ?object { - $query = $sql instanceof SqlQuery ? $sql->toSql() : $sql; + ) : mixed { + $query = $sql instanceof Sql ? $sql->toSql() : $sql; return $this->traceQuery( $query, $parameters, - function () use ($class, $sql, $parameters, $mapper, $query) : ?object { + function () use ($mapper, $sql, $parameters, $query) : mixed { $this->logQuery($query, $parameters); - return $this->client->fetchInto($class, $sql, $parameters, $mapper); + return $this->client->fetchInto($mapper, $sql, $parameters); }, - static fn (?object $obj) => $obj !== null ? 1 : 0, + static fn (mixed $result) => $result !== null ? 1 : 0, ); } - public function fetchOne(SqlQuery|string $sql, array $parameters = []) : array + public function fetchOne(Sql|string $sql, array $parameters = []) : array { - $query = $sql instanceof SqlQuery ? $sql->toSql() : $sql; + $query = $sql instanceof Sql ? $sql->toSql() : $sql; return $this->traceQuery( $query, @@ -262,28 +260,27 @@ function () use ($sql, $parameters, $query) : array { } public function fetchOneInto( - string $class, - SqlQuery|string $sql, + RowMapper $mapper, + Sql|string $sql, array $parameters = [], - ?RowMapper $mapper = null, - ) : object { - $query = $sql instanceof SqlQuery ? $sql->toSql() : $sql; + ) : mixed { + $query = $sql instanceof Sql ? $sql->toSql() : $sql; return $this->traceQuery( $query, $parameters, - function () use ($class, $sql, $parameters, $mapper, $query) : object { + function () use ($mapper, $sql, $parameters, $query) : mixed { $this->logQuery($query, $parameters); - return $this->client->fetchOneInto($class, $sql, $parameters, $mapper); + return $this->client->fetchOneInto($mapper, $sql, $parameters); }, - static fn (object $obj) => 1, + static fn (mixed $result) => 1, ); } - public function fetchScalar(SqlQuery|string $sql, array $parameters = []) : mixed + public function fetchScalar(Sql|string $sql, array $parameters = []) : mixed { - $query = $sql instanceof SqlQuery ? $sql->toSql() : $sql; + $query = $sql instanceof Sql ? $sql->toSql() : $sql; return $this->traceQuery( $query, @@ -297,9 +294,9 @@ function () use ($sql, $parameters, $query) : mixed { ); } - public function fetchScalarBool(SqlQuery|string $sql, array $parameters = []) : bool + public function fetchScalarBool(Sql|string $sql, array $parameters = []) : bool { - $query = $sql instanceof SqlQuery ? $sql->toSql() : $sql; + $query = $sql instanceof Sql ? $sql->toSql() : $sql; return $this->traceQuery( $query, @@ -313,9 +310,9 @@ function () use ($sql, $parameters, $query) : bool { ); } - public function fetchScalarFloat(SqlQuery|string $sql, array $parameters = []) : float + public function fetchScalarFloat(Sql|string $sql, array $parameters = []) : float { - $query = $sql instanceof SqlQuery ? $sql->toSql() : $sql; + $query = $sql instanceof Sql ? $sql->toSql() : $sql; return $this->traceQuery( $query, @@ -329,9 +326,9 @@ function () use ($sql, $parameters, $query) : float { ); } - public function fetchScalarInt(SqlQuery|string $sql, array $parameters = []) : int + public function fetchScalarInt(Sql|string $sql, array $parameters = []) : int { - $query = $sql instanceof SqlQuery ? $sql->toSql() : $sql; + $query = $sql instanceof Sql ? $sql->toSql() : $sql; return $this->traceQuery( $query, @@ -345,9 +342,9 @@ function () use ($sql, $parameters, $query) : int { ); } - public function fetchScalarString(SqlQuery|string $sql, array $parameters = []) : string + public function fetchScalarString(Sql|string $sql, array $parameters = []) : string { - $query = $sql instanceof SqlQuery ? $sql->toSql() : $sql; + $query = $sql instanceof Sql ? $sql->toSql() : $sql; return $this->traceQuery( $query, diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Client/Telemetry/TraceableCursor.php b/src/lib/postgresql/src/Flow/PostgreSql/Client/Telemetry/TraceableCursor.php index e69e73921f..74d0c045fb 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/Client/Telemetry/TraceableCursor.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/Client/Telemetry/TraceableCursor.php @@ -113,10 +113,10 @@ public function iterate() : \Generator } } - public function map(string $class, ?RowMapper $mapper = null) : \Generator + public function map(RowMapper $mapper) : \Generator { try { - foreach ($this->cursor->map($class, $mapper) as $object) { + foreach ($this->cursor->map($mapper) as $object) { $this->rowsIterated++; yield $object; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Client/TypedValue.php b/src/lib/postgresql/src/Flow/PostgreSql/Client/TypedValue.php index 0af39f066e..1e5e276110 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/Client/TypedValue.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/Client/TypedValue.php @@ -4,7 +4,7 @@ namespace Flow\PostgreSql\Client; -use Flow\PostgreSql\Client\Types\PostgreSqlType; +use Flow\PostgreSql\Client\Types\ValueType; /** * Wrapper for values that need explicit type specification. @@ -16,7 +16,7 @@ { public function __construct( public mixed $value, - public PostgreSqlType $targetType, + public ValueType $targetType, ) { } } diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/BoolArrayConverter.php b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/BoolArrayConverter.php index 083fc00822..2a5cbb9f95 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/BoolArrayConverter.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/BoolArrayConverter.php @@ -5,13 +5,13 @@ namespace Flow\PostgreSql\Client\Types\Converter; use Flow\PostgreSql\Client\Exception\ValueConversionException; -use Flow\PostgreSql\Client\Types\{PostgreSqlType, ValueConverter}; +use Flow\PostgreSql\Client\Types\{ValueConverter, ValueType}; final class BoolArrayConverter implements ValueConverter { public function supportedTypes() : array { - return [PostgreSqlType::BOOL_ARRAY]; + return [ValueType::BOOL_ARRAY]; } public function toDatabase(mixed $value) : ?string diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/BooleanConverter.php b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/BooleanConverter.php index 854a7cca59..60514ddd22 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/BooleanConverter.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/BooleanConverter.php @@ -5,13 +5,13 @@ namespace Flow\PostgreSql\Client\Types\Converter; use Flow\PostgreSql\Client\Exception\ValueConversionException; -use Flow\PostgreSql\Client\Types\{PostgreSqlType, ValueConverter}; +use Flow\PostgreSql\Client\Types\{ValueConverter, ValueType}; final class BooleanConverter implements ValueConverter { public function supportedTypes() : array { - return [PostgreSqlType::BOOL]; + return [ValueType::BOOL]; } public function toDatabase(mixed $value) : ?string diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/ByteaConverter.php b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/ByteaConverter.php index 949598b328..f7dbf3eb13 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/ByteaConverter.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/ByteaConverter.php @@ -5,13 +5,13 @@ namespace Flow\PostgreSql\Client\Types\Converter; use Flow\PostgreSql\Client\Exception\ValueConversionException; -use Flow\PostgreSql\Client\Types\{PostgreSqlType, ValueConverter}; +use Flow\PostgreSql\Client\Types\{ValueConverter, ValueType}; final class ByteaConverter implements ValueConverter { public function supportedTypes() : array { - return [PostgreSqlType::BYTEA]; + return [ValueType::BYTEA]; } public function toDatabase(mixed $value) : ?string diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/CidrConverter.php b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/CidrConverter.php index 4bb11bdecd..8a8ba75713 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/CidrConverter.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/CidrConverter.php @@ -5,13 +5,13 @@ namespace Flow\PostgreSql\Client\Types\Converter; use Flow\PostgreSql\Client\Exception\ValueConversionException; -use Flow\PostgreSql\Client\Types\{PostgreSqlType, ValueConverter}; +use Flow\PostgreSql\Client\Types\{ValueConverter, ValueType}; final class CidrConverter implements ValueConverter { public function supportedTypes() : array { - return [PostgreSqlType::CIDR]; + return [ValueType::CIDR]; } public function toDatabase(mixed $value) : ?string diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/DateConverter.php b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/DateConverter.php index 0453a2206b..affc2f1742 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/DateConverter.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/DateConverter.php @@ -5,13 +5,13 @@ namespace Flow\PostgreSql\Client\Types\Converter; use Flow\PostgreSql\Client\Exception\ValueConversionException; -use Flow\PostgreSql\Client\Types\{PostgreSqlType, ValueConverter}; +use Flow\PostgreSql\Client\Types\{ValueConverter, ValueType}; final class DateConverter implements ValueConverter { public function supportedTypes() : array { - return [PostgreSqlType::DATE]; + return [ValueType::DATE]; } public function toDatabase(mixed $value) : ?string diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/DateTimeConverter.php b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/DateTimeConverter.php index 1819313a86..842fb5ab95 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/DateTimeConverter.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/DateTimeConverter.php @@ -5,15 +5,15 @@ namespace Flow\PostgreSql\Client\Types\Converter; use Flow\PostgreSql\Client\Exception\ValueConversionException; -use Flow\PostgreSql\Client\Types\{PostgreSqlType, ValueConverter}; +use Flow\PostgreSql\Client\Types\{ValueConverter, ValueType}; final class DateTimeConverter implements ValueConverter { public function supportedTypes() : array { return [ - PostgreSqlType::TIMESTAMP, - PostgreSqlType::TIMESTAMPTZ, + ValueType::TIMESTAMP, + ValueType::TIMESTAMPTZ, ]; } diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/FloatArrayConverter.php b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/FloatArrayConverter.php index d492188537..1f264fbfc2 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/FloatArrayConverter.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/FloatArrayConverter.php @@ -5,15 +5,15 @@ namespace Flow\PostgreSql\Client\Types\Converter; use Flow\PostgreSql\Client\Exception\ValueConversionException; -use Flow\PostgreSql\Client\Types\{PostgreSqlType, ValueConverter}; +use Flow\PostgreSql\Client\Types\{ValueConverter, ValueType}; final class FloatArrayConverter implements ValueConverter { public function supportedTypes() : array { return [ - PostgreSqlType::FLOAT4_ARRAY, - PostgreSqlType::FLOAT8_ARRAY, + ValueType::FLOAT4_ARRAY, + ValueType::FLOAT8_ARRAY, ]; } diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/FloatConverter.php b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/FloatConverter.php index 22798adf52..bb8382353f 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/FloatConverter.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/FloatConverter.php @@ -5,15 +5,15 @@ namespace Flow\PostgreSql\Client\Types\Converter; use Flow\PostgreSql\Client\Exception\ValueConversionException; -use Flow\PostgreSql\Client\Types\{PostgreSqlType, ValueConverter}; +use Flow\PostgreSql\Client\Types\{ValueConverter, ValueType}; final class FloatConverter implements ValueConverter { public function supportedTypes() : array { return [ - PostgreSqlType::FLOAT4, - PostgreSqlType::FLOAT8, + ValueType::FLOAT4, + ValueType::FLOAT8, ]; } diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/InetConverter.php b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/InetConverter.php index af01b83155..e4eecdb1a8 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/InetConverter.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/InetConverter.php @@ -5,13 +5,13 @@ namespace Flow\PostgreSql\Client\Types\Converter; use Flow\PostgreSql\Client\Exception\ValueConversionException; -use Flow\PostgreSql\Client\Types\{PostgreSqlType, ValueConverter}; +use Flow\PostgreSql\Client\Types\{ValueConverter, ValueType}; final class InetConverter implements ValueConverter { public function supportedTypes() : array { - return [PostgreSqlType::INET]; + return [ValueType::INET]; } public function toDatabase(mixed $value) : ?string diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/IntArrayConverter.php b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/IntArrayConverter.php index 5eaddc98f0..2509ff382a 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/IntArrayConverter.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/IntArrayConverter.php @@ -5,16 +5,16 @@ namespace Flow\PostgreSql\Client\Types\Converter; use Flow\PostgreSql\Client\Exception\ValueConversionException; -use Flow\PostgreSql\Client\Types\{PostgreSqlType, ValueConverter}; +use Flow\PostgreSql\Client\Types\{ValueConverter, ValueType}; final class IntArrayConverter implements ValueConverter { public function supportedTypes() : array { return [ - PostgreSqlType::INT2_ARRAY, - PostgreSqlType::INT4_ARRAY, - PostgreSqlType::INT8_ARRAY, + ValueType::INT2_ARRAY, + ValueType::INT4_ARRAY, + ValueType::INT8_ARRAY, ]; } diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/IntegerConverter.php b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/IntegerConverter.php index 7861920f35..55c96af6b8 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/IntegerConverter.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/IntegerConverter.php @@ -5,16 +5,16 @@ namespace Flow\PostgreSql\Client\Types\Converter; use Flow\PostgreSql\Client\Exception\ValueConversionException; -use Flow\PostgreSql\Client\Types\{PostgreSqlType, ValueConverter}; +use Flow\PostgreSql\Client\Types\{ValueConverter, ValueType}; final class IntegerConverter implements ValueConverter { public function supportedTypes() : array { return [ - PostgreSqlType::INT2, - PostgreSqlType::INT4, - PostgreSqlType::INT8, + ValueType::INT2, + ValueType::INT4, + ValueType::INT8, ]; } diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/IntervalConverter.php b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/IntervalConverter.php index 92d67e76ef..f81f17cb76 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/IntervalConverter.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/IntervalConverter.php @@ -5,13 +5,13 @@ namespace Flow\PostgreSql\Client\Types\Converter; use Flow\PostgreSql\Client\Exception\ValueConversionException; -use Flow\PostgreSql\Client\Types\{PostgreSqlType, ValueConverter}; +use Flow\PostgreSql\Client\Types\{ValueConverter, ValueType}; final class IntervalConverter implements ValueConverter { public function supportedTypes() : array { - return [PostgreSqlType::INTERVAL]; + return [ValueType::INTERVAL]; } public function toDatabase(mixed $value) : ?string diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/JsonArrayConverter.php b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/JsonArrayConverter.php index bf8eade332..d4e9724bd0 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/JsonArrayConverter.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/JsonArrayConverter.php @@ -5,15 +5,15 @@ namespace Flow\PostgreSql\Client\Types\Converter; use Flow\PostgreSql\Client\Exception\ValueConversionException; -use Flow\PostgreSql\Client\Types\{PostgreSqlType, StringEscaper, ValueConverter}; +use Flow\PostgreSql\Client\Types\{StringEscaper, ValueConverter, ValueType}; final class JsonArrayConverter implements ValueConverter { public function supportedTypes() : array { return [ - PostgreSqlType::JSON_ARRAY, - PostgreSqlType::JSONB_ARRAY, + ValueType::JSON_ARRAY, + ValueType::JSONB_ARRAY, ]; } diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/JsonConverter.php b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/JsonConverter.php index 44abd30a9b..42108f7a29 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/JsonConverter.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/JsonConverter.php @@ -5,15 +5,15 @@ namespace Flow\PostgreSql\Client\Types\Converter; use Flow\PostgreSql\Client\Exception\ValueConversionException; -use Flow\PostgreSql\Client\Types\{PostgreSqlType, ValueConverter}; +use Flow\PostgreSql\Client\Types\{ValueConverter, ValueType}; final class JsonConverter implements ValueConverter { public function supportedTypes() : array { return [ - PostgreSqlType::JSON, - PostgreSqlType::JSONB, + ValueType::JSON, + ValueType::JSONB, ]; } diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/MoneyConverter.php b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/MoneyConverter.php index bedaebc670..b809043a91 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/MoneyConverter.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/MoneyConverter.php @@ -5,13 +5,13 @@ namespace Flow\PostgreSql\Client\Types\Converter; use Flow\PostgreSql\Client\Exception\ValueConversionException; -use Flow\PostgreSql\Client\Types\{PostgreSqlType, ValueConverter}; +use Flow\PostgreSql\Client\Types\{ValueConverter, ValueType}; final class MoneyConverter implements ValueConverter { public function supportedTypes() : array { - return [PostgreSqlType::MONEY]; + return [ValueType::MONEY]; } public function toDatabase(mixed $value) : ?string diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/NumericConverter.php b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/NumericConverter.php index de9bf32f49..1bf8f083fe 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/NumericConverter.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/NumericConverter.php @@ -5,13 +5,13 @@ namespace Flow\PostgreSql\Client\Types\Converter; use Flow\PostgreSql\Client\Exception\ValueConversionException; -use Flow\PostgreSql\Client\Types\{PostgreSqlType, ValueConverter}; +use Flow\PostgreSql\Client\Types\{ValueConverter, ValueType}; final class NumericConverter implements ValueConverter { public function supportedTypes() : array { - return [PostgreSqlType::NUMERIC]; + return [ValueType::NUMERIC]; } public function toDatabase(mixed $value) : ?string diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/StringConverter.php b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/StringConverter.php index 50123e2a71..cdc13f07f0 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/StringConverter.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/StringConverter.php @@ -5,17 +5,17 @@ namespace Flow\PostgreSql\Client\Types\Converter; use Flow\PostgreSql\Client\Exception\ValueConversionException; -use Flow\PostgreSql\Client\Types\{PostgreSqlType, ValueConverter}; +use Flow\PostgreSql\Client\Types\{ValueConverter, ValueType}; final class StringConverter implements ValueConverter { public function supportedTypes() : array { return [ - PostgreSqlType::TEXT, - PostgreSqlType::VARCHAR, - PostgreSqlType::CHAR, - PostgreSqlType::BPCHAR, + ValueType::TEXT, + ValueType::VARCHAR, + ValueType::CHAR, + ValueType::BPCHAR, ]; } diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/TextArrayConverter.php b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/TextArrayConverter.php index 067149b292..4dcf9c0e67 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/TextArrayConverter.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/TextArrayConverter.php @@ -5,15 +5,15 @@ namespace Flow\PostgreSql\Client\Types\Converter; use Flow\PostgreSql\Client\Exception\ValueConversionException; -use Flow\PostgreSql\Client\Types\{PostgreSqlType, StringEscaper, ValueConverter}; +use Flow\PostgreSql\Client\Types\{StringEscaper, ValueConverter, ValueType}; final class TextArrayConverter implements ValueConverter { public function supportedTypes() : array { return [ - PostgreSqlType::TEXT_ARRAY, - PostgreSqlType::VARCHAR_ARRAY, + ValueType::TEXT_ARRAY, + ValueType::VARCHAR_ARRAY, ]; } diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/TimeConverter.php b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/TimeConverter.php index df2df0140a..0216457d5a 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/TimeConverter.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/TimeConverter.php @@ -5,15 +5,15 @@ namespace Flow\PostgreSql\Client\Types\Converter; use Flow\PostgreSql\Client\Exception\ValueConversionException; -use Flow\PostgreSql\Client\Types\{PostgreSqlType, ValueConverter}; +use Flow\PostgreSql\Client\Types\{ValueConverter, ValueType}; final class TimeConverter implements ValueConverter { public function supportedTypes() : array { return [ - PostgreSqlType::TIME, - PostgreSqlType::TIMETZ, + ValueType::TIME, + ValueType::TIMETZ, ]; } diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/UuidArrayConverter.php b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/UuidArrayConverter.php index 3e0144bea0..e17c7af7a7 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/UuidArrayConverter.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/UuidArrayConverter.php @@ -5,13 +5,13 @@ namespace Flow\PostgreSql\Client\Types\Converter; use Flow\PostgreSql\Client\Exception\ValueConversionException; -use Flow\PostgreSql\Client\Types\{PostgreSqlType, ValueConverter}; +use Flow\PostgreSql\Client\Types\{ValueConverter, ValueType}; final class UuidArrayConverter implements ValueConverter { public function supportedTypes() : array { - return [PostgreSqlType::UUID_ARRAY]; + return [ValueType::UUID_ARRAY]; } public function toDatabase(mixed $value) : ?string diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/UuidConverter.php b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/UuidConverter.php index 0f32601809..577d5560cf 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/UuidConverter.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/Converter/UuidConverter.php @@ -5,13 +5,13 @@ namespace Flow\PostgreSql\Client\Types\Converter; use Flow\PostgreSql\Client\Exception\ValueConversionException; -use Flow\PostgreSql\Client\Types\{PostgreSqlType, ValueConverter}; +use Flow\PostgreSql\Client\Types\{ValueConverter, ValueType}; final class UuidConverter implements ValueConverter { public function supportedTypes() : array { - return [PostgreSqlType::UUID]; + return [ValueType::UUID]; } public function toDatabase(mixed $value) : ?string diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/ValueConverter.php b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/ValueConverter.php index f3dd6f39a2..2a7029a01d 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/ValueConverter.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/ValueConverter.php @@ -12,7 +12,7 @@ interface ValueConverter /** * Get the PostgreSQL types this converter handles. * - * @return array + * @return array */ public function supportedTypes() : array; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/ValueConverters.php b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/ValueConverters.php index ccb4832d42..aa2f8a4d6b 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/ValueConverters.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/ValueConverters.php @@ -31,14 +31,14 @@ public static function create(PostgreSqlVersion $version = PostgreSqlVersion::V1 return new self(self::defaultConverters($version)); } - public function forPostgreSqlType(PostgreSqlType $type) : ValueConverter + public function forValueType(ValueType $type) : ValueConverter { if (isset($this->pgTypeConverters[$type->value])) { return $this->pgTypeConverters[$type->value]; } if ($this->isArrayType($type)) { - return $this->pgTypeConverters[PostgreSqlType::TEXT_ARRAY->value] + return $this->pgTypeConverters[ValueType::TEXT_ARRAY->value] ?? $this->fallbackConverter; } @@ -48,7 +48,7 @@ public function forPostgreSqlType(PostgreSqlType $type) : ValueConverter /** * Check if a converter exists for the given PostgreSQL type. */ - public function has(PostgreSqlType $type) : bool + public function has(ValueType $type) : bool { return isset($this->pgTypeConverters[$type->value]) || $this->isArrayType($type); } @@ -66,25 +66,25 @@ public function register(ValueConverter $converter) : void /** * Unregister a converter for the given PostgreSQL type. */ - public function unregister(PostgreSqlType $type) : void + public function unregister(ValueType $type) : void { unset($this->pgTypeConverters[$type->value]); } - private function isArrayType(PostgreSqlType $type) : bool + private function isArrayType(ValueType $type) : bool { return match ($type) { - PostgreSqlType::BOOL_ARRAY, - PostgreSqlType::INT2_ARRAY, - PostgreSqlType::INT4_ARRAY, - PostgreSqlType::INT8_ARRAY, - PostgreSqlType::TEXT_ARRAY, - PostgreSqlType::FLOAT4_ARRAY, - PostgreSqlType::FLOAT8_ARRAY, - PostgreSqlType::VARCHAR_ARRAY, - PostgreSqlType::UUID_ARRAY, - PostgreSqlType::JSON_ARRAY, - PostgreSqlType::JSONB_ARRAY => true, + ValueType::BOOL_ARRAY, + ValueType::INT2_ARRAY, + ValueType::INT4_ARRAY, + ValueType::INT8_ARRAY, + ValueType::TEXT_ARRAY, + ValueType::FLOAT4_ARRAY, + ValueType::FLOAT8_ARRAY, + ValueType::VARCHAR_ARRAY, + ValueType::UUID_ARRAY, + ValueType::JSON_ARRAY, + ValueType::JSONB_ARRAY => true, default => false, }; } diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/PostgreSqlType.php b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/ValueType.php similarity index 97% rename from src/lib/postgresql/src/Flow/PostgreSql/Client/Types/PostgreSqlType.php rename to src/lib/postgresql/src/Flow/PostgreSql/Client/Types/ValueType.php index 93d20e336f..ea1b1bb1d8 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/PostgreSqlType.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/Client/Types/ValueType.php @@ -4,7 +4,7 @@ namespace Flow\PostgreSql\Client\Types; -enum PostgreSqlType : int +enum ValueType : int { case BIT = 1560; case BOOL = 16; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/DSL/client.php b/src/lib/postgresql/src/Flow/PostgreSql/DSL/client.php new file mode 100644 index 0000000000..52935ca784 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/DSL/client.php @@ -0,0 +1,316 @@ +parse($dsn); +} + +/** + * Create connection parameters from individual values. + * + * Allows specifying connection parameters individually for better type safety + * and IDE support. + * + * @param string $database Database name (required) + * @param string $host Hostname (default: localhost) + * @param int $port Port number (default: 5432) + * @param null|string $user Username (optional) + * @param null|string $password Password (optional) + * @param array $options Additional libpq options + * + * @example + * $params = pgsql_connection_params( + * database: 'mydb', + * host: 'localhost', + * user: 'myuser', + * password: 'secret', + * ); + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function pgsql_connection_params( + string $database, + string $host = 'localhost', + int $port = 5432, + ?string $user = null, + ?string $password = null, + array $options = [], +) : ConnectionParameters { + return ConnectionParameters::fromParams( + database: $database, + host: $host, + port: $port, + user: $user, + password: $password, + options: $options, + ); +} + +/** + * Create a PostgreSQL client using ext-pgsql. + * + * The client connects immediately and is ready to execute queries. + * + * @param Client\ConnectionParameters $params Connection parameters + * @param null|ValueConverters $valueConverters Custom type converters (optional) + * + * @throws ConnectionException If connection fails + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function pgsql_client( + ConnectionParameters $params, + ?ValueConverters $valueConverters = null, +) : Client\Client { + return PgSqlClient::connect($params, $valueConverters); +} + +/** + * Create telemetry options for PostgreSQL client instrumentation. + * + * Controls which telemetry signals (traces, metrics, logs) are enabled + * and how query information is captured. + * + * @param bool $traceQueries Create spans for query execution (default: true) + * @param bool $traceTransactions Create spans for transactions (default: true) + * @param bool $collectMetrics Collect duration and row count metrics (default: true) + * @param bool $logQueries Log executed queries (default: false) + * @param null|int $maxQueryLength Maximum query text length in telemetry (default: 1000, null = unlimited) + * @param bool $includeParameters Include query parameters in telemetry (default: false, security consideration) + * + * @example + * // Default options (traces and metrics enabled) + * $options = postgresql_telemetry_options(); + * + * // Enable query logging + * $options = postgresql_telemetry_options(logQueries: true); + * + * // Disable all but metrics + * $options = postgresql_telemetry_options( + * traceQueries: false, + * traceTransactions: false, + * collectMetrics: true, + * ); + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function postgresql_telemetry_options( + bool $traceQueries = true, + bool $traceTransactions = true, + bool $collectMetrics = true, + bool $logQueries = false, + ?int $maxQueryLength = 1000, + bool $includeParameters = false, + ?int $maxParameters = 10, + ?int $maxParameterLength = 100, +) : PostgreSqlTelemetryOptions { + return new PostgreSqlTelemetryOptions( + traceQueries: $traceQueries, + traceTransactions: $traceTransactions, + collectMetrics: $collectMetrics, + logQueries: $logQueries, + maxQueryLength: $maxQueryLength, + includeParameters: $includeParameters, + maxParameters: $maxParameters, + maxParameterLength: $maxParameterLength, + ); +} + +/** + * Create telemetry configuration for PostgreSQL client. + * + * Bundles telemetry instance, clock, and options needed to instrument a PostgreSQL client. + * + * @param Telemetry $telemetry The telemetry instance + * @param ClockInterface $clock Clock for timestamps + * @param null|PostgreSqlTelemetryOptions $options Telemetry options (default: all enabled) + * + * @example + * $config = postgresql_telemetry_config( + * telemetry(resource(['service.name' => 'my-app'])), + * new SystemClock(), + * ); + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function postgresql_telemetry_config( + Telemetry $telemetry, + ClockInterface $clock, + ?PostgreSqlTelemetryOptions $options = null, +) : PostgreSqlTelemetryConfig { + return new PostgreSqlTelemetryConfig( + telemetry: $telemetry, + clock: $clock, + options: $options ?? new PostgreSqlTelemetryOptions(), + ); +} + +/** + * Wrap a PostgreSQL client with telemetry instrumentation. + * + * Returns a decorator that adds spans, metrics, and logs to all + * query and transaction operations following OpenTelemetry conventions. + * + * @param Client\Client $client The PostgreSQL client to instrument + * @param PostgreSqlTelemetryConfig $telemetryConfig Telemetry configuration + * + * @example + * $client = pgsql_client(pgsql_connection('host=localhost dbname=mydb')); + * + * $traceableClient = traceable_postgresql_client( + * $client, + * postgresql_telemetry_config( + * telemetry(resource(['service.name' => 'my-app'])), + * new SystemClock(), + * postgresql_telemetry_options( + * traceQueries: true, + * traceTransactions: true, + * collectMetrics: true, + * logQueries: true, + * maxQueryLength: 500, + * ), + * ), + * ); + * + * // All operations now traced + * $traceableClient->transaction(function (Client $client) { + * $user = $client->fetchOne('SELECT * FROM users WHERE id = $1', [123]); + * $client->execute('UPDATE users SET last_login = NOW() WHERE id = $1', [123]); + * }); + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function traceable_postgresql_client( + Client\Client $client, + PostgreSqlTelemetryConfig $telemetryConfig, +) : TraceableClient { + return new TraceableClient($client, $telemetryConfig); +} + +/** + * Create a default constructor-based row mapper. + * + * Maps database rows directly to constructor parameters. + * Column names must match parameter names exactly (1:1). + * Use SQL aliases if column names differ from parameter names. + * + * @example + * // DTO where column names match parameter names + * readonly class User { + * public function __construct( + * public int $id, + * public string $name, + * public string $email, + * ) {} + * } + * + * // Usage + * $client = pgsql_client(pgsql_connection('...'), mapper: pgsql_mapper()); + * + * // For snake_case columns, use SQL aliases + * $user = $client->fetchInto( + * User::class, + * 'SELECT id, user_name AS name, user_email AS email FROM users WHERE id = $1', + * [1] + * ); + */ +/** + * @template T of object + * + * @param class-string $class + * + * @return ConstructorMapper + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function constructor_mapper(string $class) : ConstructorMapper +{ + return new ConstructorMapper($class); +} + +/** + * @template T + * + * @param FlowType $type + * + * @return TypeMapper + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function type_mapper(FlowType $type) : TypeMapper +{ + return new TypeMapper($type); +} + +/** + * Wrap a value with explicit PostgreSQL type information for parameter binding. + * + * Use when auto-detection isn't sufficient or when you need to specify + * the exact PostgreSQL type (since one PHP type can map to multiple PostgreSQL types): + * - int could be INT2, INT4, or INT8 + * - string could be TEXT, VARCHAR, or CHAR + * - array must always use typed() since auto-detection cannot determine element type + * - DateTimeInterface could be TIMESTAMP or TIMESTAMPTZ + * - Json could be JSON or JSONB + * + * @param mixed $value The value to bind + * @param ValueType $targetType The PostgreSQL type to convert the value to + * + * @example + * $client->fetch( + * 'SELECT * FROM users WHERE id = $1 AND tags = $2', + * [ + * typed('550e8400-e29b-41d4-a716-446655440000', ValueType::UUID), + * typed(['tag1', 'tag2'], ValueType::TEXT_ARRAY), + * ] + * ); + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function typed(mixed $value, ValueType $targetType) : TypedValue +{ + return new TypedValue($value, $targetType); +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/DSL/condition.php b/src/lib/postgresql/src/Flow/PostgreSql/DSL/condition.php new file mode 100644 index 0000000000..6c60f9adc2 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/DSL/condition.php @@ -0,0 +1,605 @@ + value). + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function gt(string|Expression $left, string|Expression $right) : Comparison +{ + return new Comparison( + $left instanceof Expression ? $left : col($left), + ComparisonOperator::GT, + $right instanceof Expression ? $right : col($right), + ); +} + +/** + * Create a greater-than-or-equal comparison (column >= value). + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function ge(string|Expression $left, string|Expression $right) : Comparison +{ + return new Comparison( + $left instanceof Expression ? $left : col($left), + ComparisonOperator::GTE, + $right instanceof Expression ? $right : col($right), + ); +} + +/** + * Create a BETWEEN condition. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function between(string|Expression $expr, string|Expression $low, string|Expression $high, bool $not = false) : Between +{ + return new Between( + $expr instanceof Expression ? $expr : col($expr), + $low instanceof Expression ? $low : col($low), + $high instanceof Expression ? $high : col($high), + $not, + ); +} + +/** + * Create an IN condition. + * + * @param Expression|string $expr Expression to check + * @param list $values List of values + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function in_(string|Expression $expr, array $values) : In +{ + return new In($expr instanceof Expression ? $expr : col($expr), \array_values($values)); +} + +/** + * Create an IS NULL condition. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function is_null(string|Expression $expr, bool $not = false) : IsNull +{ + return new IsNull($expr instanceof Expression ? $expr : col($expr), $not); +} + +/** + * Create a LIKE condition. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function like(string|Expression $expr, string|Expression $pattern, bool $caseInsensitive = false, bool $negated = false) : Like +{ + return new Like( + $expr instanceof Expression ? $expr : col($expr), + $pattern instanceof Expression ? $pattern : col($pattern), + $caseInsensitive, + negated: $negated, + ); +} + +/** + * Create a SIMILAR TO condition. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function similar_to(string|Expression $expr, string|Expression $pattern) : SimilarTo +{ + return new SimilarTo( + $expr instanceof Expression ? $expr : col($expr), + $pattern instanceof Expression ? $pattern : col($pattern), + ); +} + +/** + * Create an IS DISTINCT FROM condition. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function distinct_from(string|Expression $left, string|Expression $right, bool $not = false) : IsDistinctFrom +{ + return new IsDistinctFrom( + $left instanceof Expression ? $left : col($left), + $right instanceof Expression ? $right : col($right), + $not, + ); +} + +/** + * Create an EXISTS condition. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function exists(SelectFinalStep $subquery) : Exists +{ + $node = new Node(); + $node->setSelectStmt($subquery->toAst()); + + return new Exists($node); +} + +/** + * Create an ANY condition with a subquery or array expression. + * + * Example: any_(col('id'), ComparisonOperator::EQ, select(col('user_id'))->from(table('orders'))) + * Example: any_(col('attnum', 'a'), ComparisonOperator::EQ, col('conkey', 'con')) + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function any_(string|Expression $left, ComparisonOperator $operator, Expression|SelectFinalStep $arrayOrSubquery) : Any +{ + $left = $left instanceof Expression ? $left : col($left); + + if ($arrayOrSubquery instanceof SelectFinalStep) { + $node = new Node(); + $node->setSelectStmt($arrayOrSubquery->toAst()); + + return new Any($left, $operator, $node); + } + + return new Any($left, $operator, $arrayOrSubquery); +} + +/** + * Create an ALL condition with a subquery or array expression. + * + * Example: all_(col('id'), ComparisonOperator::EQ, select(col('user_id'))->from(table('orders'))) + * Example: all_(col('value'), ComparisonOperator::GT, col('thresholds')) + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function all_(string|Expression $left, ComparisonOperator $operator, Expression|SelectFinalStep $arrayOrSubquery) : All +{ + $left = $left instanceof Expression ? $left : col($left); + + if ($arrayOrSubquery instanceof SelectFinalStep) { + $node = new Node(); + $node->setSelectStmt($arrayOrSubquery->toAst()); + + return new All($left, $operator, $node); + } + + return new All($left, $operator, $arrayOrSubquery); +} + +/** + * Wrap an expression as a boolean condition for use in WHERE/HAVING/JOIN ON. + * + * Example: is_true(col('is_active')) — uses a boolean column in WHERE clause. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function is_true(string|Expression $expr) : BooleanCondition +{ + return new BooleanCondition($expr instanceof Expression ? $expr : col($expr)); +} + +/** + * Create a NOT LIKE condition. + * + * Example: not_like(col('name'), literal('pg_%')) + * Produces: name NOT LIKE 'pg_%' + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function not_like(string|Expression $expr, string|Expression $pattern, bool $caseInsensitive = false) : Like +{ + return new Like( + $expr instanceof Expression ? $expr : col($expr), + $pattern instanceof Expression ? $pattern : col($pattern), + $caseInsensitive, + negated: true, + ); +} + +/** + * Create a condition builder for fluent condition composition. + * + * This builder allows incremental condition building with a fluent API: + * + * ```php + * $builder = conditions(); + * + * if ($hasFilter) { + * $builder = $builder->and(eq(col('status'), literal('active'))); + * } + * + * if (!$builder->isEmpty()) { + * $query = select()->from(table('users'))->where($builder); + * } + * ``` + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function conditions() : ConditionBuilder +{ + return ConditionBuilder::create(); +} + +/** + * Combine conditions with AND. + * + * @param Condition ...$conditions Conditions to combine + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function and_(Condition ...$conditions) : AndCondition +{ + return new AndCondition(...$conditions); +} + +/** + * Combine conditions with OR. + * + * @param Condition ...$conditions Conditions to combine + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function or_(Condition ...$conditions) : OrCondition +{ + return new OrCondition(...$conditions); +} + +/** + * Negate a condition or expression with NOT. + * + * Accepts both Condition and Expression — NOT always produces a boolean result. + * Can be used in WHERE clauses and SELECT lists (via ->as('alias')). + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function not_(string|Expression $expression) : NotCondition +{ + return new NotCondition($expression instanceof Expression ? $expression : col($expression)); +} + +/** + * Create a JSONB contains condition (@>). + * + * Example: json_contains(col('metadata'), literal_json('{"category": "electronics"}')) + * Produces: metadata @> '{"category": "electronics"}' + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function json_contains(string|Expression $left, string|Expression $right) : OperatorCondition +{ + return new OperatorCondition( + $left instanceof Expression ? $left : col($left), + '@>', + $right instanceof Expression ? $right : col($right), + ); +} + +/** + * Create a JSONB is contained by condition (<@). + * + * Example: json_contained_by(col('metadata'), literal_json('{"category": "electronics", "price": 100}')) + * Produces: metadata <@ '{"category": "electronics", "price": 100}' + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function json_contained_by(string|Expression $left, string|Expression $right) : OperatorCondition +{ + return new OperatorCondition( + $left instanceof Expression ? $left : col($left), + '<@', + $right instanceof Expression ? $right : col($right), + ); +} + +/** + * Create a JSON field access expression (->). + * Returns JSON. + * + * Example: json_get(col('metadata'), literal_string('category')) + * Produces: metadata -> 'category' + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function json_get(string|Expression $expr, string|Expression $key) : BinaryExpression +{ + return new BinaryExpression( + $expr instanceof Expression ? $expr : col($expr), + '->', + $key instanceof Expression ? $key : col($key), + ); +} + +/** + * Create a JSON field access expression (->>). + * Returns text. + * + * Example: json_get_text(col('metadata'), literal_string('name')) + * Produces: metadata ->> 'name' + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function json_get_text(string|Expression $expr, string|Expression $key) : BinaryExpression +{ + return new BinaryExpression( + $expr instanceof Expression ? $expr : col($expr), + '->>', + $key instanceof Expression ? $key : col($key), + ); +} + +/** + * Create a JSON path access expression (#>). + * Returns JSON. + * + * Example: json_path(col('metadata'), literal_string('{category,name}')) + * Produces: metadata #> '{category,name}' + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function json_path(string|Expression $expr, string|Expression $path) : BinaryExpression +{ + return new BinaryExpression( + $expr instanceof Expression ? $expr : col($expr), + '#>', + $path instanceof Expression ? $path : col($path), + ); +} + +/** + * Create a JSON path access expression (#>>). + * Returns text. + * + * Example: json_path_text(col('metadata'), literal_string('{category,name}')) + * Produces: metadata #>> '{category,name}' + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function json_path_text(string|Expression $expr, string|Expression $path) : BinaryExpression +{ + return new BinaryExpression( + $expr instanceof Expression ? $expr : col($expr), + '#>>', + $path instanceof Expression ? $path : col($path), + ); +} + +/** + * Create a JSONB key exists condition (?). + * + * Example: json_exists(col('metadata'), literal_string('category')) + * Produces: metadata ? 'category' + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function json_exists(string|Expression $expr, string|Expression $key) : OperatorCondition +{ + return new OperatorCondition( + $expr instanceof Expression ? $expr : col($expr), + '?', + $key instanceof Expression ? $key : col($key), + ); +} + +/** + * Create a JSONB any key exists condition (?|). + * + * Example: json_exists_any(col('metadata'), array_expr([literal('category'), literal('name')])) + * Produces: metadata ?| array['category', 'name'] + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function json_exists_any(string|Expression $expr, string|Expression $keys) : OperatorCondition +{ + return new OperatorCondition( + $expr instanceof Expression ? $expr : col($expr), + '?|', + $keys instanceof Expression ? $keys : col($keys), + ); +} + +/** + * Create a JSONB all keys exist condition (?&). + * + * Example: json_exists_all(col('metadata'), array_expr([literal('category'), literal('name')])) + * Produces: metadata ?& array['category', 'name'] + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function json_exists_all(string|Expression $expr, string|Expression $keys) : OperatorCondition +{ + return new OperatorCondition( + $expr instanceof Expression ? $expr : col($expr), + '?&', + $keys instanceof Expression ? $keys : col($keys), + ); +} + +/** + * Create an array contains condition (@>). + * + * Example: array_contains(col('tags'), array_expr([literal('sale')])) + * Produces: tags @> ARRAY['sale'] + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function array_contains(string|Expression $left, string|Expression $right) : OperatorCondition +{ + return new OperatorCondition( + $left instanceof Expression ? $left : col($left), + '@>', + $right instanceof Expression ? $right : col($right), + ); +} + +/** + * Create an array is contained by condition (<@). + * + * Example: array_contained_by(col('tags'), array_expr([literal('sale'), literal('featured'), literal('new')])) + * Produces: tags <@ ARRAY['sale', 'featured', 'new'] + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function array_contained_by(string|Expression $left, string|Expression $right) : OperatorCondition +{ + return new OperatorCondition( + $left instanceof Expression ? $left : col($left), + '<@', + $right instanceof Expression ? $right : col($right), + ); +} + +/** + * Create an array overlap condition (&&). + * + * Example: array_overlap(col('tags'), array_expr([literal('sale'), literal('featured')])) + * Produces: tags && ARRAY['sale', 'featured'] + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function array_overlap(string|Expression $left, string|Expression $right) : OperatorCondition +{ + return new OperatorCondition( + $left instanceof Expression ? $left : col($left), + '&&', + $right instanceof Expression ? $right : col($right), + ); +} + +/** + * Create a POSIX regex match condition (~). + * Case-sensitive. + * + * Example: regex_match(col('email'), literal_string('.*@gmail\\.com')) + * + * Produces: email ~ '.*@gmail\.com' + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function regex_match(string|Expression $expr, string|Expression $pattern) : OperatorCondition +{ + return new OperatorCondition( + $expr instanceof Expression ? $expr : col($expr), + '~', + $pattern instanceof Expression ? $pattern : col($pattern), + ); +} + +/** + * Create a POSIX regex match condition (~*). + * Case-insensitive. + * + * Example: regex_imatch(col('email'), literal_string('.*@gmail\\.com')) + * + * Produces: email ~* '.*@gmail\.com' + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function regex_imatch(string|Expression $expr, string|Expression $pattern) : OperatorCondition +{ + return new OperatorCondition( + $expr instanceof Expression ? $expr : col($expr), + '~*', + $pattern instanceof Expression ? $pattern : col($pattern), + ); +} + +/** + * Create a POSIX regex not match condition (!~). + * Case-sensitive. + * + * Example: not_regex_match(col('email'), literal_string('.*@spam\\.com')) + * + * Produces: email !~ '.*@spam\.com' + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function not_regex_match(string|Expression $expr, string|Expression $pattern) : OperatorCondition +{ + return new OperatorCondition( + $expr instanceof Expression ? $expr : col($expr), + '!~', + $pattern instanceof Expression ? $pattern : col($pattern), + ); +} + +/** + * Create a POSIX regex not match condition (!~*). + * Case-insensitive. + * + * Example: not_regex_imatch(col('email'), literal_string('.*@spam\\.com')) + * + * Produces: email !~* '.*@spam\.com' + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function not_regex_imatch(string|Expression $expr, string|Expression $pattern) : OperatorCondition +{ + return new OperatorCondition( + $expr instanceof Expression ? $expr : col($expr), + '!~*', + $pattern instanceof Expression ? $pattern : col($pattern), + ); +} + +/** + * Create a full-text search match condition (@@). + * + * Example: text_search_match(col('document'), func('to_tsquery', [literal('english'), literal('hello & world')])) + * Produces: document @@ to_tsquery('english', 'hello & world') + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function text_search_match(string|Expression $document, string|Expression $query) : OperatorCondition +{ + return new OperatorCondition( + $document instanceof Expression ? $document : col($document), + '@@', + $query instanceof Expression ? $query : col($query), + ); +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/DSL/functions.php b/src/lib/postgresql/src/Flow/PostgreSql/DSL/functions.php deleted file mode 100644 index 019b05f518..0000000000 --- a/src/lib/postgresql/src/Flow/PostgreSql/DSL/functions.php +++ /dev/null @@ -1,3440 +0,0 @@ -parse($sql); -} - -/** - * Returns a fingerprint of the given SQL query. - * Literal values are normalized so they won't affect the fingerprint. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function sql_fingerprint(string $sql) : ?string -{ - return (new Parser())->fingerprint($sql); -} - -/** - * Normalize SQL query by replacing literal values and named parameters with positional parameters. - * WHERE id = :id will be changed into WHERE id = $1 - * WHERE id = 1 will be changed into WHERE id = $1. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function sql_normalize(string $sql) : ?string -{ - return (new Parser())->normalize($sql); -} - -/** - * Normalize utility SQL statements (DDL like CREATE, ALTER, DROP). - * This handles DDL statements differently from pg_normalize() which is optimized for DML. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function sql_normalize_utility(string $sql) : ?string -{ - return (new Parser())->normalizeUtility($sql); -} - -/** - * Split string with multiple SQL statements into array of individual statements. - * - * @return array - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function sql_split(string $sql) : array -{ - return (new Parser())->split($sql); -} - -/** - * Create DeparseOptions for configuring SQL formatting. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function sql_deparse_options() : DeparseOptions -{ - return DeparseOptions::new(); -} - -/** - * Convert a ParsedQuery AST back to SQL string. - * - * When called without options, returns the SQL as a simple string. - * When called with DeparseOptions, applies formatting (pretty-printing, indentation, etc.). - * - * @throws \RuntimeException if deparsing fails - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function sql_deparse(ParsedQuery $query, ?DeparseOptions $options = null) : string -{ - return $query->deparse($options); -} - -/** - * Parse and format SQL query with pretty printing. - * - * This is a convenience function that parses SQL and returns it formatted. - * - * @param string $sql The SQL query to format - * @param null|DeparseOptions $options Formatting options (defaults to pretty-print enabled) - * - * @throws \RuntimeException if parsing or deparsing fails - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function sql_format(string $sql, ?DeparseOptions $options = null) : string -{ - return (new Parser())->parse($sql)->deparse($options ?? DeparseOptions::new()); -} - -/** - * Generate a summary of parsed queries in protobuf format. - * Useful for query monitoring and logging without full AST overhead. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function sql_summary(string $sql, int $options = 0, int $truncateLimit = 0) : string -{ - return (new Parser())->summary($sql, $options, $truncateLimit); -} - -/** - * Transform a SQL query into a paginated query with LIMIT and OFFSET. - * - * @param string $sql The SQL query to paginate - * @param int $limit Maximum number of rows to return - * @param int $offset Number of rows to skip (requires ORDER BY in query) - * - * @return string The paginated SQL query - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function sql_to_paginated_query(string $sql, int $limit, int $offset = 0) : string -{ - $query = (new Parser())->parse($sql); - $query->traverse(new PaginationModifier(new PaginationConfig($limit, $offset))); - - return $query->deparse(); -} - -/** - * Transform a SQL query to limit results to a specific number of rows. - * - * @param string $sql The SQL query to limit - * @param int $limit Maximum number of rows to return - * - * @return string The limited SQL query - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function sql_to_limited_query(string $sql, int $limit) : string -{ - $query = (new Parser())->parse($sql); - $query->traverse(new PaginationModifier(new PaginationConfig($limit))); - - return $query->deparse(); -} - -/** - * Transform a SQL query into a COUNT query for pagination. - * - * Wraps the query in: SELECT COUNT(*) FROM (...) AS _count_subq - * Removes ORDER BY and LIMIT/OFFSET from the inner query. - * - * @param string $sql The SQL query to transform - * - * @return string The COUNT query - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function sql_to_count_query(string $sql) : string -{ - $query = (new Parser())->parse($sql); - $query->traverse(new CountModifier()); - - return $query->deparse(); -} - -/** - * Transform a SQL query into a keyset (cursor-based) paginated query. - * - * More efficient than OFFSET for large datasets - uses indexed WHERE conditions. - * Automatically detects existing query parameters and appends keyset placeholders at the end. - * - * @param string $sql The SQL query to paginate (must have ORDER BY) - * @param int $limit Maximum number of rows to return - * @param list $columns Columns for keyset pagination (must match ORDER BY) - * @param null|list $cursor Values from last row of previous page (null for first page) - * - * @return string The paginated SQL query - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function sql_to_keyset_query(string $sql, int $limit, array $columns, ?array $cursor = null) : string -{ - $query = (new Parser())->parse($sql); - $query->traverse(new KeysetPaginationModifier(new KeysetPaginationConfig($limit, $columns, $cursor))); - - return $query->deparse(); -} - -/** - * Create a KeysetColumn for keyset pagination. - * - * @param string $column Column name (can include table alias like "u.id") - * @param SortOrder $order Sort order (ASC or DESC) - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function sql_keyset_column(string $column, SortOrder $order = SortOrder::ASC) : KeysetColumn -{ - return new KeysetColumn($column, $order); -} - -/** - * Extract columns from a parsed SQL query. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function sql_query_columns(ParsedQuery $query) : Columns -{ - return new Columns($query); -} - -/** - * Extract tables from a parsed SQL query. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function sql_query_tables(ParsedQuery $query) : Tables -{ - return new Tables($query); -} - -/** - * Extract functions from a parsed SQL query. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function sql_query_functions(ParsedQuery $query) : Functions -{ - return new Functions($query); -} - -/** - * Extract ORDER BY clauses from a parsed SQL query. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function sql_query_order_by(ParsedQuery $query) : OrderByExtractor -{ - return new OrderByExtractor($query); -} - -/** - * Get the maximum nesting depth of a SQL query. - * - * Example: - * - "SELECT * FROM t" => 1 - * - "SELECT * FROM (SELECT * FROM t)" => 2 - * - "SELECT * FROM (SELECT * FROM (SELECT * FROM t))" => 3 - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function sql_query_depth(string $sql) : int -{ - return (new QueryDepth(sql_parse($sql)))->depth(); -} - -/** - * Transform a SQL query into an EXPLAIN query. - * - * Returns the modified SQL with EXPLAIN wrapped around it. - * Defaults to EXPLAIN ANALYZE with JSON format for easy parsing. - * - * @param string $sql The SQL query to explain - * @param null|ExplainConfig $config EXPLAIN configuration (defaults to forAnalysis()) - * - * @return string The EXPLAIN query - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function sql_to_explain(string $sql, ?ExplainConfig $config = null) : string -{ - $config ??= ExplainConfig::forAnalysis(); - $query = (new Parser())->parse($sql); - $query->traverse(new ExplainModifier($config)); - - return $query->deparse(); -} - -/** - * Create an ExplainConfig for customizing EXPLAIN options. - * - * @param bool $analyze Whether to actually execute the query (ANALYZE) - * @param bool $verbose Include verbose output - * @param bool $costs Include cost estimates (default true) - * @param bool $buffers Include buffer usage statistics (requires analyze) - * @param bool $timing Include timing information (requires analyze) - * @param ExplainFormat $format Output format (JSON recommended for parsing) - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function sql_explain_config( - bool $analyze = true, - bool $verbose = false, - bool $costs = true, - bool $buffers = true, - bool $timing = true, - ExplainFormat $format = ExplainFormat::JSON, -) : ExplainConfig { - return new ExplainConfig( - analyze: $analyze, - verbose: $verbose, - costs: $costs, - buffers: $buffers, - timing: $timing, - format: $format, - ); -} - -/** - * Create an ExplainModifier for transforming queries into EXPLAIN queries. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function sql_explain_modifier(ExplainConfig $config) : ExplainModifier -{ - return new ExplainModifier($config); -} - -/** - * Parse EXPLAIN JSON output into a Plan object. - * - * @param string $jsonOutput The JSON output from EXPLAIN (FORMAT JSON) - * - * @return Plan The parsed execution plan - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function sql_explain_parse(string $jsonOutput) : Plan -{ - return (new ExplainParser())->parse($jsonOutput); -} - -/** - * Create a plan analyzer for analyzing EXPLAIN plans. - * - * @param Plan $plan The execution plan to analyze - * - * @return PlanAnalyzer The analyzer for extracting insights - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function sql_analyze(Plan $plan) : PlanAnalyzer -{ - return new PlanAnalyzer($plan); -} - -/** - * Create a new SELECT query builder. - * - * @param Expression ...$expressions Columns to select. If empty, returns SelectSelectStep. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function select(Expression ...$expressions) : SelectBuilder -{ - if ($expressions === []) { - return SelectBuilder::create(); - } - - return SelectBuilder::create()->select(...$expressions); -} - -/** - * Create a WITH clause builder for CTEs. - * - * Example: with(cte('users', $subquery))->select(star())->from(table('users')) - * Example: with(cte('a', $q1), cte('b', $q2))->recursive()->select(...)->from(table('a')) - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function with(CTE ...$ctes) : WithBuilder -{ - if ($ctes === []) { - throw new \InvalidArgumentException('At least one CTE is required'); - } - - return new WithBuilder(new WithClause($ctes)); -} - -/** - * Create a new INSERT query builder. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function insert() : InsertIntoStep -{ - return InsertBuilder::create(); -} - -/** - * Create an optimized bulk INSERT query for high-performance multi-row inserts. - * - * Unlike insert() which uses immutable builder patterns (O(n²) for n rows), - * this function generates SQL directly using string operations (O(n) complexity). - * - * @param string $table Table name - * @param list $columns Column names - * @param int $rowCount Number of rows to insert - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function bulk_insert(string $table, array $columns, int $rowCount) : BulkInsert -{ - return BulkInsert::into($table, $columns, $rowCount); -} - -/** - * Create a new UPDATE query builder. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function update() : UpdateTableStep -{ - return UpdateBuilder::create(); -} - -/** - * Create a new DELETE query builder. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function delete() : DeleteFromStep -{ - return DeleteBuilder::create(); -} - -/** - * Create a new MERGE query builder. - * - * @param string $table Target table name - * @param null|string $alias Optional table alias - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function merge(string $table, ?string $alias = null) : MergeUsingStep -{ - return MergeBuilder::create()->into($table, $alias); -} - -/** - * Create a new COPY query builder for data import/export. - * - * Usage: - * copy()->from('users')->file('/tmp/users.csv')->format(CopyFormat::CSV) - * copy()->to('users')->file('/tmp/users.csv')->format(CopyFormat::CSV) - * copy()->toQuery(select(...))->file('/tmp/data.csv') - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function copy() : CopyFactory -{ - return new CopyFactory(); -} - -/** - * Create a column reference expression. - * - * Can be used in two modes: - * - Parse mode: col('users.id') or col('schema.table.column') - parses dot-separated string - * - Explicit mode: col('id', 'users') or col('id', 'users', 'schema') - separate arguments - * - * When $table or $schema is provided, $column must be a plain column name (no dots). - * - * @param string $column Column name, or dot-separated path like "table.column" or "schema.table.column" - * @param null|string $table Table name (optional, triggers explicit mode) - * @param null|string $schema Schema name (optional, requires $table) - * - * @throws InvalidExpressionException when $schema is provided without $table, or when $column contains dots in explicit mode - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function col(string $column, ?string $table = null, ?string $schema = null) : Column -{ - if ($table !== null || $schema !== null) { - if ($schema !== null && $table === null) { - throw new InvalidExpressionException('Cannot specify schema without table in col()'); - } - - if (\str_contains($column, '.')) { - throw new InvalidExpressionException('Column name cannot contain dots when table or schema is specified. Use col("table.column") or col("column", "table") but not both.'); - } - - if ($schema !== null && $table !== null) { - return Column::schemaTableColumn($schema, $table, $column); - } - - if ($table === null) { - return Column::fromParts(QualifiedIdentifier::parse($column)->parts()); - } - - return Column::tableColumn($table, $column); - } - - return Column::fromParts(QualifiedIdentifier::parse($column)->parts()); -} - -/** - * Create a SELECT * expression. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function star(?string $table = null) : Star -{ - return $table !== null ? Star::fromTable($table) : Star::all(); -} - -/** - * Create a literal value for use in queries. - * - * Automatically detects the type and creates the appropriate literal: - * - literal('hello') creates a string literal - * - literal(42) creates an integer literal - * - literal(3.14) creates a float literal - * - literal(true) creates a boolean literal - * - literal(null) creates a NULL literal - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function literal(string|int|float|bool|null $value) : Literal -{ - return match (true) { - $value === null => Literal::null(), - \is_string($value) => Literal::string($value), - \is_int($value) => Literal::int($value), - \is_float($value) => Literal::float($value), - \is_bool($value) => Literal::bool($value), - }; -} - -/** - * Create a positional parameter ($1, $2, etc.). - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function param(int $position) : Parameter -{ - return Parameter::positional($position); -} - -/** - * Create a function call expression. - * - * @param string $name Function name (can include schema like "pg_catalog.now") - * @param list $args Function arguments - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function func(string $name, array $args = []) : FunctionCall -{ - return new FunctionCall(QualifiedIdentifier::parse($name)->parts(), $args); -} - -/** - * Create an aggregate function call (COUNT, SUM, AVG, etc.). - * - * @param string $name Aggregate function name - * @param list $args Function arguments - * @param bool $distinct Use DISTINCT modifier - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function agg(string $name, array $args = [], bool $distinct = false) : AggregateCall -{ - return new AggregateCall([$name], $args, false, $distinct); -} - -/** - * Create COUNT(*) aggregate. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function agg_count(?Expression $expr = null, bool $distinct = false) : AggregateCall -{ - if ($expr === null) { - return new AggregateCall(['count'], [], true, false); - } - - return new AggregateCall(['count'], [$expr], false, $distinct); -} - -/** - * Create SUM aggregate. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function agg_sum(Expression $expr, bool $distinct = false) : AggregateCall -{ - return new AggregateCall(['sum'], [$expr], false, $distinct); -} - -/** - * Create AVG aggregate. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function agg_avg(Expression $expr, bool $distinct = false) : AggregateCall -{ - return new AggregateCall(['avg'], [$expr], false, $distinct); -} - -/** - * Create MIN aggregate. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function agg_min(Expression $expr) : AggregateCall -{ - return new AggregateCall(['min'], [$expr]); -} - -/** - * Create MAX aggregate. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function agg_max(Expression $expr) : AggregateCall -{ - return new AggregateCall(['max'], [$expr]); -} - -/** - * Create a COALESCE expression. - * - * @param Expression ...$expressions Expressions to coalesce - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function coalesce(Expression ...$expressions) : Coalesce -{ - return new Coalesce(\array_values($expressions)); -} - -/** - * Create a NULLIF expression. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function nullif(Expression $expr1, Expression $expr2) : NullIf -{ - return new NullIf($expr1, $expr2); -} - -/** - * Create a GREATEST expression. - * - * @param Expression ...$expressions Expressions to compare - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function greatest(Expression ...$expressions) : Greatest -{ - return new Greatest(\array_values($expressions)); -} - -/** - * Create a LEAST expression. - * - * @param Expression ...$expressions Expressions to compare - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function least(Expression ...$expressions) : Least -{ - return new Least(\array_values($expressions)); -} - -/** - * Create a type cast expression. - * - * @param Expression $expr Expression to cast - * @param DataType $dataType Target data type (use data_type_* functions) - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function cast(Expression $expr, DataType $dataType) : TypeCast -{ - return new TypeCast($expr, $dataType); -} - -/** - * Create an integer data type (PostgreSQL int4). - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function data_type_integer() : DataType -{ - return DataType::integer(); -} - -/** - * Create a smallint data type (PostgreSQL int2). - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function data_type_smallint() : DataType -{ - return DataType::smallint(); -} - -/** - * Create a bigint data type (PostgreSQL int8). - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function data_type_bigint() : DataType -{ - return DataType::bigint(); -} - -/** - * Create a boolean data type. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function data_type_boolean() : DataType -{ - return DataType::boolean(); -} - -/** - * Create a text data type. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function data_type_text() : DataType -{ - return DataType::text(); -} - -/** - * Create a varchar data type with length constraint. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function data_type_varchar(int $length) : DataType -{ - return DataType::varchar($length); -} - -/** - * Create a char data type with length constraint. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function data_type_char(int $length) : DataType -{ - return DataType::char($length); -} - -/** - * Create a numeric data type with optional precision and scale. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function data_type_numeric(?int $precision = null, ?int $scale = null) : DataType -{ - return DataType::numeric($precision, $scale); -} - -/** - * Create a decimal data type with optional precision and scale. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function data_type_decimal(?int $precision = null, ?int $scale = null) : DataType -{ - return DataType::decimal($precision, $scale); -} - -/** - * Create a real data type (PostgreSQL float4). - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function data_type_real() : DataType -{ - return DataType::real(); -} - -/** - * Create a double precision data type (PostgreSQL float8). - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function data_type_double_precision() : DataType -{ - return DataType::doublePrecision(); -} - -/** - * Create a date data type. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function data_type_date() : DataType -{ - return DataType::date(); -} - -/** - * Create a time data type with optional precision. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function data_type_time(?int $precision = null) : DataType -{ - return DataType::time($precision); -} - -/** - * Create a timestamp data type with optional precision. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function data_type_timestamp(?int $precision = null) : DataType -{ - return DataType::timestamp($precision); -} - -/** - * Create a timestamp with time zone data type with optional precision. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function data_type_timestamptz(?int $precision = null) : DataType -{ - return DataType::timestamptz($precision); -} - -/** - * Create an interval data type. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function data_type_interval() : DataType -{ - return DataType::interval(); -} - -/** - * SQL standard CURRENT_TIMESTAMP function. - * - * Returns the current date and time (at the start of the transaction). - * Useful as a column default value or in SELECT queries. - * - * Example: column('created_at', data_type_timestamp())->default(current_timestamp()) - * Example: select()->select(current_timestamp()->as('now')) - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function current_timestamp() : SQLValueFunctionExpression -{ - return SQLValueFunctionExpression::currentTimestamp(); -} - -/** - * SQL standard CURRENT_DATE function. - * - * Returns the current date (at the start of the transaction). - * Useful as a column default value or in SELECT queries. - * - * Example: column('birth_date', data_type_date())->default(current_date()) - * Example: select()->select(current_date()->as('today')) - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function current_date() : SQLValueFunctionExpression -{ - return SQLValueFunctionExpression::currentDate(); -} - -/** - * SQL standard CURRENT_TIME function. - * - * Returns the current time (at the start of the transaction). - * Useful as a column default value or in SELECT queries. - * - * Example: column('start_time', data_type_time())->default(current_time()) - * Example: select()->select(current_time()->as('now_time')) - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function current_time() : SQLValueFunctionExpression -{ - return SQLValueFunctionExpression::currentTime(); -} - -/** - * Create a UUID data type. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function data_type_uuid() : DataType -{ - return DataType::uuid(); -} - -/** - * Create a JSON data type. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function data_type_json() : DataType -{ - return DataType::json(); -} - -/** - * Create a JSONB data type. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function data_type_jsonb() : DataType -{ - return DataType::jsonb(); -} - -/** - * Create a bytea data type. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function data_type_bytea() : DataType -{ - return DataType::bytea(); -} - -/** - * Create an inet data type. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function data_type_inet() : DataType -{ - return DataType::inet(); -} - -/** - * Create a cidr data type. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function data_type_cidr() : DataType -{ - return DataType::cidr(); -} - -/** - * Create a macaddr data type. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function data_type_macaddr() : DataType -{ - return DataType::macaddr(); -} - -/** - * Create a serial data type. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function data_type_serial() : DataType -{ - return DataType::serial(); -} - -/** - * Create a smallserial data type. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function data_type_smallserial() : DataType -{ - return DataType::smallserial(); -} - -/** - * Create a bigserial data type. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function data_type_bigserial() : DataType -{ - return DataType::bigserial(); -} - -/** - * Create an array data type from an element type. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function data_type_array(DataType $elementType) : DataType -{ - return DataType::array($elementType); -} - -/** - * Create a custom data type. - * - * @param string $typeName Type name - * @param null|string $schema Optional schema name - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function data_type_custom(string $typeName, ?string $schema = null) : DataType -{ - return DataType::custom($typeName, $schema); -} - -/** - * Create a CASE expression. - * - * @param non-empty-list $whenClauses WHEN clauses - * @param null|Expression $elseResult ELSE result (optional) - * @param null|Expression $operand CASE operand for simple CASE (optional) - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function case_when(array $whenClauses, ?Expression $elseResult = null, ?Expression $operand = null) : CaseExpression -{ - return new CaseExpression($operand, \array_values($whenClauses), $elseResult); -} - -/** - * Create a WHEN clause for CASE expression. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function when(Expression $condition, Expression $result) : WhenClause -{ - return new WhenClause($condition, $result); -} - -/** - * Create a subquery expression. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function sub_select(SelectFinalStep $query) : Subquery -{ - $node = new Node(); - $node->setSelectStmt($query->toAst()); - - return new Subquery($node); -} - -/** - * Create an array expression. - * - * @param list $elements Array elements - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function array_expr(array $elements) : ArrayExpression -{ - return new ArrayExpression(\array_values($elements)); -} - -/** - * Create a row expression. - * - * @param list $elements Row elements - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function row_expr(array $elements) : RowExpression -{ - return new RowExpression(\array_values($elements)); -} - -/** - * Create a raw SQL expression (use with caution). - * - * SECURITY WARNING: This function accepts raw SQL without parameterization. - * SQL injection is possible if used with untrusted user input. - * Only use with trusted, validated input. - * - * For user-provided values, use param() instead: - * ```php - * // UNSAFE - SQL injection possible: - * raw_expr("custom_func('" . $userInput . "')") - * - * // SAFE - use parameters: - * func('custom_func', param(1)) - * ``` - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function raw_expr(string $sql) : RawExpression -{ - return new RawExpression($sql); -} - -/** - * Create a binary expression (left op right). - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function binary_expr(Expression $left, string $operator, Expression $right) : BinaryExpression -{ - return new BinaryExpression($left, $operator, $right); -} - -/** - * Create a window function. - * - * @param string $name Function name - * @param list $args Function arguments - * @param list $partitionBy PARTITION BY expressions - * @param list $orderBy ORDER BY items - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function window_func( - string $name, - array $args = [], - array $partitionBy = [], - array $orderBy = [], -) : WindowFunction { - return new WindowFunction([$name], \array_values($args), \array_values($partitionBy), \array_values($orderBy)); -} - -/** - * Create an equality comparison (column = value). - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function eq(Expression $left, Expression $right) : Comparison -{ - return new Comparison($left, ComparisonOperator::EQ, $right); -} - -/** - * Create a not-equal comparison (column != value). - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function neq(Expression $left, Expression $right) : Comparison -{ - return new Comparison($left, ComparisonOperator::NEQ, $right); -} - -/** - * Create a less-than comparison (column < value). - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function lt(Expression $left, Expression $right) : Comparison -{ - return new Comparison($left, ComparisonOperator::LT, $right); -} - -/** - * Create a less-than-or-equal comparison (column <= value). - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function lte(Expression $left, Expression $right) : Comparison -{ - return new Comparison($left, ComparisonOperator::LTE, $right); -} - -/** - * Create a greater-than comparison (column > value). - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function gt(Expression $left, Expression $right) : Comparison -{ - return new Comparison($left, ComparisonOperator::GT, $right); -} - -/** - * Create a greater-than-or-equal comparison (column >= value). - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function gte(Expression $left, Expression $right) : Comparison -{ - return new Comparison($left, ComparisonOperator::GTE, $right); -} - -/** - * Create a BETWEEN condition. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function between(Expression $expr, Expression $low, Expression $high, bool $not = false) : Between -{ - return new Between($expr, $low, $high, $not); -} - -/** - * Create an IN condition. - * - * @param Expression $expr Expression to check - * @param list $values List of values - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function is_in(Expression $expr, array $values) : In -{ - return new In($expr, \array_values($values)); -} - -/** - * Create an IS NULL condition. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function is_null(Expression $expr, bool $not = false) : IsNull -{ - return new IsNull($expr, $not); -} - -/** - * Create a LIKE condition. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function like(Expression $expr, Expression $pattern, bool $caseInsensitive = false) : Like -{ - return new Like($expr, $pattern, $caseInsensitive); -} - -/** - * Create a SIMILAR TO condition. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function similar_to(Expression $expr, Expression $pattern) : SimilarTo -{ - return new SimilarTo($expr, $pattern); -} - -/** - * Create an IS DISTINCT FROM condition. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function is_distinct_from(Expression $left, Expression $right, bool $not = false) : IsDistinctFrom -{ - return new IsDistinctFrom($left, $right, $not); -} - -/** - * Create an EXISTS condition. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function exists(SelectFinalStep $subquery) : Exists -{ - $node = new Node(); - $node->setSelectStmt($subquery->toAst()); - - return new Exists($node); -} - -/** - * Create an ANY condition. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function any_sub_select(Expression $left, ComparisonOperator $operator, SelectFinalStep $subquery) : Any -{ - $node = new Node(); - $node->setSelectStmt($subquery->toAst()); - - return new Any($left, $operator, $node); -} - -/** - * Create an ALL condition. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function all_sub_select(Expression $left, ComparisonOperator $operator, SelectFinalStep $subquery) : All -{ - $node = new Node(); - $node->setSelectStmt($subquery->toAst()); - - return new All($left, $operator, $node); -} - -/** - * Create a condition builder for fluent condition composition. - * - * This builder allows incremental condition building with a fluent API: - * - * ```php - * $builder = conditions(); - * - * if ($hasFilter) { - * $builder = $builder->and(eq(col('status'), literal('active'))); - * } - * - * if (!$builder->isEmpty()) { - * $query = select()->from(table('users'))->where($builder); - * } - * ``` - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function conditions() : ConditionBuilder -{ - return ConditionBuilder::create(); -} - -/** - * Combine conditions with AND. - * - * @param Condition ...$conditions Conditions to combine - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function cond_and(Condition ...$conditions) : AndCondition -{ - return new AndCondition(...$conditions); -} - -/** - * Combine conditions with OR. - * - * @param Condition ...$conditions Conditions to combine - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function cond_or(Condition ...$conditions) : OrCondition -{ - return new OrCondition(...$conditions); -} - -/** - * Negate a condition with NOT. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function cond_not(Condition $condition) : NotCondition -{ - return new NotCondition($condition); -} - -/** - * Create a raw SQL condition (use with caution). - * - * SECURITY WARNING: This function accepts raw SQL without parameterization. - * SQL injection is possible if used with untrusted user input. - * Only use with trusted, validated input. - * - * For user-provided values, use standard condition functions with param(): - * ```php - * // UNSAFE - SQL injection possible: - * raw_cond("status = '" . $userInput . "'") - * - * // SAFE - use typed conditions: - * eq(col('status'), param(1)) - * ``` - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function raw_cond(string $sql) : RawCondition -{ - return new RawCondition($sql); -} - -/** - * Create a TRUE condition for WHERE clauses. - * - * Useful when you need a condition that always evaluates to true. - * - * Example: select(literal(1))->where(cond_true()) // SELECT 1 WHERE true - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function cond_true() : RawCondition -{ - return new RawCondition('true'); -} - -/** - * Create a FALSE condition for WHERE clauses. - * - * Useful when you need a condition that always evaluates to false, - * typically for testing or to return an empty result set. - * - * Example: select(literal(1))->where(cond_false()) // SELECT 1 WHERE false - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function cond_false() : RawCondition -{ - return new RawCondition('false'); -} - -/** - * Create a JSONB contains condition (@>). - * - * Example: json_contains(col('metadata'), literal_json('{"category": "electronics"}')) - * Produces: metadata @> '{"category": "electronics"}' - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function json_contains(Expression $left, Expression $right) : OperatorCondition -{ - return new OperatorCondition($left, '@>', $right); -} - -/** - * Create a JSONB is contained by condition (<@). - * - * Example: json_contained_by(col('metadata'), literal_json('{"category": "electronics", "price": 100}')) - * Produces: metadata <@ '{"category": "electronics", "price": 100}' - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function json_contained_by(Expression $left, Expression $right) : OperatorCondition -{ - return new OperatorCondition($left, '<@', $right); -} - -/** - * Create a JSON field access expression (->). - * Returns JSON. - * - * Example: json_get(col('metadata'), literal_string('category')) - * Produces: metadata -> 'category' - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function json_get(Expression $expr, Expression $key) : BinaryExpression -{ - return new BinaryExpression($expr, '->', $key); -} - -/** - * Create a JSON field access expression (->>). - * Returns text. - * - * Example: json_get_text(col('metadata'), literal_string('name')) - * Produces: metadata ->> 'name' - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function json_get_text(Expression $expr, Expression $key) : BinaryExpression -{ - return new BinaryExpression($expr, '->>', $key); -} - -/** - * Create a JSON path access expression (#>). - * Returns JSON. - * - * Example: json_path(col('metadata'), literal_string('{category,name}')) - * Produces: metadata #> '{category,name}' - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function json_path(Expression $expr, Expression $path) : BinaryExpression -{ - return new BinaryExpression($expr, '#>', $path); -} - -/** - * Create a JSON path access expression (#>>). - * Returns text. - * - * Example: json_path_text(col('metadata'), literal_string('{category,name}')) - * Produces: metadata #>> '{category,name}' - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function json_path_text(Expression $expr, Expression $path) : BinaryExpression -{ - return new BinaryExpression($expr, '#>>', $path); -} - -/** - * Create a JSONB key exists condition (?). - * - * Example: json_exists(col('metadata'), literal_string('category')) - * Produces: metadata ? 'category' - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function json_exists(Expression $expr, Expression $key) : OperatorCondition -{ - return new OperatorCondition($expr, '?', $key); -} - -/** - * Create a JSONB any key exists condition (?|). - * - * Example: json_exists_any(col('metadata'), raw_expr("array['category', 'name']")) - * Produces: metadata ?| array['category', 'name'] - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function json_exists_any(Expression $expr, Expression $keys) : OperatorCondition -{ - return new OperatorCondition($expr, '?|', $keys); -} - -/** - * Create a JSONB all keys exist condition (?&). - * - * Example: json_exists_all(col('metadata'), raw_expr("array['category', 'name']")) - * Produces: metadata ?& array['category', 'name'] - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function json_exists_all(Expression $expr, Expression $keys) : OperatorCondition -{ - return new OperatorCondition($expr, '?&', $keys); -} - -/** - * Create an array contains condition (@>). - * - * Example: array_contains(col('tags'), raw_expr("ARRAY['sale']")) - * Produces: tags @> ARRAY['sale'] - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function array_contains(Expression $left, Expression $right) : OperatorCondition -{ - return new OperatorCondition($left, '@>', $right); -} - -/** - * Create an array is contained by condition (<@). - * - * Example: array_contained_by(col('tags'), raw_expr("ARRAY['sale', 'featured', 'new']")) - * Produces: tags <@ ARRAY['sale', 'featured', 'new'] - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function array_contained_by(Expression $left, Expression $right) : OperatorCondition -{ - return new OperatorCondition($left, '<@', $right); -} - -/** - * Create an array overlap condition (&&). - * - * Example: array_overlap(col('tags'), raw_expr("ARRAY['sale', 'featured']")) - * Produces: tags && ARRAY['sale', 'featured'] - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function array_overlap(Expression $left, Expression $right) : OperatorCondition -{ - return new OperatorCondition($left, '&&', $right); -} - -/** - * Create a POSIX regex match condition (~). - * Case-sensitive. - * - * Example: regex_match(col('email'), literal_string('.*@gmail\\.com')) - * - * Produces: email ~ '.*@gmail\.com' - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function regex_match(Expression $expr, Expression $pattern) : OperatorCondition -{ - return new OperatorCondition($expr, '~', $pattern); -} - -/** - * Create a POSIX regex match condition (~*). - * Case-insensitive. - * - * Example: regex_imatch(col('email'), literal_string('.*@gmail\\.com')) - * - * Produces: email ~* '.*@gmail\.com' - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function regex_imatch(Expression $expr, Expression $pattern) : OperatorCondition -{ - return new OperatorCondition($expr, '~*', $pattern); -} - -/** - * Create a POSIX regex not match condition (!~). - * Case-sensitive. - * - * Example: not_regex_match(col('email'), literal_string('.*@spam\\.com')) - * - * Produces: email !~ '.*@spam\.com' - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function not_regex_match(Expression $expr, Expression $pattern) : OperatorCondition -{ - return new OperatorCondition($expr, '!~', $pattern); -} - -/** - * Create a POSIX regex not match condition (!~*). - * Case-insensitive. - * - * Example: not_regex_imatch(col('email'), literal_string('.*@spam\\.com')) - * - * Produces: email !~* '.*@spam\.com' - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function not_regex_imatch(Expression $expr, Expression $pattern) : OperatorCondition -{ - return new OperatorCondition($expr, '!~*', $pattern); -} - -/** - * Create a full-text search match condition (@@). - * - * Example: text_search_match(col('document'), raw_expr("to_tsquery('english', 'hello & world')")) - * Produces: document @@ to_tsquery('english', 'hello & world') - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function text_search_match(Expression $document, Expression $query) : OperatorCondition -{ - return new OperatorCondition($document, '@@', $query); -} - -/** - * Create a table reference. - * - * Supports dot notation for schema-qualified names: "public.users" or explicit schema parameter. - * Double-quoted identifiers preserve dots: '"my.table"' creates a single identifier. - * - * @param string $name Table name (may include schema as "schema.table") - * @param null|string $schema Schema name (optional, overrides parsed schema) - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function table(string $name, ?string $schema = null) : Table -{ - if ($schema !== null) { - return new Table($name, $schema); - } - - $identifier = QualifiedIdentifier::parse($name); - - return new Table($identifier->name(), $identifier->schema()); -} - -/** - * Create a derived table (subquery in FROM clause). - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function derived(SelectFinalStep $query, string $alias) : DerivedTable -{ - $node = new Node(); - $node->setSelectStmt($query->toAst()); - - return new DerivedTable($node, $alias); -} - -/** - * Create a LATERAL subquery. - * - * @param TableReference $reference The subquery or table function reference - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function lateral(TableReference $reference) : Lateral -{ - return new Lateral($reference); -} - -/** - * Create a table function reference. - * - * @param FunctionCall $function The table-valued function - * @param bool $withOrdinality Whether to add WITH ORDINALITY - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function table_func(FunctionCall $function, bool $withOrdinality = false) : TableFunction -{ - return new TableFunction($function, $withOrdinality); -} - -/** - * Create a VALUES clause as a table reference. - * - * Usage: - * select()->from( - * values_table( - * row_expr([literal(1), literal('Alice')]), - * row_expr([literal(2), literal('Bob')]) - * )->as('t', ['id', 'name']) - * ) - * - * Generates: SELECT * FROM (VALUES (1, 'Alice'), (2, 'Bob')) AS t(id, name) - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function values_table(RowExpression ...$rows) : ValuesTable -{ - return new ValuesTable($rows); -} - -/** - * Create an ORDER BY item. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function order_by( - Expression $expr, - SortDirection $direction = SortDirection::ASC, - NullsPosition $nulls = NullsPosition::DEFAULT, -) : OrderBy { - return new OrderBy($expr, $direction, $nulls); -} - -/** - * Create an ORDER BY item with ASC direction. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function asc(Expression $expr, NullsPosition $nulls = NullsPosition::DEFAULT) : OrderBy -{ - return new OrderBy($expr, SortDirection::ASC, $nulls); -} - -/** - * Create an ORDER BY item with DESC direction. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function desc(Expression $expr, NullsPosition $nulls = NullsPosition::DEFAULT) : OrderBy -{ - return new OrderBy($expr, SortDirection::DESC, $nulls); -} - -/** - * Create a CTE (Common Table Expression). - * - * @param string $name CTE name - * @param SelectFinalStep $query CTE query - * @param array $columnNames Column aliases (optional) - * @param CTEMaterialization $materialization Materialization hint - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function cte( - string $name, - SelectFinalStep $query, - array $columnNames = [], - CTEMaterialization $materialization = CTEMaterialization::DEFAULT, - bool $recursive = false, -) : CTE { - $node = new Node(); - $node->setSelectStmt($query->toAst()); - - return new CTE($name, $node, $columnNames, $materialization, $recursive); -} - -/** - * Create a window definition for WINDOW clause. - * - * @param string $name Window name - * @param list $partitionBy PARTITION BY expressions - * @param list $orderBy ORDER BY items - * @param null|WindowFrame $frame Window frame specification - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function window_def( - string $name, - array $partitionBy = [], - array $orderBy = [], - ?WindowFrame $frame = null, -) : WindowDefinition { - return new WindowDefinition($name, \array_values($partitionBy), \array_values($orderBy), $frame); -} - -/** - * Create a window frame specification. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function window_frame( - FrameMode $mode, - FrameBound $start, - ?FrameBound $end = null, - FrameExclusion $exclusion = FrameExclusion::NO_OTHERS, -) : WindowFrame { - return new WindowFrame($mode, $start, $end, $exclusion); -} - -/** - * Create a frame bound for CURRENT ROW. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function frame_current_row() : FrameBound -{ - return FrameBound::currentRow(); -} - -/** - * Create a frame bound for UNBOUNDED PRECEDING. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function frame_unbounded_preceding() : FrameBound -{ - return FrameBound::unboundedPreceding(); -} - -/** - * Create a frame bound for UNBOUNDED FOLLOWING. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function frame_unbounded_following() : FrameBound -{ - return FrameBound::unboundedFollowing(); -} - -/** - * Create a frame bound for N PRECEDING. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function frame_preceding(Expression $offset) : FrameBound -{ - return FrameBound::preceding($offset); -} - -/** - * Create a frame bound for N FOLLOWING. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function frame_following(Expression $offset) : FrameBound -{ - return FrameBound::following($offset); -} - -/** - * Create a locking clause (FOR UPDATE, FOR SHARE, etc.). - * - * @param LockStrength $strength Lock strength - * @param list $tables Tables to lock (empty for all) - * @param LockWaitPolicy $waitPolicy Wait policy - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function lock_for( - LockStrength $strength, - array $tables = [], - LockWaitPolicy $waitPolicy = LockWaitPolicy::DEFAULT, -) : LockingClause { - return new LockingClause($strength, \array_values($tables), $waitPolicy); -} - -/** - * Create a FOR UPDATE locking clause. - * - * @param list $tables Tables to lock (empty for all) - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function for_update(array $tables = []) : LockingClause -{ - return LockingClause::forUpdate(\array_values($tables)); -} - -/** - * Create a FOR SHARE locking clause. - * - * @param list $tables Tables to lock (empty for all) - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function for_share(array $tables = []) : LockingClause -{ - return LockingClause::forShare(\array_values($tables)); -} - -/** - * Create an ON CONFLICT DO NOTHING clause. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function on_conflict_nothing(?ConflictTarget $target = null) : OnConflictClause -{ - return OnConflictClause::doNothing($target); -} - -/** - * Create an ON CONFLICT DO UPDATE clause. - * - * @param ConflictTarget $target Conflict target (columns or constraint) - * @param array $updates Column updates - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function on_conflict_update(ConflictTarget $target, array $updates) : OnConflictClause -{ - return OnConflictClause::doUpdate($target, $updates); -} - -/** - * Create a conflict target for ON CONFLICT (columns). - * - * @param list $columns Columns that define uniqueness - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function conflict_columns(array $columns) : ConflictTarget -{ - return ConflictTarget::columns(\array_values($columns)); -} - -/** - * Create a conflict target for ON CONFLICT ON CONSTRAINT. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function conflict_constraint(string $name) : ConflictTarget -{ - return ConflictTarget::constraint($name); -} - -/** - * Create a RETURNING clause. - * - * @param Expression ...$expressions Expressions to return - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function returning(Expression ...$expressions) : ReturningClause -{ - return new ReturningClause(\array_values($expressions)); -} - -/** - * Create a RETURNING * clause. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function returning_all() : ReturningClause -{ - return ReturningClause::all(); -} - -/** - * Create a BEGIN transaction builder. - * - * Example: begin()->isolationLevel(IsolationLevel::SERIALIZABLE)->readOnly() - * Produces: BEGIN ISOLATION LEVEL SERIALIZABLE READ ONLY - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function begin() : BeginOptionsStep -{ - return BeginBuilder::create(); -} - -/** - * Create a COMMIT transaction builder. - * - * Example: commit()->andChain() - * Produces: COMMIT AND CHAIN - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function commit() : CommitOptionsStep -{ - return CommitBuilder::create(); -} - -/** - * Create a ROLLBACK transaction builder. - * - * Example: rollback()->toSavepoint('my_savepoint') - * Produces: ROLLBACK TO SAVEPOINT my_savepoint - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function rollback() : RollbackOptionsStep -{ - return RollbackBuilder::create(); -} - -/** - * Create a SAVEPOINT. - * - * Example: savepoint('my_savepoint') - * Produces: SAVEPOINT my_savepoint - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function savepoint(string $name) : SavepointFinalStep -{ - return SavepointBuilder::create($name); -} - -/** - * Release a SAVEPOINT. - * - * Example: release_savepoint('my_savepoint') - * Produces: RELEASE my_savepoint - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function release_savepoint(string $name) : SavepointFinalStep -{ - return SavepointBuilder::release($name); -} - -/** - * Create a SET TRANSACTION builder. - * - * Example: set_transaction()->isolationLevel(IsolationLevel::SERIALIZABLE)->readOnly() - * Produces: SET TRANSACTION ISOLATION LEVEL SERIALIZABLE, READ ONLY - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function set_transaction() : SetTransactionOptionsStep -{ - return SetTransactionBuilder::create(); -} - -/** - * Create a SET SESSION CHARACTERISTICS AS TRANSACTION builder. - * - * Example: set_session_transaction()->isolationLevel(IsolationLevel::SERIALIZABLE) - * Produces: SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function set_session_transaction() : SetTransactionOptionsStep -{ - return SetTransactionBuilder::session(); -} - -/** - * Create a SET TRANSACTION SNAPSHOT builder. - * - * Example: transaction_snapshot('00000003-0000001A-1') - * Produces: SET TRANSACTION SNAPSHOT '00000003-0000001A-1' - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function transaction_snapshot(string $snapshotId) : SetTransactionFinalStep -{ - return SetTransactionBuilder::create()->snapshot($snapshotId); -} - -/** - * Create a PREPARE TRANSACTION builder. - * - * Example: prepare_transaction('my_transaction') - * Produces: PREPARE TRANSACTION 'my_transaction' - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function prepare_transaction(string $transactionId) : PreparedTransactionFinalStep -{ - return PreparedTransactionBuilder::prepare($transactionId); -} - -/** - * Create a COMMIT PREPARED builder. - * - * Example: commit_prepared('my_transaction') - * Produces: COMMIT PREPARED 'my_transaction' - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function commit_prepared(string $transactionId) : PreparedTransactionFinalStep -{ - return PreparedTransactionBuilder::commitPrepared($transactionId); -} - -/** - * Create a ROLLBACK PREPARED builder. - * - * Example: rollback_prepared('my_transaction') - * Produces: ROLLBACK PREPARED 'my_transaction' - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function rollback_prepared(string $transactionId) : PreparedTransactionFinalStep -{ - return PreparedTransactionBuilder::rollbackPrepared($transactionId); -} - -/** - * Declare a server-side cursor for a query. - * - * Cursors must be declared within a transaction and provide memory-efficient - * iteration over large result sets via FETCH commands. - * - * Example with query builder: - * declare_cursor('my_cursor', select(star())->from(table('users')))->noScroll() - * Produces: DECLARE my_cursor NO SCROLL CURSOR FOR SELECT * FROM users - * - * Example with raw SQL: - * declare_cursor('my_cursor', 'SELECT * FROM users WHERE active = true')->withHold() - * Produces: DECLARE my_cursor NO SCROLL CURSOR WITH HOLD FOR SELECT * FROM users WHERE active = true - * - * @param string $cursorName Unique cursor name - * @param SelectFinalStep|SqlQuery|string $query Query to iterate over - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function declare_cursor(string $cursorName, SelectFinalStep|string|SqlQuery $query) : DeclareCursorOptionsStep -{ - if ($query instanceof SelectFinalStep) { - return DeclareCursorBuilder::create($cursorName, $query); - } - - return DeclareCursorBuilder::createFromSql($cursorName, $query); -} - -/** - * Fetch rows from a cursor. - * - * Example: fetch('my_cursor')->forward(100) - * Produces: FETCH FORWARD 100 my_cursor - * - * Example: fetch('my_cursor')->all() - * Produces: FETCH ALL my_cursor - * - * @param string $cursorName Cursor to fetch from - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function fetch(string $cursorName) : FetchCursorBuilder -{ - return FetchCursorBuilder::create($cursorName); -} - -/** - * Close a cursor. - * - * Example: close_cursor('my_cursor') - * Produces: CLOSE my_cursor - * - * Example: close_cursor() - closes all cursors - * Produces: CLOSE ALL - * - * @param null|string $cursorName Cursor to close, or null to close all - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function close_cursor(?string $cursorName = null) : CloseCursorFinalStep -{ - if ($cursorName === null) { - return CloseCursorBuilder::closeAll(); - } - - return CloseCursorBuilder::close($cursorName); -} - -/** - * Create a column definition for CREATE TABLE. - * - * @param string $name Column name - * @param DataType $type Column data type - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function column(string $name, DataType $type) : ColumnDefinition -{ - return ColumnDefinition::create($name, $type); -} - -/** - * Create a PRIMARY KEY constraint. - * - * @param string ...$columns Columns that form the primary key - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function primary_key(string ...$columns) : PrimaryKeyConstraint -{ - return PrimaryKeyConstraint::create(...$columns); -} - -/** - * Create a UNIQUE constraint. - * - * @param string ...$columns Columns that must be unique together - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function unique_constraint(string ...$columns) : UniqueConstraint -{ - return UniqueConstraint::create(...$columns); -} - -/** - * Create a FOREIGN KEY constraint. - * - * @param list $columns Local columns - * @param string $referenceTable Referenced table - * @param list $referenceColumns Referenced columns (defaults to same as $columns if empty) - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function foreign_key(array $columns, string $referenceTable, array $referenceColumns = []) : ForeignKeyConstraint -{ - return ForeignKeyConstraint::create($columns, $referenceTable, $referenceColumns); -} - -/** - * Create a CHECK constraint. - * - * @param string $expression SQL expression that must evaluate to true - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function check_constraint(string $expression) : CheckConstraint -{ - return CheckConstraint::create($expression); -} - -/** - * Create a factory for building CREATE statements. - * - * Provides a unified entry point for all CREATE operations: - * - create()->table() - CREATE TABLE - * - create()->tableAs() - CREATE TABLE AS - * - create()->index() - CREATE INDEX - * - create()->view() - CREATE VIEW - * - create()->materializedView() - CREATE MATERIALIZED VIEW - * - create()->sequence() - CREATE SEQUENCE - * - create()->schema() - CREATE SCHEMA - * - create()->role() - CREATE ROLE - * - create()->function() - CREATE FUNCTION - * - create()->procedure() - CREATE PROCEDURE - * - create()->trigger() - CREATE TRIGGER - * - create()->rule() - CREATE RULE - * - create()->extension() - CREATE EXTENSION - * - create()->compositeType() - CREATE TYPE (composite) - * - create()->enumType() - CREATE TYPE (enum) - * - create()->rangeType() - CREATE TYPE (range) - * - create()->domain() - CREATE DOMAIN - * - * Example: create()->table('users')->columns(col_def('id', data_type_serial())) - * Example: create()->index('idx_email')->on('users')->columns('email') - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::SCHEMA)] -function create() : CreateFactory -{ - return new CreateFactory(); -} - -/** - * Create a factory for building DROP statements. - * - * Provides a unified entry point for all DROP operations: - * - drop()->table() - DROP TABLE - * - drop()->index() - DROP INDEX - * - drop()->view() - DROP VIEW - * - drop()->materializedView() - DROP MATERIALIZED VIEW - * - drop()->sequence() - DROP SEQUENCE - * - drop()->schema() - DROP SCHEMA - * - drop()->role() - DROP ROLE - * - drop()->function() - DROP FUNCTION - * - drop()->procedure() - DROP PROCEDURE - * - drop()->trigger() - DROP TRIGGER - * - drop()->rule() - DROP RULE - * - drop()->extension() - DROP EXTENSION - * - drop()->type() - DROP TYPE - * - drop()->domain() - DROP DOMAIN - * - drop()->owned() - DROP OWNED - * - * Example: drop()->table('users', 'orders')->ifExists()->cascade() - * Example: drop()->index('idx_email')->ifExists() - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::SCHEMA)] -function drop() : DropFactory -{ - return new DropFactory(); -} - -/** - * Create a factory for building ALTER statements. - * - * Provides a unified entry point for all ALTER operations: - * - alter()->table() - ALTER TABLE - * - alter()->index() - ALTER INDEX - * - alter()->view() - ALTER VIEW - * - alter()->materializedView() - ALTER MATERIALIZED VIEW - * - alter()->sequence() - ALTER SEQUENCE - * - alter()->schema() - ALTER SCHEMA - * - alter()->role() - ALTER ROLE - * - alter()->function() - ALTER FUNCTION - * - alter()->procedure() - ALTER PROCEDURE - * - alter()->trigger() - ALTER TRIGGER - * - alter()->extension() - ALTER EXTENSION - * - alter()->enumType() - ALTER TYPE (enum) - * - alter()->domain() - ALTER DOMAIN - * - * Rename operations are also under alter(): - * - alter()->index('old')->renameTo('new') - * - alter()->view('old')->renameTo('new') - * - alter()->schema('old')->renameTo('new') - * - alter()->role('old')->renameTo('new') - * - alter()->trigger('old')->on('table')->renameTo('new') - * - * Example: alter()->table('users')->addColumn(col_def('email', data_type_text())) - * Example: alter()->sequence('user_id_seq')->restart(1000) - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::SCHEMA)] -function alter() : AlterFactory -{ - return new AlterFactory(); -} - -/** - * Create a TRUNCATE TABLE builder. - * - * @param string ...$tables Table names to truncate - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function truncate_table(string ...$tables) : TruncateFinalStep -{ - return TruncateBuilder::create(...$tables); -} - -/** - * Create a REFRESH MATERIALIZED VIEW builder. - * - * Example: refresh_materialized_view('user_stats') - * Produces: REFRESH MATERIALIZED VIEW user_stats - * - * Example: refresh_materialized_view('user_stats')->concurrently()->withData() - * Produces: REFRESH MATERIALIZED VIEW CONCURRENTLY user_stats WITH DATA - * - * @param string $name View name (may include schema as "schema.view") - * @param null|string $schema Schema name (optional, overrides parsed schema) - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::SCHEMA)] -function refresh_materialized_view(string $name, ?string $schema = null) : RefreshMatViewOptionsStep -{ - return RefreshMaterializedViewBuilder::create($name, $schema); -} - -/** - * Get a CASCADE referential action. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function ref_action_cascade() : ReferentialAction -{ - return ReferentialAction::CASCADE; -} - -/** - * Get a RESTRICT referential action. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function ref_action_restrict() : ReferentialAction -{ - return ReferentialAction::RESTRICT; -} - -/** - * Get a SET NULL referential action. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function ref_action_set_null() : ReferentialAction -{ - return ReferentialAction::SET_NULL; -} - -/** - * Get a SET DEFAULT referential action. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function ref_action_set_default() : ReferentialAction -{ - return ReferentialAction::SET_DEFAULT; -} - -/** - * Get a NO ACTION referential action. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function ref_action_no_action() : ReferentialAction -{ - return ReferentialAction::NO_ACTION; -} - -/** - * Start building a REINDEX INDEX statement. - * - * Use chainable methods: ->concurrently(), ->verbose(), ->tablespace() - * - * Example: reindex_index('idx_users_email')->concurrently() - * - * @param string $name The index name (may include schema: schema.index) - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::SCHEMA)] -function reindex_index(string $name) : ReindexFinalStep -{ - return ReindexBuilder::index($name); -} - -/** - * Start building a REINDEX TABLE statement. - * - * Use chainable methods: ->concurrently(), ->verbose(), ->tablespace() - * - * Example: reindex_table('users')->concurrently() - * - * @param string $name The table name (may include schema: schema.table) - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::SCHEMA)] -function reindex_table(string $name) : ReindexFinalStep -{ - return ReindexBuilder::table($name); -} - -/** - * Start building a REINDEX SCHEMA statement. - * - * Use chainable methods: ->concurrently(), ->verbose(), ->tablespace() - * - * Example: reindex_schema('public')->concurrently() - * - * @param string $name The schema name - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::SCHEMA)] -function reindex_schema(string $name) : ReindexFinalStep -{ - return ReindexBuilder::schema($name); -} - -/** - * Start building a REINDEX DATABASE statement. - * - * Use chainable methods: ->concurrently(), ->verbose(), ->tablespace() - * - * Example: reindex_database('mydb')->concurrently() - * - * @param string $name The database name - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::SCHEMA)] -function reindex_database(string $name) : ReindexFinalStep -{ - return ReindexBuilder::database($name); -} - -/** - * Create an index column specification. - * - * Use chainable methods: ->asc(), ->desc(), ->nullsFirst(), ->nullsLast(), ->opclass(), ->collate() - * - * Example: index_col('email')->desc()->nullsLast() - * - * @param string $name The column name - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::SCHEMA)] -function index_col(string $name) : IndexColumn -{ - return IndexColumn::column($name); -} - -/** - * Create an index column specification from an expression. - * - * Use chainable methods: ->asc(), ->desc(), ->nullsFirst(), ->nullsLast(), ->opclass(), ->collate() - * - * Example: index_expr(fn_call('lower', col('email')))->desc() - * - * @param Expression $expression The expression to index - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::SCHEMA)] -function index_expr(Expression $expression) : IndexColumn -{ - return IndexColumn::expression($expression); -} - -/** - * Get the BTREE index method. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function index_method_btree() : IndexMethod -{ - return IndexMethod::BTREE; -} - -/** - * Get the HASH index method. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function index_method_hash() : IndexMethod -{ - return IndexMethod::HASH; -} - -/** - * Get the GIST index method. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function index_method_gist() : IndexMethod -{ - return IndexMethod::GIST; -} - -/** - * Get the SPGIST index method. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function index_method_spgist() : IndexMethod -{ - return IndexMethod::SPGIST; -} - -/** - * Get the GIN index method. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function index_method_gin() : IndexMethod -{ - return IndexMethod::GIN; -} - -/** - * Get the BRIN index method. - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function index_method_brin() : IndexMethod -{ - return IndexMethod::BRIN; -} - -/** - * Create a VACUUM builder. - * - * Example: vacuum()->table('users') - * Produces: VACUUM users - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function vacuum() : VacuumFinalStep -{ - return VacuumBuilder::create(); -} - -/** - * Create an ANALYZE builder. - * - * Example: analyze()->table('users') - * Produces: ANALYZE users - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function analyze() : AnalyzeFinalStep -{ - return AnalyzeBuilder::create(); -} - -/** - * Create an EXPLAIN builder for a query. - * - * Example: explain(select()->from('users')) - * Produces: EXPLAIN SELECT * FROM users - * - * @param DeleteBuilder|InsertBuilder|SelectFinalStep|UpdateBuilder $query Query to explain - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function explain(SelectFinalStep|InsertBuilder|UpdateBuilder|DeleteBuilder $query) : ExplainFinalStep -{ - return ExplainBuilder::create($query); -} - -/** - * Create a LOCK TABLE builder. - * - * Example: lock_table('users', 'orders')->accessExclusive() - * Produces: LOCK TABLE users, orders IN ACCESS EXCLUSIVE MODE - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function lock_table(string ...$tables) : LockFinalStep -{ - return LockBuilder::create(...$tables); -} - -/** - * Create a COMMENT ON builder. - * - * Example: comment(CommentTarget::TABLE, 'users')->is('User accounts table') - * Produces: COMMENT ON TABLE users IS 'User accounts table' - * - * @param CommentTarget $target Target type (TABLE, COLUMN, INDEX, etc.) - * @param string $name Target name (use 'table.column' for COLUMN targets) - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function comment(CommentTarget $target, string $name) : CommentFinalStep -{ - return CommentBuilder::create($target, $name); -} - -/** - * Create a CLUSTER builder. - * - * Example: cluster()->table('users')->using('idx_users_pkey') - * Produces: CLUSTER users USING idx_users_pkey - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function cluster() : ClusterFinalStep -{ - return ClusterBuilder::create(); -} - -/** - * Create a DISCARD builder. - * - * Example: discard(DiscardType::ALL) - * Produces: DISCARD ALL - * - * @param DiscardType $type Type of resources to discard (ALL, PLANS, SEQUENCES, TEMP) - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function discard(DiscardType $type) : DiscardFinalStep -{ - return DiscardBuilder::create($type); -} - -/** - * Create a GRANT privileges builder. - * - * Example: grant(TablePrivilege::SELECT)->onTable('users')->to('app_user') - * Produces: GRANT SELECT ON users TO app_user - * - * Example: grant(TablePrivilege::ALL)->onAllTablesInSchema('public')->to('admin') - * Produces: GRANT ALL ON ALL TABLES IN SCHEMA public TO admin - * - * @param string|TablePrivilege ...$privileges The privileges to grant - * - * @return GrantOnStep Builder for grant options - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function grant(TablePrivilege|string ...$privileges) : GrantOnStep -{ - return GrantBuilder::create(...$privileges); -} - -/** - * Create a GRANT role builder. - * - * Example: grant_role('admin')->to('user1') - * Produces: GRANT admin TO user1 - * - * Example: grant_role('admin', 'developer')->to('user1')->withAdminOption() - * Produces: GRANT admin, developer TO user1 WITH ADMIN OPTION - * - * @param string ...$roles The roles to grant - * - * @return GrantRoleToStep Builder for grant role options - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function grant_role(string ...$roles) : GrantRoleToStep -{ - return GrantRoleBuilder::create(...$roles); -} - -/** - * Create a REVOKE privileges builder. - * - * Example: revoke(TablePrivilege::SELECT)->onTable('users')->from('app_user') - * Produces: REVOKE SELECT ON users FROM app_user - * - * Example: revoke(TablePrivilege::ALL)->onTable('users')->from('app_user')->cascade() - * Produces: REVOKE ALL ON users FROM app_user CASCADE - * - * @param string|TablePrivilege ...$privileges The privileges to revoke - * - * @return RevokeOnStep Builder for revoke options - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function revoke(TablePrivilege|string ...$privileges) : RevokeOnStep -{ - return RevokeBuilder::create(...$privileges); -} - -/** - * Create a REVOKE role builder. - * - * Example: revoke_role('admin')->from('user1') - * Produces: REVOKE admin FROM user1 - * - * Example: revoke_role('admin')->from('user1')->cascade() - * Produces: REVOKE admin FROM user1 CASCADE - * - * @param string ...$roles The roles to revoke - * - * @return RevokeRoleFromStep Builder for revoke role options - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function revoke_role(string ...$roles) : RevokeRoleFromStep -{ - return RevokeRoleBuilder::create(...$roles); -} - -/** - * Create a SET ROLE builder. - * - * Example: set_role('admin') - * Produces: SET ROLE admin - * - * @param string $role The role to set - * - * @return SetRoleFinalStep Builder for set role - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function set_role(string $role) : SetRoleFinalStep -{ - return SetRoleBuilder::create($role); -} - -/** - * Create a RESET ROLE builder. - * - * Example: reset_role() - * Produces: RESET ROLE - * - * @return ResetRoleFinalStep Builder for reset role - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function reset_role() : ResetRoleFinalStep -{ - return ResetRoleBuilder::create(); -} - -/** - * Create a REASSIGN OWNED builder. - * - * Example: reassign_owned('old_role')->to('new_role') - * Produces: REASSIGN OWNED BY old_role TO new_role - * - * @param string ...$roles The roles whose owned objects should be reassigned - * - * @return ReassignOwnedToStep Builder for reassign owned options - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function reassign_owned(string ...$roles) : ReassignOwnedToStep -{ - return ReassignOwnedBuilder::create(...$roles); -} - -/** - * Create a DROP OWNED builder. - * - * Example: drop_owned('role1') - * Produces: DROP OWNED BY role1 - * - * Example: drop_owned('role1', 'role2')->cascade() - * Produces: DROP OWNED BY role1, role2 CASCADE - * - * @param string ...$roles The roles whose owned objects should be dropped - * - * @return DropOwnedFinalStep Builder for drop owned options - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function drop_owned(string ...$roles) : DropOwnedFinalStep -{ - return DropOwnedBuilder::create(...$roles); -} - -/** - * Creates a new function argument for use in function/procedure definitions. - * - * Example: func_arg(data_type_integer()) - * Example: func_arg(data_type_text())->named('username') - * Example: func_arg(data_type_integer())->named('count')->default('0') - * Example: func_arg(data_type_text())->out() - * - * @param DataType $type The PostgreSQL data type for the argument - * - * @return FunctionArgument Builder for function argument options - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function func_arg(DataType $type) : FunctionArgument -{ - return FunctionArgument::of($type); -} - -/** - * Creates a CALL statement builder for invoking a procedure. - * - * Example: call('update_stats')->with(123) - * Produces: CALL update_stats(123) - * - * Example: call('process_data')->with('test', 42, true) - * Produces: CALL process_data('test', 42, true) - * - * @param string $procedure The name of the procedure to call - * - * @return CallFinalStep Builder for call statement options - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function call(string $procedure) : CallFinalStep -{ - return CallBuilder::create($procedure); -} - -/** - * Creates a DO statement builder for executing an anonymous code block. - * - * Example: do_block('BEGIN RAISE NOTICE $$Hello World$$; END;') - * Produces: DO $$ BEGIN RAISE NOTICE $$Hello World$$; END; $$ LANGUAGE plpgsql - * - * Example: do_block('SELECT 1')->language('sql') - * Produces: DO $$ SELECT 1 $$ LANGUAGE sql - * - * @param string $code The anonymous code block to execute - * - * @return DoFinalStep Builder for DO statement options - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function do_block(string $code) : DoFinalStep -{ - return DoBuilder::create($code); -} - -/** - * Creates a type attribute for composite types. - * - * Example: type_attr('name', data_type_text()) - * Produces: name text - * - * Example: type_attr('description', data_type_text())->collate('en_US') - * Produces: description text COLLATE "en_US" - * - * @param string $name The attribute name - * @param DataType $type The attribute type - * - * @return TypeAttribute Type attribute value object - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function type_attr(string $name, DataType $type) : TypeAttribute -{ - return TypeAttribute::of($name, $type); -} - -/** - * Create connection parameters from a connection string. - * - * Accepts libpq-style connection strings: - * - Key-value format: "host=localhost port=5432 dbname=mydb user=myuser password=secret" - * - URI format: "postgresql://user:password@localhost:5432/dbname" - * - * @example - * $params = pgsql_connection('host=localhost dbname=mydb'); - * $params = pgsql_connection('postgresql://user:pass@localhost/mydb'); - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_connection(#[\SensitiveParameter] string $connectionString) : ConnectionParameters -{ - return ConnectionParameters::fromString($connectionString); -} - -/** - * Create connection parameters from a DSN string. - * - * Parses standard PostgreSQL DSN format commonly used in environment variables - * (e.g., DATABASE_URL). Supports postgres://, postgresql://, and pgsql:// schemes. - * - * @param string $dsn DSN string in format: postgres://user:password@host:port/database?options - * - * @throws Client\DsnParserException If the DSN cannot be parsed - * - * @example - * $params = pgsql_connection_dsn('postgres://myuser:secret@localhost:5432/mydb'); - * $params = pgsql_connection_dsn('postgresql://user:pass@db.example.com/app?sslmode=require'); - * $params = pgsql_connection_dsn('pgsql://user:pass@localhost/mydb'); // Symfony/Doctrine format - * $params = pgsql_connection_dsn(getenv('DATABASE_URL')); - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_connection_dsn(#[\SensitiveParameter] string $dsn) : ConnectionParameters -{ - return (new DsnParser())->parse($dsn); -} - -/** - * Create connection parameters from individual values. - * - * Allows specifying connection parameters individually for better type safety - * and IDE support. - * - * @param string $database Database name (required) - * @param string $host Hostname (default: localhost) - * @param int $port Port number (default: 5432) - * @param null|string $user Username (optional) - * @param null|string $password Password (optional) - * @param array $options Additional libpq options - * - * @example - * $params = pgsql_connection_params( - * database: 'mydb', - * host: 'localhost', - * user: 'myuser', - * password: 'secret', - * ); - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_connection_params( - string $database, - string $host = 'localhost', - int $port = 5432, - ?string $user = null, - ?string $password = null, - array $options = [], -) : ConnectionParameters { - return ConnectionParameters::fromParams( - database: $database, - host: $host, - port: $port, - user: $user, - password: $password, - options: $options, - ); -} - -/** - * Create a PostgreSQL client using ext-pgsql. - * - * The client connects immediately and is ready to execute queries. - * For object mapping, provide a RowMapper (use pgsql_mapper() for the default). - * - * @param Client\ConnectionParameters $params Connection parameters - * @param null|ValueConverters $valueConverters Custom type converters (optional) - * @param null|Client\RowMapper $mapper Row mapper for object hydration (optional) - * - * @throws ConnectionException If connection fails - * - * @example - * // Basic client - * $client = pgsql_client(pgsql_connection('host=localhost dbname=mydb')); - * - * // With object mapping - * $client = pgsql_client( - * pgsql_connection('host=localhost dbname=mydb'), - * mapper: pgsql_mapper(), - * ); - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_client( - ConnectionParameters $params, - ?ValueConverters $valueConverters = null, - ?RowMapper $mapper = null, -) : Client\Client { - return PgSqlClient::connect($params, $valueConverters, $mapper); -} - -/** - * Create telemetry options for PostgreSQL client instrumentation. - * - * Controls which telemetry signals (traces, metrics, logs) are enabled - * and how query information is captured. - * - * @param bool $traceQueries Create spans for query execution (default: true) - * @param bool $traceTransactions Create spans for transactions (default: true) - * @param bool $collectMetrics Collect duration and row count metrics (default: true) - * @param bool $logQueries Log executed queries (default: false) - * @param null|int $maxQueryLength Maximum query text length in telemetry (default: 1000, null = unlimited) - * @param bool $includeParameters Include query parameters in telemetry (default: false, security consideration) - * - * @example - * // Default options (traces and metrics enabled) - * $options = postgresql_telemetry_options(); - * - * // Enable query logging - * $options = postgresql_telemetry_options(logQueries: true); - * - * // Disable all but metrics - * $options = postgresql_telemetry_options( - * traceQueries: false, - * traceTransactions: false, - * collectMetrics: true, - * ); - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function postgresql_telemetry_options( - bool $traceQueries = true, - bool $traceTransactions = true, - bool $collectMetrics = true, - bool $logQueries = false, - ?int $maxQueryLength = 1000, - bool $includeParameters = false, - ?int $maxParameters = 10, - ?int $maxParameterLength = 100, -) : PostgreSqlTelemetryOptions { - return new PostgreSqlTelemetryOptions( - traceQueries: $traceQueries, - traceTransactions: $traceTransactions, - collectMetrics: $collectMetrics, - logQueries: $logQueries, - maxQueryLength: $maxQueryLength, - includeParameters: $includeParameters, - maxParameters: $maxParameters, - maxParameterLength: $maxParameterLength, - ); -} - -/** - * Create telemetry configuration for PostgreSQL client. - * - * Bundles telemetry instance, clock, and options needed to instrument a PostgreSQL client. - * - * @param Telemetry $telemetry The telemetry instance - * @param ClockInterface $clock Clock for timestamps - * @param null|PostgreSqlTelemetryOptions $options Telemetry options (default: all enabled) - * - * @example - * $config = postgresql_telemetry_config( - * telemetry(resource(['service.name' => 'my-app'])), - * new SystemClock(), - * ); - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function postgresql_telemetry_config( - Telemetry $telemetry, - ClockInterface $clock, - ?PostgreSqlTelemetryOptions $options = null, -) : PostgreSqlTelemetryConfig { - return new PostgreSqlTelemetryConfig( - telemetry: $telemetry, - clock: $clock, - options: $options ?? new PostgreSqlTelemetryOptions(), - ); -} - -/** - * Wrap a PostgreSQL client with telemetry instrumentation. - * - * Returns a decorator that adds spans, metrics, and logs to all - * query and transaction operations following OpenTelemetry conventions. - * - * @param Client\Client $client The PostgreSQL client to instrument - * @param PostgreSqlTelemetryConfig $telemetryConfig Telemetry configuration - * - * @example - * $client = pgsql_client(pgsql_connection('host=localhost dbname=mydb')); - * - * $traceableClient = traceable_postgresql_client( - * $client, - * postgresql_telemetry_config( - * telemetry(resource(['service.name' => 'my-app'])), - * new SystemClock(), - * postgresql_telemetry_options( - * traceQueries: true, - * traceTransactions: true, - * collectMetrics: true, - * logQueries: true, - * maxQueryLength: 500, - * ), - * ), - * ); - * - * // All operations now traced - * $traceableClient->transaction(function (Client $client) { - * $user = $client->fetchOne('SELECT * FROM users WHERE id = $1', [123]); - * $client->execute('UPDATE users SET last_login = NOW() WHERE id = $1', [123]); - * }); - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function traceable_postgresql_client( - Client\Client $client, - PostgreSqlTelemetryConfig $telemetryConfig, -) : TraceableClient { - return new TraceableClient($client, $telemetryConfig); -} - -/** - * Create a default constructor-based row mapper. - * - * Maps database rows directly to constructor parameters. - * Column names must match parameter names exactly (1:1). - * Use SQL aliases if column names differ from parameter names. - * - * @example - * // DTO where column names match parameter names - * readonly class User { - * public function __construct( - * public int $id, - * public string $name, - * public string $email, - * ) {} - * } - * - * // Usage - * $client = pgsql_client(pgsql_connection('...'), mapper: pgsql_mapper()); - * - * // For snake_case columns, use SQL aliases - * $user = $client->fetchInto( - * User::class, - * 'SELECT id, user_name AS name, user_email AS email FROM users WHERE id = $1', - * [1] - * ); - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_mapper() : ConstructorMapper -{ - return new ConstructorMapper(); -} - -/** - * Wrap a value with explicit PostgreSQL type information for parameter binding. - * - * Use when auto-detection isn't sufficient or when you need to specify - * the exact PostgreSQL type (since one PHP type can map to multiple PostgreSQL types): - * - int could be INT2, INT4, or INT8 - * - string could be TEXT, VARCHAR, or CHAR - * - array must always use typed() since auto-detection cannot determine element type - * - DateTimeInterface could be TIMESTAMP or TIMESTAMPTZ - * - Json could be JSON or JSONB - * - * @param mixed $value The value to bind - * @param PostgreSqlType $targetType The PostgreSQL type to convert the value to - * - * @example - * $client->fetch( - * 'SELECT * FROM users WHERE id = $1 AND tags = $2', - * [ - * typed('550e8400-e29b-41d4-a716-446655440000', PostgreSqlType::UUID), - * typed(['tag1', 'tag2'], PostgreSqlType::TEXT_ARRAY), - * ] - * ); - */ -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function typed(mixed $value, PostgreSqlType $targetType) : TypedValue -{ - return new TypedValue($value, $targetType); -} - -// PostgreSqlType DSL functions - Scalar types - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_text() : PostgreSqlType -{ - return PostgreSqlType::TEXT; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_varchar() : PostgreSqlType -{ - return PostgreSqlType::VARCHAR; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_char() : PostgreSqlType -{ - return PostgreSqlType::CHAR; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_bpchar() : PostgreSqlType -{ - return PostgreSqlType::BPCHAR; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_int2() : PostgreSqlType -{ - return PostgreSqlType::INT2; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_smallint() : PostgreSqlType -{ - return PostgreSqlType::INT2; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_int4() : PostgreSqlType -{ - return PostgreSqlType::INT4; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_integer() : PostgreSqlType -{ - return PostgreSqlType::INT4; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_int8() : PostgreSqlType -{ - return PostgreSqlType::INT8; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_bigint() : PostgreSqlType -{ - return PostgreSqlType::INT8; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_float4() : PostgreSqlType -{ - return PostgreSqlType::FLOAT4; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_real() : PostgreSqlType -{ - return PostgreSqlType::FLOAT4; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_float8() : PostgreSqlType -{ - return PostgreSqlType::FLOAT8; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_double() : PostgreSqlType -{ - return PostgreSqlType::FLOAT8; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_numeric() : PostgreSqlType -{ - return PostgreSqlType::NUMERIC; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_money() : PostgreSqlType -{ - return PostgreSqlType::MONEY; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_bool() : PostgreSqlType -{ - return PostgreSqlType::BOOL; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_boolean() : PostgreSqlType -{ - return PostgreSqlType::BOOL; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_bytea() : PostgreSqlType -{ - return PostgreSqlType::BYTEA; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_bit() : PostgreSqlType -{ - return PostgreSqlType::BIT; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_varbit() : PostgreSqlType -{ - return PostgreSqlType::VARBIT; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_date() : PostgreSqlType -{ - return PostgreSqlType::DATE; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_time() : PostgreSqlType -{ - return PostgreSqlType::TIME; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_timetz() : PostgreSqlType -{ - return PostgreSqlType::TIMETZ; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_timestamp() : PostgreSqlType -{ - return PostgreSqlType::TIMESTAMP; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_timestamptz() : PostgreSqlType -{ - return PostgreSqlType::TIMESTAMPTZ; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_interval() : PostgreSqlType -{ - return PostgreSqlType::INTERVAL; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_json() : PostgreSqlType -{ - return PostgreSqlType::JSON; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_jsonb() : PostgreSqlType -{ - return PostgreSqlType::JSONB; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_uuid() : PostgreSqlType -{ - return PostgreSqlType::UUID; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_inet() : PostgreSqlType -{ - return PostgreSqlType::INET; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_cidr() : PostgreSqlType -{ - return PostgreSqlType::CIDR; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_macaddr() : PostgreSqlType -{ - return PostgreSqlType::MACADDR; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_macaddr8() : PostgreSqlType -{ - return PostgreSqlType::MACADDR8; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_xml() : PostgreSqlType -{ - return PostgreSqlType::XML; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_oid() : PostgreSqlType -{ - return PostgreSqlType::OID; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_text_array() : PostgreSqlType -{ - return PostgreSqlType::TEXT_ARRAY; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_varchar_array() : PostgreSqlType -{ - return PostgreSqlType::VARCHAR_ARRAY; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_int2_array() : PostgreSqlType -{ - return PostgreSqlType::INT2_ARRAY; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_int4_array() : PostgreSqlType -{ - return PostgreSqlType::INT4_ARRAY; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_int8_array() : PostgreSqlType -{ - return PostgreSqlType::INT8_ARRAY; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_float4_array() : PostgreSqlType -{ - return PostgreSqlType::FLOAT4_ARRAY; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_float8_array() : PostgreSqlType -{ - return PostgreSqlType::FLOAT8_ARRAY; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_bool_array() : PostgreSqlType -{ - return PostgreSqlType::BOOL_ARRAY; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_uuid_array() : PostgreSqlType -{ - return PostgreSqlType::UUID_ARRAY; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_json_array() : PostgreSqlType -{ - return PostgreSqlType::JSON_ARRAY; -} - -#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] -function pgsql_type_jsonb_array() : PostgreSqlType -{ - return PostgreSqlType::JSONB_ARRAY; -} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/DSL/parser.php b/src/lib/postgresql/src/Flow/PostgreSql/DSL/parser.php new file mode 100644 index 0000000000..a98d5595cf --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/DSL/parser.php @@ -0,0 +1,340 @@ +parse($sql); +} + +/** + * Returns a fingerprint of the given SQL query. + * Literal values are normalized so they won't affect the fingerprint. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function sql_fingerprint(string $sql) : ?string +{ + return (new Parser())->fingerprint($sql); +} + +/** + * Normalize SQL query by replacing literal values and named parameters with positional parameters. + * WHERE id = :id will be changed into WHERE id = $1 + * WHERE id = 1 will be changed into WHERE id = $1. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function sql_normalize(string $sql) : ?string +{ + return (new Parser())->normalize($sql); +} + +/** + * Normalize utility SQL statements (DDL like CREATE, ALTER, DROP). + * This handles DDL statements differently from pg_normalize() which is optimized for DML. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function sql_normalize_utility(string $sql) : ?string +{ + return (new Parser())->normalizeUtility($sql); +} + +/** + * Split string with multiple SQL statements into array of individual statements. + * + * @return array + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function sql_split(string $sql) : array +{ + return (new Parser())->split($sql); +} + +/** + * Create DeparseOptions for configuring SQL formatting. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function sql_deparse_options() : DeparseOptions +{ + return DeparseOptions::new(); +} + +/** + * Convert a ParsedQuery AST back to SQL string. + * + * When called without options, returns the SQL as a simple string. + * When called with DeparseOptions, applies formatting (pretty-printing, indentation, etc.). + * + * @throws \RuntimeException if deparsing fails + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function sql_deparse(ParsedQuery $query, ?DeparseOptions $options = null) : string +{ + return $query->deparse($options); +} + +/** + * Parse and format SQL query with pretty printing. + * + * This is a convenience function that parses SQL and returns it formatted. + * + * @param string $sql The SQL query to format + * @param null|DeparseOptions $options Formatting options (defaults to pretty-print enabled) + * + * @throws \RuntimeException if parsing or deparsing fails + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function sql_format(string $sql, ?DeparseOptions $options = null) : string +{ + return (new Parser())->parse($sql)->deparse($options ?? DeparseOptions::new()); +} + +/** + * Generate a summary of parsed queries in protobuf format. + * Useful for query monitoring and logging without full AST overhead. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function sql_summary(string $sql, int $options = 0, int $truncateLimit = 0) : string +{ + return (new Parser())->summary($sql, $options, $truncateLimit); +} + +/** + * Transform a SQL query into a paginated query with LIMIT and OFFSET. + * + * @param string $sql The SQL query to paginate + * @param int $limit Maximum number of rows to return + * @param int $offset Number of rows to skip (requires ORDER BY in query) + * + * @return string The paginated SQL query + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function sql_to_paginated_query(string $sql, int $limit, int $offset = 0) : string +{ + $query = (new Parser())->parse($sql); + $query->traverse(new PaginationModifier(new PaginationConfig($limit, $offset))); + + return $query->deparse(); +} + +/** + * Transform a SQL query to limit results to a specific number of rows. + * + * @param string $sql The SQL query to limit + * @param int $limit Maximum number of rows to return + * + * @return string The limited SQL query + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function sql_to_limited_query(string $sql, int $limit) : string +{ + $query = (new Parser())->parse($sql); + $query->traverse(new PaginationModifier(new PaginationConfig($limit))); + + return $query->deparse(); +} + +/** + * Transform a SQL query into a COUNT query for pagination. + * + * Wraps the query in: SELECT COUNT(*) FROM (...) AS _count_subq + * Removes ORDER BY and LIMIT/OFFSET from the inner query. + * + * @param string $sql The SQL query to transform + * + * @return string The COUNT query + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function sql_to_count_query(string $sql) : string +{ + $query = (new Parser())->parse($sql); + $query->traverse(new CountModifier()); + + return $query->deparse(); +} + +/** + * Transform a SQL query into a keyset (cursor-based) paginated query. + * + * More efficient than OFFSET for large datasets - uses indexed WHERE conditions. + * Automatically detects existing query parameters and appends keyset placeholders at the end. + * + * @param string $sql The SQL query to paginate (must have ORDER BY) + * @param int $limit Maximum number of rows to return + * @param list $columns Columns for keyset pagination (must match ORDER BY) + * @param null|list $cursor Values from last row of previous page (null for first page) + * + * @return string The paginated SQL query + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function sql_to_keyset_query(string $sql, int $limit, array $columns, ?array $cursor = null) : string +{ + $query = (new Parser())->parse($sql); + $query->traverse(new KeysetPaginationModifier(new KeysetPaginationConfig($limit, $columns, $cursor))); + + return $query->deparse(); +} + +/** + * Create a KeysetColumn for keyset pagination. + * + * @param string $column Column name (can include table alias like "u.id") + * @param SortOrder $order Sort order (ASC or DESC) + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function sql_keyset_column(string $column, SortOrder $order = SortOrder::ASC) : KeysetColumn +{ + return new KeysetColumn($column, $order); +} + +/** + * Extract columns from a parsed SQL query. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function sql_query_columns(ParsedQuery $query) : Columns +{ + return new Columns($query); +} + +/** + * Extract tables from a parsed SQL query. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function sql_query_tables(ParsedQuery $query) : Tables +{ + return new Tables($query); +} + +/** + * Extract functions from a parsed SQL query. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function sql_query_functions(ParsedQuery $query) : Functions +{ + return new Functions($query); +} + +/** + * Extract ORDER BY clauses from a parsed SQL query. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function sql_query_order_by(ParsedQuery $query) : OrderByExtractor +{ + return new OrderByExtractor($query); +} + +/** + * Get the maximum nesting depth of a SQL query. + * + * Example: + * - "SELECT * FROM t" => 1 + * - "SELECT * FROM (SELECT * FROM t)" => 2 + * - "SELECT * FROM (SELECT * FROM (SELECT * FROM t))" => 3 + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function sql_query_depth(string $sql) : int +{ + return (new QueryDepth(sql_parse($sql)))->depth(); +} + +/** + * Transform a SQL query into an EXPLAIN query. + * + * Returns the modified SQL with EXPLAIN wrapped around it. + * Defaults to EXPLAIN ANALYZE with JSON format for easy parsing. + * + * @param string $sql The SQL query to explain + * @param null|ExplainConfig $config EXPLAIN configuration (defaults to forAnalysis()) + * + * @return string The EXPLAIN query + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function sql_to_explain(string $sql, ?ExplainConfig $config = null) : string +{ + $config ??= ExplainConfig::forAnalysis(); + $query = (new Parser())->parse($sql); + $query->traverse(new ExplainModifier($config)); + + return $query->deparse(); +} + +/** + * Create an ExplainConfig for customizing EXPLAIN options. + * + * @param bool $analyze Whether to actually execute the query (ANALYZE) + * @param bool $verbose Include verbose output + * @param bool $costs Include cost estimates (default true) + * @param bool $buffers Include buffer usage statistics (requires analyze) + * @param bool $timing Include timing information (requires analyze) + * @param ExplainFormat $format Output format (JSON recommended for parsing) + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function sql_explain_config( + bool $analyze = true, + bool $verbose = false, + bool $costs = true, + bool $buffers = true, + bool $timing = true, + ExplainFormat $format = ExplainFormat::JSON, +) : ExplainConfig { + return new ExplainConfig( + analyze: $analyze, + verbose: $verbose, + costs: $costs, + buffers: $buffers, + timing: $timing, + format: $format, + ); +} + +/** + * Create an ExplainModifier for transforming queries into EXPLAIN queries. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function sql_explain_modifier(ExplainConfig $config) : ExplainModifier +{ + return new ExplainModifier($config); +} + +/** + * Parse EXPLAIN JSON output into a Plan object. + * + * @param string $jsonOutput The JSON output from EXPLAIN (FORMAT JSON) + * + * @return Plan The parsed execution plan + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function sql_explain_parse(string $jsonOutput) : Plan +{ + return (new ExplainParser())->parse($jsonOutput); +} + +/** + * Create a plan analyzer for analyzing EXPLAIN plans. + * + * @param Plan $plan The execution plan to analyze + * + * @return PlanAnalyzer The analyzer for extracting insights + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function sql_analyze(Plan $plan) : PlanAnalyzer +{ + return new PlanAnalyzer($plan); +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/DSL/query.php b/src/lib/postgresql/src/Flow/PostgreSql/DSL/query.php new file mode 100644 index 0000000000..8d09a8ea22 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/DSL/query.php @@ -0,0 +1,1156 @@ + $e instanceof Expression ? $e : col($e), + $expressions, + ); + + return SelectBuilder::create()->select(...$expressions); +} + +/** + * Create a SelectFinalStep from a raw SQL SELECT string. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function parsed_select(string $sql) : ParsedSelect +{ + return new ParsedSelect($sql); +} + +/** + * Create a WITH clause builder for CTEs. + * + * Example: with(cte('users', $subquery))->select(star())->from(table('users')) + * Example: with(cte('a', $q1), cte('b', $q2))->recursive()->select(...)->from(table('a')) + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function with(CTE ...$ctes) : WithBuilder +{ + if ($ctes === []) { + throw new \InvalidArgumentException('At least one CTE is required'); + } + + return new WithBuilder(new WithClause($ctes)); +} + +/** + * Create a new INSERT query builder. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function insert() : InsertIntoStep +{ + return InsertBuilder::create(); +} + +/** + * Create an optimized bulk INSERT query for high-performance multi-row inserts. + * + * Unlike insert() which uses immutable builder patterns (O(n²) for n rows), + * this function generates SQL directly using string operations (O(n) complexity). + * + * @param string $table Table name + * @param list $columns Column names + * @param int $rowCount Number of rows to insert + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function bulk_insert(string $table, array $columns, int $rowCount) : BulkInsert +{ + return BulkInsert::into($table, $columns, $rowCount); +} + +/** + * Create a new UPDATE query builder. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function update() : UpdateTableStep +{ + return UpdateBuilder::create(); +} + +/** + * Create a new DELETE query builder. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function delete() : DeleteFromStep +{ + return DeleteBuilder::create(); +} + +/** + * Create a new MERGE query builder. + * + * @param string $table Target table name + * @param null|string $alias Optional table alias + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function merge(string $table, ?string $alias = null) : MergeUsingStep +{ + return MergeBuilder::create()->into($table, $alias); +} + +/** + * Create a new COPY query builder for data import/export. + * + * Usage: + * copy()->from('users')->file('/tmp/users.csv')->format(CopyFormat::CSV) + * copy()->to('users')->file('/tmp/users.csv')->format(CopyFormat::CSV) + * copy()->toQuery(select(...))->file('/tmp/data.csv') + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function copy() : CopyFactory +{ + return new CopyFactory(); +} + +/** + * Create a column reference expression. + * + * Can be used in two modes: + * - Parse mode: col('users.id') or col('schema.table.column') - parses dot-separated string + * - Explicit mode: col('id', 'users') or col('id', 'users', 'schema') - separate arguments + * + * When $table or $schema is provided, $column must be a plain column name (no dots). + * + * @param string $column Column name, or dot-separated path like "table.column" or "schema.table.column" + * @param null|string $table Table name (optional, triggers explicit mode) + * @param null|string $schema Schema name (optional, requires $table) + * + * @throws InvalidExpressionException when $schema is provided without $table, or when $column contains dots in explicit mode + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function col(string $column, ?string $table = null, ?string $schema = null) : Column +{ + if ($table !== null || $schema !== null) { + if ($schema !== null && $table === null) { + throw new InvalidExpressionException('Cannot specify schema without table in col()'); + } + + if (\str_contains($column, '.')) { + throw new InvalidExpressionException('Column name cannot contain dots when table or schema is specified. Use col("table.column") or col("column", "table") but not both.'); + } + + if ($schema !== null && $table !== null) { + return Column::schemaTableColumn($schema, $table, $column); + } + + if ($table === null) { + return Column::fromParts(QualifiedIdentifier::parse($column)->parts()); + } + + return Column::tableColumn($table, $column); + } + + return Column::fromParts(QualifiedIdentifier::parse($column)->parts()); +} + +/** + * Create a SELECT * expression. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function star(?string $table = null) : Star +{ + return $table !== null ? Star::fromTable($table) : Star::all(); +} + +/** + * Create a literal value for use in queries. + * + * Automatically detects the type and creates the appropriate literal: + * - literal('hello') creates a string literal + * - literal(42) creates an integer literal + * - literal(3.14) creates a float literal + * - literal(true) creates a boolean literal + * - literal(null) creates a NULL literal + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function literal(string|int|float|bool|null $value) : Literal +{ + return match (true) { + $value === null => Literal::null(), + \is_string($value) => Literal::string($value), + \is_int($value) => Literal::int($value), + \is_float($value) => Literal::float($value), + \is_bool($value) => Literal::bool($value), + }; +} + +/** + * Create a positional parameter ($1, $2, etc.). + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function param(int $position) : Parameter +{ + return Parameter::positional($position); +} + +/** + * @return list + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function parameters(int $count, int $startAt = 1) : array +{ + if ($count < 1) { + throw new \InvalidArgumentException('Parameter count must be at least 1'); + } + + if ($startAt < 1) { + throw new \InvalidArgumentException('Start position must be at least 1'); + } + + $params = []; + + for ($i = 0; $i < $count; $i++) { + $params[] = Parameter::positional($startAt + $i); + } + + return $params; +} + +/** + * Create a function call expression. + * + * @param string $name Function name (can include schema like "pg_catalog.now") + * @param list $args Function arguments + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function func(string $name, array $args = []) : FunctionCall +{ + return new FunctionCall( + QualifiedIdentifier::parse($name)->parts(), + \array_map( + static fn (string|Expression $e) : Expression => $e instanceof Expression ? $e : col($e), + $args, + ), + ); +} + +/** + * Create an aggregate function call (COUNT, SUM, AVG, etc.). + * + * @param string $name Aggregate function name + * @param list $args Function arguments + * @param bool $distinct Use DISTINCT modifier + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function agg(string $name, array $args = [], bool $distinct = false) : AggregateCall +{ + return new AggregateCall( + [$name], + \array_map( + static fn (string|Expression $e) : Expression => $e instanceof Expression ? $e : col($e), + $args, + ), + false, + $distinct, + ); +} + +/** + * Create COUNT(*) aggregate. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function agg_count(string|Expression|null $expr = null, bool $distinct = false) : AggregateCall +{ + if ($expr === null) { + return new AggregateCall(['count'], [], true, false); + } + + return new AggregateCall(['count'], [$expr instanceof Expression ? $expr : col($expr)], false, $distinct); +} + +/** + * Create SUM aggregate. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function agg_sum(string|Expression $expr, bool $distinct = false) : AggregateCall +{ + return new AggregateCall(['sum'], [$expr instanceof Expression ? $expr : col($expr)], false, $distinct); +} + +/** + * Create AVG aggregate. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function agg_avg(string|Expression $expr, bool $distinct = false) : AggregateCall +{ + return new AggregateCall(['avg'], [$expr instanceof Expression ? $expr : col($expr)], false, $distinct); +} + +/** + * Create MIN aggregate. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function agg_min(string|Expression $expr) : AggregateCall +{ + return new AggregateCall(['min'], [$expr instanceof Expression ? $expr : col($expr)]); +} + +/** + * Create MAX aggregate. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function agg_max(string|Expression $expr) : AggregateCall +{ + return new AggregateCall(['max'], [$expr instanceof Expression ? $expr : col($expr)]); +} + +/** + * Create a COALESCE expression. + * + * @param Expression|string ...$expressions Expressions to coalesce + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function coalesce(string|Expression ...$expressions) : Coalesce +{ + return new Coalesce(\array_map( + static fn (string|Expression $e) : Expression => $e instanceof Expression ? $e : col($e), + \array_values($expressions), + )); +} + +/** + * Create a NULLIF expression. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function nullif(string|Expression $expr1, string|Expression $expr2) : NullIf +{ + return new NullIf( + $expr1 instanceof Expression ? $expr1 : col($expr1), + $expr2 instanceof Expression ? $expr2 : col($expr2), + ); +} + +/** + * Create a GREATEST expression. + * + * @param Expression|string ...$expressions Expressions to compare + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function greatest(string|Expression ...$expressions) : Greatest +{ + return new Greatest(\array_map( + static fn (string|Expression $e) : Expression => $e instanceof Expression ? $e : col($e), + \array_values($expressions), + )); +} + +/** + * Create a LEAST expression. + * + * @param Expression|string ...$expressions Expressions to compare + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function least(string|Expression ...$expressions) : Least +{ + return new Least(\array_map( + static fn (string|Expression $e) : Expression => $e instanceof Expression ? $e : col($e), + \array_values($expressions), + )); +} + +/** + * Create a type cast expression. + * + * @param Expression $expr Expression to cast + * @param ColumnType $dataType Target data type (use column_type_* functions) + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function cast(string|Expression $expr, ColumnType $dataType) : TypeCast +{ + return new TypeCast($expr instanceof Expression ? $expr : col($expr), $dataType); +} + +/** + * SQL standard CURRENT_TIMESTAMP function. + * + * Returns the current date and time (at the start of the transaction). + * Useful as a column default value or in SELECT queries. + * + * Example: column('created_at', column_type_timestamp())->default(current_timestamp()) + * Example: select()->select(current_timestamp()->as('now')) + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function current_timestamp() : SQLValueFunctionExpression +{ + return SQLValueFunctionExpression::currentTimestamp(); +} + +/** + * SQL standard CURRENT_DATE function. + * + * Returns the current date (at the start of the transaction). + * Useful as a column default value or in SELECT queries. + * + * Example: column('birth_date', column_type_date())->default(current_date()) + * Example: select()->select(current_date()->as('today')) + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function current_date() : SQLValueFunctionExpression +{ + return SQLValueFunctionExpression::currentDate(); +} + +/** + * SQL standard CURRENT_TIME function. + * + * Returns the current time (at the start of the transaction). + * Useful as a column default value or in SELECT queries. + * + * Example: column('start_time', column_type_time())->default(current_time()) + * Example: select()->select(current_time()->as('now_time')) + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function current_time() : SQLValueFunctionExpression +{ + return SQLValueFunctionExpression::currentTime(); +} + +/** + * Create a CASE expression. + * + * @param non-empty-list $whenClauses WHEN clauses + * @param null|Expression|string $elseResult ELSE result (optional) + * @param null|Expression|string $operand CASE operand for simple CASE (optional) + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function case_when(array $whenClauses, string|Expression|null $elseResult = null, string|Expression|null $operand = null) : CaseExpression +{ + return new CaseExpression( + $operand === null ? null : ($operand instanceof Expression ? $operand : col($operand)), + \array_values($whenClauses), + $elseResult === null ? null : ($elseResult instanceof Expression ? $elseResult : col($elseResult)), + ); +} + +/** + * Create a WHEN clause for CASE expression. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function when(string|Expression $condition, string|Expression $result) : WhenClause +{ + return new WhenClause( + $condition instanceof Expression ? $condition : col($condition), + $result instanceof Expression ? $result : col($result), + ); +} + +/** + * Create a subquery expression. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function sub_select(SelectFinalStep $query) : Subquery +{ + $node = new Node(); + $node->setSelectStmt($query->toAst()); + + return new Subquery($node); +} + +/** + * Create an array expression. + * + * @param list $elements Array elements + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function array_expr(array $elements) : ArrayExpression +{ + return new ArrayExpression(\array_map( + static fn (string|Expression $e) : Expression => $e instanceof Expression ? $e : col($e), + \array_values($elements), + )); +} + +/** + * Create a row expression. + * + * @param list $elements Row elements + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function row_expr(array $elements) : RowExpression +{ + return new RowExpression(\array_map( + static fn (string|Expression $e) : Expression => $e instanceof Expression ? $e : col($e), + \array_values($elements), + )); +} + +/** + * Create a binary expression (left op right). + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function binary_expr(string|Expression $left, string $operator, string|Expression $right) : BinaryExpression +{ + return new BinaryExpression( + $left instanceof Expression ? $left : col($left), + $operator, + $right instanceof Expression ? $right : col($right), + ); +} + +/** + * Create a window function. + * + * @param string $name Function name + * @param list $args Function arguments + * @param list $partitionBy PARTITION BY expressions + * @param list $orderBy ORDER BY items + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function window_func( + string $name, + array $args = [], + array $partitionBy = [], + array $orderBy = [], +) : WindowFunction { + $coerce = static fn (string|Expression $e) : Expression => $e instanceof Expression ? $e : col($e); + + return new WindowFunction( + [$name], + \array_map($coerce, \array_values($args)), + \array_map($coerce, \array_values($partitionBy)), + \array_values($orderBy), + ); +} + +/** + * Concatenate expressions with the || operator. + * + * Example: concat(col('schema'), literal('.'), col('table')) + * Produces: schema || '.' || table + * + * @param Expression|string ...$expressions At least 2 expressions to concatenate + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function concat(string|Expression ...$expressions) : BinaryExpression +{ + if (\count($expressions) < 2) { + throw InvalidExpressionException::emptyArray('concat requires at least 2 expressions'); + } + + $expressions = \array_map( + static fn (string|Expression $e) : Expression => $e instanceof Expression ? $e : col($e), + $expressions, + ); + + $result = $expressions[0]; + + for ($i = 1; $i < \count($expressions); $i++) { + $result = new BinaryExpression($result, '||', $expressions[$i]); + } + + /** @var BinaryExpression $result */ + return $result; +} + +/** + * Create a table reference. + * + * Supports dot notation for schema-qualified names: "public.users" or explicit schema parameter. + * Double-quoted identifiers preserve dots: '"my.table"' creates a single identifier. + * + * @param string $name Table name (may include schema as "schema.table") + * @param null|string $schema Schema name (optional, overrides parsed schema) + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function table(string $name, ?string $schema = null) : Table +{ + if ($schema !== null) { + return new Table($name, $schema); + } + + $identifier = QualifiedIdentifier::parse($name); + + return new Table($identifier->name(), $identifier->schema()); +} + +/** + * Create a derived table (subquery in FROM clause). + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function derived(SelectFinalStep $query, string $alias) : DerivedTable +{ + $node = new Node(); + $node->setSelectStmt($query->toAst()); + + return new DerivedTable($node, $alias); +} + +/** + * Create a LATERAL subquery. + * + * @param TableReference $reference The subquery or table function reference + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function lateral(TableReference $reference) : Lateral +{ + return new Lateral($reference); +} + +/** + * Create a table function reference. + * + * @param FunctionCall $function The table-valued function + * @param bool $withOrdinality Whether to add WITH ORDINALITY + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function table_func(FunctionCall $function, bool $withOrdinality = false) : TableFunction +{ + return new TableFunction($function, $withOrdinality); +} + +/** + * Create a VALUES clause as a table reference. + * + * Usage: + * select()->from( + * values_table( + * row_expr([literal(1), literal('Alice')]), + * row_expr([literal(2), literal('Bob')]) + * )->as('t', ['id', 'name']) + * ) + * + * Generates: SELECT * FROM (VALUES (1, 'Alice'), (2, 'Bob')) AS t(id, name) + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function values_table(RowExpression ...$rows) : ValuesTable +{ + return new ValuesTable($rows); +} + +/** + * Create an ORDER BY item. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function order_by( + string|Expression $expr, + SortDirection $direction = SortDirection::ASC, + NullsPosition $nulls = NullsPosition::DEFAULT, +) : OrderBy { + return new OrderBy($expr instanceof Expression ? $expr : col($expr), $direction, $nulls); +} + +/** + * Create an ORDER BY item with ASC direction. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function asc(string|Expression $expr, NullsPosition $nulls = NullsPosition::DEFAULT) : OrderBy +{ + return new OrderBy($expr instanceof Expression ? $expr : col($expr), SortDirection::ASC, $nulls); +} + +/** + * Create an ORDER BY item with DESC direction. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function desc(string|Expression $expr, NullsPosition $nulls = NullsPosition::DEFAULT) : OrderBy +{ + return new OrderBy($expr instanceof Expression ? $expr : col($expr), SortDirection::DESC, $nulls); +} + +/** + * Create a CTE (Common Table Expression). + * + * @param string $name CTE name + * @param SelectFinalStep $query CTE query + * @param array $columnNames Column aliases (optional) + * @param CTEMaterialization $materialization Materialization hint + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function cte( + string $name, + SelectFinalStep $query, + array $columnNames = [], + CTEMaterialization $materialization = CTEMaterialization::DEFAULT, + bool $recursive = false, +) : CTE { + $node = new Node(); + $node->setSelectStmt($query->toAst()); + + return new CTE($name, $node, $columnNames, $materialization, $recursive); +} + +/** + * Create a window definition for WINDOW clause. + * + * @param string $name Window name + * @param list $partitionBy PARTITION BY expressions + * @param list $orderBy ORDER BY items + * @param null|WindowFrame $frame Window frame specification + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function window_def( + string $name, + array $partitionBy = [], + array $orderBy = [], + ?WindowFrame $frame = null, +) : WindowDefinition { + return new WindowDefinition( + $name, + \array_map( + static fn (string|Expression $e) : Expression => $e instanceof Expression ? $e : col($e), + \array_values($partitionBy), + ), + \array_values($orderBy), + $frame, + ); +} + +/** + * Create a window frame specification. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function window_frame( + FrameMode $mode, + FrameBound $start, + ?FrameBound $end = null, + FrameExclusion $exclusion = FrameExclusion::NO_OTHERS, +) : WindowFrame { + return new WindowFrame($mode, $start, $end, $exclusion); +} + +/** + * Create a frame bound for CURRENT ROW. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function frame_current_row() : FrameBound +{ + return FrameBound::currentRow(); +} + +/** + * Create a frame bound for UNBOUNDED PRECEDING. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function frame_unbounded_preceding() : FrameBound +{ + return FrameBound::unboundedPreceding(); +} + +/** + * Create a frame bound for UNBOUNDED FOLLOWING. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function frame_unbounded_following() : FrameBound +{ + return FrameBound::unboundedFollowing(); +} + +/** + * Create a frame bound for N PRECEDING. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function frame_preceding(string|Expression $offset) : FrameBound +{ + return FrameBound::preceding($offset instanceof Expression ? $offset : col($offset)); +} + +/** + * Create a frame bound for N FOLLOWING. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function frame_following(string|Expression $offset) : FrameBound +{ + return FrameBound::following($offset instanceof Expression ? $offset : col($offset)); +} + +/** + * Create a locking clause (FOR UPDATE, FOR SHARE, etc.). + * + * @param LockStrength $strength Lock strength + * @param list $tables Tables to lock (empty for all) + * @param LockWaitPolicy $waitPolicy Wait policy + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function lock_for( + LockStrength $strength, + array $tables = [], + LockWaitPolicy $waitPolicy = LockWaitPolicy::DEFAULT, +) : LockingClause { + return new LockingClause($strength, \array_values($tables), $waitPolicy); +} + +/** + * Create a FOR UPDATE locking clause. + * + * @param list $tables Tables to lock (empty for all) + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function for_update(array $tables = []) : LockingClause +{ + return LockingClause::forUpdate(\array_values($tables)); +} + +/** + * Create a FOR SHARE locking clause. + * + * @param list $tables Tables to lock (empty for all) + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function for_share(array $tables = []) : LockingClause +{ + return LockingClause::forShare(\array_values($tables)); +} + +/** + * Create an ON CONFLICT DO NOTHING clause. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function on_conflict_nothing(?ConflictTarget $target = null) : OnConflictClause +{ + return OnConflictClause::doNothing($target); +} + +/** + * Create an ON CONFLICT DO UPDATE clause. + * + * @param ConflictTarget $target Conflict target (columns or constraint) + * @param array $updates Column updates + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function on_conflict_update(ConflictTarget $target, array $updates) : OnConflictClause +{ + return OnConflictClause::doUpdate($target, \array_map( + static fn (string|Expression $e) : Expression => $e instanceof Expression ? $e : col($e), + $updates, + )); +} + +/** + * Create a conflict target for ON CONFLICT (columns). + * + * @param list $columns Columns that define uniqueness + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function conflict_columns(array $columns) : ConflictTarget +{ + return ConflictTarget::columns(\array_values($columns)); +} + +/** + * Create a conflict target for ON CONFLICT ON CONSTRAINT. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function conflict_constraint(string $name) : ConflictTarget +{ + return ConflictTarget::constraint($name); +} + +/** + * Create a RETURNING clause. + * + * @param Expression|string ...$expressions Expressions to return + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function returning(string|Expression ...$expressions) : ReturningClause +{ + return new ReturningClause(\array_map( + static fn (string|Expression $e) : Expression => $e instanceof Expression ? $e : col($e), + \array_values($expressions), + )); +} + +/** + * Create a RETURNING * clause. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function returning_all() : ReturningClause +{ + return ReturningClause::all(); +} + +/** + * Create a BEGIN transaction builder. + * + * Example: begin()->isolationLevel(IsolationLevel::SERIALIZABLE)->readOnly() + * Produces: BEGIN ISOLATION LEVEL SERIALIZABLE READ ONLY + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function begin() : BeginOptionsStep +{ + return BeginBuilder::create(); +} + +/** + * Create a COMMIT transaction builder. + * + * Example: commit()->andChain() + * Produces: COMMIT AND CHAIN + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function commit() : CommitOptionsStep +{ + return CommitBuilder::create(); +} + +/** + * Create a ROLLBACK transaction builder. + * + * Example: rollback()->toSavepoint('my_savepoint') + * Produces: ROLLBACK TO SAVEPOINT my_savepoint + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function rollback() : RollbackOptionsStep +{ + return RollbackBuilder::create(); +} + +/** + * Create a SAVEPOINT. + * + * Example: savepoint('my_savepoint') + * Produces: SAVEPOINT my_savepoint + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function savepoint(string $name) : SavepointFinalStep +{ + return SavepointBuilder::create($name); +} + +/** + * Release a SAVEPOINT. + * + * Example: release_savepoint('my_savepoint') + * Produces: RELEASE my_savepoint + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function release_savepoint(string $name) : SavepointFinalStep +{ + return SavepointBuilder::release($name); +} + +/** + * Create a SET TRANSACTION builder. + * + * Example: set_transaction()->isolationLevel(IsolationLevel::SERIALIZABLE)->readOnly() + * Produces: SET TRANSACTION ISOLATION LEVEL SERIALIZABLE, READ ONLY + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function set_transaction() : SetTransactionOptionsStep +{ + return SetTransactionBuilder::create(); +} + +/** + * Create a SET SESSION CHARACTERISTICS AS TRANSACTION builder. + * + * Example: set_session_transaction()->isolationLevel(IsolationLevel::SERIALIZABLE) + * Produces: SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function set_session_transaction() : SetTransactionOptionsStep +{ + return SetTransactionBuilder::session(); +} + +/** + * Create a SET TRANSACTION SNAPSHOT builder. + * + * Example: transaction_snapshot('00000003-0000001A-1') + * Produces: SET TRANSACTION SNAPSHOT '00000003-0000001A-1' + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function transaction_snapshot(string $snapshotId) : SetTransactionFinalStep +{ + return SetTransactionBuilder::create()->snapshot($snapshotId); +} + +/** + * Create a PREPARE TRANSACTION builder. + * + * Example: prepare_transaction('my_transaction') + * Produces: PREPARE TRANSACTION 'my_transaction' + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function prepare_transaction(string $transactionId) : PreparedTransactionFinalStep +{ + return PreparedTransactionBuilder::prepare($transactionId); +} + +/** + * Create a COMMIT PREPARED builder. + * + * Example: commit_prepared('my_transaction') + * Produces: COMMIT PREPARED 'my_transaction' + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function commit_prepared(string $transactionId) : PreparedTransactionFinalStep +{ + return PreparedTransactionBuilder::commitPrepared($transactionId); +} + +/** + * Create a ROLLBACK PREPARED builder. + * + * Example: rollback_prepared('my_transaction') + * Produces: ROLLBACK PREPARED 'my_transaction' + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function rollback_prepared(string $transactionId) : PreparedTransactionFinalStep +{ + return PreparedTransactionBuilder::rollbackPrepared($transactionId); +} + +/** + * Declare a server-side cursor for a query. + * + * Cursors must be declared within a transaction and provide memory-efficient + * iteration over large result sets via FETCH commands. + * + * Example with query builder: + * declare_cursor('my_cursor', select(star())->from(table('users')))->noScroll() + * Produces: DECLARE my_cursor NO SCROLL CURSOR FOR SELECT * FROM users + * + * Example with raw SQL: + * declare_cursor('my_cursor', 'SELECT * FROM users WHERE active = true')->withHold() + * Produces: DECLARE my_cursor NO SCROLL CURSOR WITH HOLD FOR SELECT * FROM users WHERE active = true + * + * @param string $cursorName Unique cursor name + * @param SelectFinalStep|Sql|string $query Query to iterate over + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function declare_cursor(string $cursorName, SelectFinalStep|string|Sql $query) : DeclareCursorOptionsStep +{ + if ($query instanceof SelectFinalStep) { + return DeclareCursorBuilder::create($cursorName, $query); + } + + return DeclareCursorBuilder::createFromSql($cursorName, $query); +} + +/** + * Fetch rows from a cursor. + * + * Example: fetch('my_cursor')->forward(100) + * Produces: FETCH FORWARD 100 my_cursor + * + * Example: fetch('my_cursor')->all() + * Produces: FETCH ALL my_cursor + * + * @param string $cursorName Cursor to fetch from + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function fetch(string $cursorName) : FetchCursorBuilder +{ + return FetchCursorBuilder::create($cursorName); +} + +/** + * Close a cursor. + * + * Example: close_cursor('my_cursor') + * Produces: CLOSE my_cursor + * + * Example: close_cursor() - closes all cursors + * Produces: CLOSE ALL + * + * @param null|string $cursorName Cursor to close, or null to close all + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function close_cursor(?string $cursorName = null) : CloseCursorFinalStep +{ + if ($cursorName === null) { + return CloseCursorBuilder::closeAll(); + } + + return CloseCursorBuilder::close($cursorName); +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/DSL/schema.php b/src/lib/postgresql/src/Flow/PostgreSql/DSL/schema.php new file mode 100644 index 0000000000..028387e3ec --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/DSL/schema.php @@ -0,0 +1,1783 @@ + $columns Local columns + * @param string $referenceTable Referenced table + * @param list $referenceColumns Referenced columns (defaults to same as $columns if empty) + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function foreign_key(array $columns, string $referenceTable, array $referenceColumns = []) : ForeignKeyConstraint +{ + return ForeignKeyConstraint::create($columns, $referenceTable, $referenceColumns); +} + +/** + * Create a CHECK constraint. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function check_constraint(Condition $condition) : CheckConstraint +{ + return CheckConstraint::create($condition); +} + +/** + * Create a factory for building CREATE statements. + * + * Provides a unified entry point for all CREATE operations: + * - create()->table() - CREATE TABLE + * - create()->tableAs() - CREATE TABLE AS + * - create()->index() - CREATE INDEX + * - create()->view() - CREATE VIEW + * - create()->materializedView() - CREATE MATERIALIZED VIEW + * - create()->sequence() - CREATE SEQUENCE + * - create()->schema() - CREATE SCHEMA + * - create()->role() - CREATE ROLE + * - create()->function() - CREATE FUNCTION + * - create()->procedure() - CREATE PROCEDURE + * - create()->trigger() - CREATE TRIGGER + * - create()->rule() - CREATE RULE + * - create()->extension() - CREATE EXTENSION + * - create()->compositeType() - CREATE TYPE (composite) + * - create()->enumType() - CREATE TYPE (enum) + * - create()->rangeType() - CREATE TYPE (range) + * - create()->domain() - CREATE DOMAIN + * + * Example: create()->table('users')->columns(col_def('id', column_type_serial())) + * Example: create()->index('idx_email')->on('users')->columns('email') + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::SCHEMA)] +function create() : CreateFactory +{ + return new CreateFactory(); +} + +/** + * Create a factory for building DROP statements. + * + * Provides a unified entry point for all DROP operations: + * - drop()->table() - DROP TABLE + * - drop()->index() - DROP INDEX + * - drop()->view() - DROP VIEW + * - drop()->materializedView() - DROP MATERIALIZED VIEW + * - drop()->sequence() - DROP SEQUENCE + * - drop()->schema() - DROP SCHEMA + * - drop()->role() - DROP ROLE + * - drop()->function() - DROP FUNCTION + * - drop()->procedure() - DROP PROCEDURE + * - drop()->trigger() - DROP TRIGGER + * - drop()->rule() - DROP RULE + * - drop()->extension() - DROP EXTENSION + * - drop()->type() - DROP TYPE + * - drop()->domain() - DROP DOMAIN + * - drop()->owned() - DROP OWNED + * + * Example: drop()->table('users', 'orders')->ifExists()->cascade() + * Example: drop()->index('idx_email')->ifExists() + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::SCHEMA)] +function drop() : DropFactory +{ + return new DropFactory(); +} + +/** + * Create a factory for building ALTER statements. + * + * Provides a unified entry point for all ALTER operations: + * - alter()->table() - ALTER TABLE + * - alter()->index() - ALTER INDEX + * - alter()->view() - ALTER VIEW + * - alter()->materializedView() - ALTER MATERIALIZED VIEW + * - alter()->sequence() - ALTER SEQUENCE + * - alter()->schema() - ALTER SCHEMA + * - alter()->role() - ALTER ROLE + * - alter()->function() - ALTER FUNCTION + * - alter()->procedure() - ALTER PROCEDURE + * - alter()->trigger() - ALTER TRIGGER + * - alter()->extension() - ALTER EXTENSION + * - alter()->enumType() - ALTER TYPE (enum) + * - alter()->domain() - ALTER DOMAIN + * + * Rename operations are also under alter(): + * - alter()->index('old')->renameTo('new') + * - alter()->view('old')->renameTo('new') + * - alter()->schema('old')->renameTo('new') + * - alter()->role('old')->renameTo('new') + * - alter()->trigger('old')->on('table')->renameTo('new') + * + * Example: alter()->table('users')->addColumn(col_def('email', column_type_text())) + * Example: alter()->sequence('user_id_seq')->restart(1000) + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::SCHEMA)] +function alter() : AlterFactory +{ + return new AlterFactory(); +} + +/** + * Create a TRUNCATE TABLE builder. + * + * @param string ...$tables Table names to truncate + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function truncate_table(string ...$tables) : TruncateFinalStep +{ + return TruncateBuilder::create(...$tables); +} + +/** + * Create a REFRESH MATERIALIZED VIEW builder. + * + * Example: refresh_materialized_view('user_stats') + * Produces: REFRESH MATERIALIZED VIEW user_stats + * + * Example: refresh_materialized_view('user_stats')->concurrently()->withData() + * Produces: REFRESH MATERIALIZED VIEW CONCURRENTLY user_stats WITH DATA + * + * @param string $name View name (may include schema as "schema.view") + * @param null|string $schema Schema name (optional, overrides parsed schema) + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::SCHEMA)] +function refresh_materialized_view(string $name, ?string $schema = null) : RefreshMatViewOptionsStep +{ + return RefreshMaterializedViewBuilder::create($name, $schema); +} + +/** + * Get a CASCADE referential action. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function ref_action_cascade() : ReferentialAction +{ + return ReferentialAction::CASCADE; +} + +/** + * Get a RESTRICT referential action. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function ref_action_restrict() : ReferentialAction +{ + return ReferentialAction::RESTRICT; +} + +/** + * Get a SET NULL referential action. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function ref_action_set_null() : ReferentialAction +{ + return ReferentialAction::SET_NULL; +} + +/** + * Get a SET DEFAULT referential action. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function ref_action_set_default() : ReferentialAction +{ + return ReferentialAction::SET_DEFAULT; +} + +/** + * Get a NO ACTION referential action. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function ref_action_no_action() : ReferentialAction +{ + return ReferentialAction::NO_ACTION; +} + +/** + * Start building a REINDEX INDEX statement. + * + * Use chainable methods: ->concurrently(), ->verbose(), ->tablespace() + * + * Example: reindex_index('idx_users_email')->concurrently() + * + * @param string $name The index name (may include schema: schema.index) + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::SCHEMA)] +function reindex_index(string $name) : ReindexFinalStep +{ + return ReindexBuilder::index($name); +} + +/** + * Start building a REINDEX TABLE statement. + * + * Use chainable methods: ->concurrently(), ->verbose(), ->tablespace() + * + * Example: reindex_table('users')->concurrently() + * + * @param string $name The table name (may include schema: schema.table) + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::SCHEMA)] +function reindex_table(string $name) : ReindexFinalStep +{ + return ReindexBuilder::table($name); +} + +/** + * Start building a REINDEX SCHEMA statement. + * + * Use chainable methods: ->concurrently(), ->verbose(), ->tablespace() + * + * Example: reindex_schema('public')->concurrently() + * + * @param string $name The schema name + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::SCHEMA)] +function reindex_schema(string $name) : ReindexFinalStep +{ + return ReindexBuilder::schema($name); +} + +/** + * Start building a REINDEX DATABASE statement. + * + * Use chainable methods: ->concurrently(), ->verbose(), ->tablespace() + * + * Example: reindex_database('mydb')->concurrently() + * + * @param string $name The database name + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::SCHEMA)] +function reindex_database(string $name) : ReindexFinalStep +{ + return ReindexBuilder::database($name); +} + +/** + * Create an index column specification. + * + * Use chainable methods: ->asc(), ->desc(), ->nullsFirst(), ->nullsLast(), ->opclass(), ->collate() + * + * Example: index_col('email')->desc()->nullsLast() + * + * @param string $name The column name + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::SCHEMA)] +function index_col(string $name) : IndexColumn +{ + return IndexColumn::column($name); +} + +/** + * Create an index column specification from an expression. + * + * Use chainable methods: ->asc(), ->desc(), ->nullsFirst(), ->nullsLast(), ->opclass(), ->collate() + * + * Example: index_expr(fn_call('lower', col('email')))->desc() + * + * @param Expression $expression The expression to index + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::SCHEMA)] +function index_expr(Expression $expression) : IndexColumn +{ + return IndexColumn::expression($expression); +} + +/** + * Get the BTREE index method. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function index_method_btree() : IndexMethod +{ + return IndexMethod::BTREE; +} + +/** + * Get the HASH index method. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function index_method_hash() : IndexMethod +{ + return IndexMethod::HASH; +} + +/** + * Get the GIST index method. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function index_method_gist() : IndexMethod +{ + return IndexMethod::GIST; +} + +/** + * Get the SPGIST index method. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function index_method_spgist() : IndexMethod +{ + return IndexMethod::SPGIST; +} + +/** + * Get the GIN index method. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function index_method_gin() : IndexMethod +{ + return IndexMethod::GIN; +} + +/** + * Get the BRIN index method. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function index_method_brin() : IndexMethod +{ + return IndexMethod::BRIN; +} + +/** + * Create a VACUUM builder. + * + * Example: vacuum()->table('users') + * Produces: VACUUM users + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function vacuum() : VacuumFinalStep +{ + return VacuumBuilder::create(); +} + +/** + * Create an ANALYZE builder. + * + * Example: analyze()->table('users') + * Produces: ANALYZE users + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function analyze() : AnalyzeFinalStep +{ + return AnalyzeBuilder::create(); +} + +/** + * Create an EXPLAIN builder for a query. + * + * Example: explain(select()->from('users')) + * Produces: EXPLAIN SELECT * FROM users + * + * @param DeleteBuilder|InsertBuilder|SelectFinalStep|UpdateBuilder $query Query to explain + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function explain(SelectFinalStep|InsertBuilder|UpdateBuilder|DeleteBuilder $query) : ExplainFinalStep +{ + return ExplainBuilder::create($query); +} + +/** + * Create a LOCK TABLE builder. + * + * Example: lock_table('users', 'orders')->accessExclusive() + * Produces: LOCK TABLE users, orders IN ACCESS EXCLUSIVE MODE + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function lock_table(string ...$tables) : LockFinalStep +{ + return LockBuilder::create(...$tables); +} + +/** + * Create a COMMENT ON builder. + * + * Example: comment(CommentTarget::TABLE, 'users')->is('User accounts table') + * Produces: COMMENT ON TABLE users IS 'User accounts table' + * + * @param CommentTarget $target Target type (TABLE, COLUMN, INDEX, etc.) + * @param string $name Target name (use 'table.column' for COLUMN targets) + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function comment(CommentTarget $target, string $name) : CommentFinalStep +{ + return CommentBuilder::create($target, $name); +} + +/** + * Create a CLUSTER builder. + * + * Example: cluster()->table('users')->using('idx_users_pkey') + * Produces: CLUSTER users USING idx_users_pkey + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function cluster() : ClusterFinalStep +{ + return ClusterBuilder::create(); +} + +/** + * Create a DISCARD builder. + * + * Example: discard(DiscardType::ALL) + * Produces: DISCARD ALL + * + * @param DiscardType $type Type of resources to discard (ALL, PLANS, SEQUENCES, TEMP) + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function discard(DiscardType $type) : DiscardFinalStep +{ + return DiscardBuilder::create($type); +} + +/** + * Create a GRANT privileges builder. + * + * Example: grant(TablePrivilege::SELECT)->onTable('users')->to('app_user') + * Produces: GRANT SELECT ON users TO app_user + * + * Example: grant(TablePrivilege::ALL)->onAllTablesInSchema('public')->to('admin') + * Produces: GRANT ALL ON ALL TABLES IN SCHEMA public TO admin + * + * @param string|TablePrivilege ...$privileges The privileges to grant + * + * @return GrantOnStep Builder for grant options + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function grant(TablePrivilege|string ...$privileges) : GrantOnStep +{ + return GrantBuilder::create(...$privileges); +} + +/** + * Create a GRANT role builder. + * + * Example: grant_role('admin')->to('user1') + * Produces: GRANT admin TO user1 + * + * Example: grant_role('admin', 'developer')->to('user1')->withAdminOption() + * Produces: GRANT admin, developer TO user1 WITH ADMIN OPTION + * + * @param string ...$roles The roles to grant + * + * @return GrantRoleToStep Builder for grant role options + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function grant_role(string ...$roles) : GrantRoleToStep +{ + return GrantRoleBuilder::create(...$roles); +} + +/** + * Create a REVOKE privileges builder. + * + * Example: revoke(TablePrivilege::SELECT)->onTable('users')->from('app_user') + * Produces: REVOKE SELECT ON users FROM app_user + * + * Example: revoke(TablePrivilege::ALL)->onTable('users')->from('app_user')->cascade() + * Produces: REVOKE ALL ON users FROM app_user CASCADE + * + * @param string|TablePrivilege ...$privileges The privileges to revoke + * + * @return RevokeOnStep Builder for revoke options + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function revoke(TablePrivilege|string ...$privileges) : RevokeOnStep +{ + return RevokeBuilder::create(...$privileges); +} + +/** + * Create a REVOKE role builder. + * + * Example: revoke_role('admin')->from('user1') + * Produces: REVOKE admin FROM user1 + * + * Example: revoke_role('admin')->from('user1')->cascade() + * Produces: REVOKE admin FROM user1 CASCADE + * + * @param string ...$roles The roles to revoke + * + * @return RevokeRoleFromStep Builder for revoke role options + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function revoke_role(string ...$roles) : RevokeRoleFromStep +{ + return RevokeRoleBuilder::create(...$roles); +} + +/** + * Create a SET ROLE builder. + * + * Example: set_role('admin') + * Produces: SET ROLE admin + * + * @param string $role The role to set + * + * @return SetRoleFinalStep Builder for set role + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function set_role(string $role) : SetRoleFinalStep +{ + return SetRoleBuilder::create($role); +} + +/** + * Create a RESET ROLE builder. + * + * Example: reset_role() + * Produces: RESET ROLE + * + * @return ResetRoleFinalStep Builder for reset role + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function reset_role() : ResetRoleFinalStep +{ + return ResetRoleBuilder::create(); +} + +/** + * Create a REASSIGN OWNED builder. + * + * Example: reassign_owned('old_role')->to('new_role') + * Produces: REASSIGN OWNED BY old_role TO new_role + * + * @param string ...$roles The roles whose owned objects should be reassigned + * + * @return ReassignOwnedToStep Builder for reassign owned options + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function reassign_owned(string ...$roles) : ReassignOwnedToStep +{ + return ReassignOwnedBuilder::create(...$roles); +} + +/** + * Create a DROP OWNED builder. + * + * Example: drop_owned('role1') + * Produces: DROP OWNED BY role1 + * + * Example: drop_owned('role1', 'role2')->cascade() + * Produces: DROP OWNED BY role1, role2 CASCADE + * + * @param string ...$roles The roles whose owned objects should be dropped + * + * @return DropOwnedFinalStep Builder for drop owned options + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function drop_owned(string ...$roles) : DropOwnedFinalStep +{ + return DropOwnedBuilder::create(...$roles); +} + +/** + * Creates a new function argument for use in function/procedure definitions. + * + * Example: func_arg(column_type_integer()) + * Example: func_arg(column_type_text())->named('username') + * Example: func_arg(column_type_integer())->named('count')->default('0') + * Example: func_arg(column_type_text())->out() + * + * @param ColumnType $type The PostgreSQL data type for the argument + * + * @return FunctionArgument Builder for function argument options + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function func_arg(ColumnType $type) : FunctionArgument +{ + return FunctionArgument::of($type); +} + +/** + * Creates a CALL statement builder for invoking a procedure. + * + * Example: call('update_stats')->with(123) + * Produces: CALL update_stats(123) + * + * Example: call('process_data')->with('test', 42, true) + * Produces: CALL process_data('test', 42, true) + * + * @param string $procedure The name of the procedure to call + * + * @return CallFinalStep Builder for call statement options + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function call(string $procedure) : CallFinalStep +{ + return CallBuilder::create($procedure); +} + +/** + * Creates a DO statement builder for executing an anonymous code block. + * + * Example: do_block('BEGIN RAISE NOTICE $$Hello World$$; END;') + * Produces: DO $$ BEGIN RAISE NOTICE $$Hello World$$; END; $$ LANGUAGE plpgsql + * + * Example: do_block('SELECT 1')->language('sql') + * Produces: DO $$ SELECT 1 $$ LANGUAGE sql + * + * @param string $code The anonymous code block to execute + * + * @return DoFinalStep Builder for DO statement options + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function do_block(string $code) : DoFinalStep +{ + return DoBuilder::create($code); +} + +/** + * Creates a type attribute for composite types. + * + * Example: type_attr('name', column_type_text()) + * Produces: name text + * + * Example: type_attr('description', column_type_text())->collate('en_US') + * Produces: description text COLLATE "en_US" + * + * @param string $name The attribute name + * @param ColumnType $type The attribute type + * + * @return TypeAttribute Type attribute value object + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function type_attr(string $name, ColumnType $type) : TypeAttribute +{ + return TypeAttribute::of($name, $type); +} + +/** + * Create an integer data type (PostgreSQL int4). + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function column_type_integer() : ColumnType +{ + return ColumnType::integer(); +} + +/** + * Create a smallint data type (PostgreSQL int2). + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function column_type_smallint() : ColumnType +{ + return ColumnType::smallint(); +} + +/** + * Create a bigint data type (PostgreSQL int8). + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function column_type_bigint() : ColumnType +{ + return ColumnType::bigint(); +} + +/** + * Create a boolean data type. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function column_type_boolean() : ColumnType +{ + return ColumnType::boolean(); +} + +/** + * Create a text data type. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function column_type_text() : ColumnType +{ + return ColumnType::text(); +} + +/** + * Create a varchar data type with length constraint. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function column_type_varchar(int $length) : ColumnType +{ + return ColumnType::varchar($length); +} + +/** + * Create a char data type with length constraint. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function column_type_char(int $length) : ColumnType +{ + return ColumnType::char($length); +} + +/** + * Create a numeric data type with optional precision and scale. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function column_type_numeric(?int $precision = null, ?int $scale = null) : ColumnType +{ + return ColumnType::numeric($precision, $scale); +} + +/** + * Create a decimal data type with optional precision and scale. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function column_type_decimal(?int $precision = null, ?int $scale = null) : ColumnType +{ + return ColumnType::decimal($precision, $scale); +} + +/** + * Create a real data type (PostgreSQL float4). + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function column_type_real() : ColumnType +{ + return ColumnType::real(); +} + +/** + * Create a double precision data type (PostgreSQL float8). + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function column_type_double_precision() : ColumnType +{ + return ColumnType::doublePrecision(); +} + +/** + * Create a date data type. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function column_type_date() : ColumnType +{ + return ColumnType::date(); +} + +/** + * Create a time data type with optional precision. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function column_type_time(?int $precision = null) : ColumnType +{ + return ColumnType::time($precision); +} + +/** + * Create a timestamp data type with optional precision. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function column_type_timestamp(?int $precision = null) : ColumnType +{ + return ColumnType::timestamp($precision); +} + +/** + * Create a timestamp with time zone data type with optional precision. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function column_type_timestamptz(?int $precision = null) : ColumnType +{ + return ColumnType::timestamptz($precision); +} + +/** + * Create an interval data type. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function column_type_interval() : ColumnType +{ + return ColumnType::interval(); +} + +/** + * Create a UUID data type. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function column_type_uuid() : ColumnType +{ + return ColumnType::uuid(); +} + +/** + * Create a JSON data type. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function column_type_json() : ColumnType +{ + return ColumnType::json(); +} + +/** + * Create a JSONB data type. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function column_type_jsonb() : ColumnType +{ + return ColumnType::jsonb(); +} + +/** + * Create a bytea data type. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function column_type_bytea() : ColumnType +{ + return ColumnType::bytea(); +} + +/** + * Create an inet data type. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function column_type_inet() : ColumnType +{ + return ColumnType::inet(); +} + +/** + * Create a cidr data type. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function column_type_cidr() : ColumnType +{ + return ColumnType::cidr(); +} + +/** + * Create a macaddr data type. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function column_type_macaddr() : ColumnType +{ + return ColumnType::macaddr(); +} + +/** + * Create a serial data type. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function column_type_serial() : ColumnType +{ + return ColumnType::serial(); +} + +/** + * Create a smallserial data type. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function column_type_smallserial() : ColumnType +{ + return ColumnType::smallserial(); +} + +/** + * Create a bigserial data type. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function column_type_bigserial() : ColumnType +{ + return ColumnType::bigserial(); +} + +/** + * Create an array data type from an element type. + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function column_type_array(ColumnType $elementType) : ColumnType +{ + return ColumnType::array($elementType); +} + +/** + * Create a custom data type. + * + * @param string $typeName Type name + * @param null|string $schema Optional schema name + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function column_type_custom(string $typeName, ?string $schema = null) : ColumnType +{ + return ColumnType::custom($typeName, $schema); +} + +/** + * Parse a PostgreSQL type string into a ColumnType. + * + * Handles all PostgreSQL type syntax including precision, arrays, and schema-qualified types. + * + * @param string $typeName PostgreSQL type string (e.g., 'integer', 'character varying(255)', 'text[]') + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function column_type_from_string(string $typeName) : ColumnType +{ + return (new ColumnTypeParser())->parse($typeName); +} + +// ValueType DSL functions - Scalar types + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_text() : ValueType +{ + return ValueType::TEXT; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_varchar() : ValueType +{ + return ValueType::VARCHAR; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_char() : ValueType +{ + return ValueType::CHAR; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_bpchar() : ValueType +{ + return ValueType::BPCHAR; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_int2() : ValueType +{ + return ValueType::INT2; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_smallint() : ValueType +{ + return ValueType::INT2; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_int4() : ValueType +{ + return ValueType::INT4; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_integer() : ValueType +{ + return ValueType::INT4; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_int8() : ValueType +{ + return ValueType::INT8; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_bigint() : ValueType +{ + return ValueType::INT8; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_float4() : ValueType +{ + return ValueType::FLOAT4; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_real() : ValueType +{ + return ValueType::FLOAT4; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_float8() : ValueType +{ + return ValueType::FLOAT8; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_double() : ValueType +{ + return ValueType::FLOAT8; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_numeric() : ValueType +{ + return ValueType::NUMERIC; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_money() : ValueType +{ + return ValueType::MONEY; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_bool() : ValueType +{ + return ValueType::BOOL; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_boolean() : ValueType +{ + return ValueType::BOOL; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_bytea() : ValueType +{ + return ValueType::BYTEA; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_bit() : ValueType +{ + return ValueType::BIT; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_varbit() : ValueType +{ + return ValueType::VARBIT; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_date() : ValueType +{ + return ValueType::DATE; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_time() : ValueType +{ + return ValueType::TIME; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_timetz() : ValueType +{ + return ValueType::TIMETZ; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_timestamp() : ValueType +{ + return ValueType::TIMESTAMP; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_timestamptz() : ValueType +{ + return ValueType::TIMESTAMPTZ; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_interval() : ValueType +{ + return ValueType::INTERVAL; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_json() : ValueType +{ + return ValueType::JSON; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_jsonb() : ValueType +{ + return ValueType::JSONB; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_uuid() : ValueType +{ + return ValueType::UUID; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_inet() : ValueType +{ + return ValueType::INET; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_cidr() : ValueType +{ + return ValueType::CIDR; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_macaddr() : ValueType +{ + return ValueType::MACADDR; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_macaddr8() : ValueType +{ + return ValueType::MACADDR8; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_xml() : ValueType +{ + return ValueType::XML; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_oid() : ValueType +{ + return ValueType::OID; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_text_array() : ValueType +{ + return ValueType::TEXT_ARRAY; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_varchar_array() : ValueType +{ + return ValueType::VARCHAR_ARRAY; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_int2_array() : ValueType +{ + return ValueType::INT2_ARRAY; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_int4_array() : ValueType +{ + return ValueType::INT4_ARRAY; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_int8_array() : ValueType +{ + return ValueType::INT8_ARRAY; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_float4_array() : ValueType +{ + return ValueType::FLOAT4_ARRAY; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_float8_array() : ValueType +{ + return ValueType::FLOAT8_ARRAY; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_bool_array() : ValueType +{ + return ValueType::BOOL_ARRAY; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_uuid_array() : ValueType +{ + return ValueType::UUID_ARRAY; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_json_array() : ValueType +{ + return ValueType::JSON_ARRAY; +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function value_type_jsonb_array() : ValueType +{ + return ValueType::JSONB_ARRAY; +} + +/** + * @param list $tables + * @param list $sequences + * @param list $views + * @param list $materializedViews + * @param list $functions + * @param list $procedures + * @param list $domains + * @param list $extensions + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function schema( + string $name, + array $tables = [], + array $sequences = [], + array $views = [], + array $materializedViews = [], + array $functions = [], + array $procedures = [], + array $domains = [], + array $extensions = [], +) : DatabaseSchema { + return new DatabaseSchema($name, $tables, $sequences, $views, $materializedViews, $functions, $procedures, $domains, $extensions); +} + +/** + * @param non-empty-list $columns + * @param list $indexes + * @param list $foreignKeys + * @param list $uniqueConstraints + * @param list $checkConstraints + * @param list $excludeConstraints + * @param list $triggers + * @param list $partitionColumns + * @param list $inherits + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function schema_table( + string $name, + array $columns, + ?SchemaPrimaryKey $primaryKey = null, + array $indexes = [], + array $foreignKeys = [], + array $uniqueConstraints = [], + array $checkConstraints = [], + array $excludeConstraints = [], + array $triggers = [], + string $schema = 'public', + bool $unlogged = false, + ?PartitionStrategy $partitionStrategy = null, + array $partitionColumns = [], + array $inherits = [], + ?string $tablespace = null, +) : SchemaTable { + return new SchemaTable($schema, $name, $columns, $primaryKey, $indexes, $foreignKeys, $uniqueConstraints, $checkConstraints, $excludeConstraints, $triggers, $unlogged, $partitionStrategy, $partitionColumns, $inherits, $tablespace); +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function schema_column( + string $name, + ColumnType $type, + bool $nullable = true, + ?string $default = null, + bool $isIdentity = false, + ?IdentityGeneration $identityGeneration = null, + bool $isGenerated = false, + ?string $generationExpression = null, + ?int $ordinalPosition = null, +) : SchemaColumn { + return new SchemaColumn($name, $type, $nullable, $default, $isIdentity, $identityGeneration, $isGenerated, $generationExpression, $ordinalPosition); +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function schema_column_integer(string $name, bool $nullable = true, ?string $default = null) : SchemaColumn +{ + return new SchemaColumn($name, ColumnType::integer(), $nullable, $default); +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function schema_column_smallint(string $name, bool $nullable = true, ?string $default = null) : SchemaColumn +{ + return new SchemaColumn($name, ColumnType::smallint(), $nullable, $default); +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function schema_column_bigint(string $name, bool $nullable = true, ?string $default = null) : SchemaColumn +{ + return new SchemaColumn($name, ColumnType::bigint(), $nullable, $default); +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function schema_column_serial(string $name) : SchemaColumn +{ + return new SchemaColumn($name, ColumnType::serial(), false); +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function schema_column_small_serial(string $name) : SchemaColumn +{ + return new SchemaColumn($name, ColumnType::smallserial(), false); +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function schema_column_big_serial(string $name) : SchemaColumn +{ + return new SchemaColumn($name, ColumnType::bigserial(), false); +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function schema_column_boolean(string $name, bool $nullable = true, ?string $default = null) : SchemaColumn +{ + return new SchemaColumn($name, ColumnType::boolean(), $nullable, $default); +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function schema_column_text(string $name, bool $nullable = true, ?string $default = null) : SchemaColumn +{ + return new SchemaColumn($name, ColumnType::text(), $nullable, $default); +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function schema_column_varchar(string $name, int $length, bool $nullable = true, ?string $default = null) : SchemaColumn +{ + return new SchemaColumn($name, ColumnType::varchar($length), $nullable, $default); +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function schema_column_char(string $name, int $length, bool $nullable = true, ?string $default = null) : SchemaColumn +{ + return new SchemaColumn($name, ColumnType::char($length), $nullable, $default); +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function schema_column_numeric(string $name, ?int $precision = null, ?int $scale = null, bool $nullable = true, ?string $default = null) : SchemaColumn +{ + return new SchemaColumn($name, ColumnType::numeric($precision, $scale), $nullable, $default); +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function schema_column_real(string $name, bool $nullable = true, ?string $default = null) : SchemaColumn +{ + return new SchemaColumn($name, ColumnType::real(), $nullable, $default); +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function schema_column_double_precision(string $name, bool $nullable = true, ?string $default = null) : SchemaColumn +{ + return new SchemaColumn($name, ColumnType::doublePrecision(), $nullable, $default); +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function schema_column_date(string $name, bool $nullable = true, ?string $default = null) : SchemaColumn +{ + return new SchemaColumn($name, ColumnType::date(), $nullable, $default); +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function schema_column_time(string $name, ?int $precision = null, bool $nullable = true, ?string $default = null) : SchemaColumn +{ + return new SchemaColumn($name, ColumnType::time($precision), $nullable, $default); +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function schema_column_timestamp(string $name, ?int $precision = null, bool $nullable = true, ?string $default = null) : SchemaColumn +{ + return new SchemaColumn($name, ColumnType::timestamp($precision), $nullable, $default); +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function schema_column_timestamp_tz(string $name, ?int $precision = null, bool $nullable = true, ?string $default = null) : SchemaColumn +{ + return new SchemaColumn($name, ColumnType::timestamptz($precision), $nullable, $default); +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function schema_column_interval(string $name, bool $nullable = true, ?string $default = null) : SchemaColumn +{ + return new SchemaColumn($name, ColumnType::interval(), $nullable, $default); +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function schema_column_uuid(string $name, bool $nullable = true, ?string $default = null) : SchemaColumn +{ + return new SchemaColumn($name, ColumnType::uuid(), $nullable, $default); +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function schema_column_json(string $name, bool $nullable = true, ?string $default = null) : SchemaColumn +{ + return new SchemaColumn($name, ColumnType::json(), $nullable, $default); +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function schema_column_jsonb(string $name, bool $nullable = true, ?string $default = null) : SchemaColumn +{ + return new SchemaColumn($name, ColumnType::jsonb(), $nullable, $default); +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function schema_column_bytea(string $name, bool $nullable = true, ?string $default = null) : SchemaColumn +{ + return new SchemaColumn($name, ColumnType::bytea(), $nullable, $default); +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function schema_column_inet(string $name, bool $nullable = true, ?string $default = null) : SchemaColumn +{ + return new SchemaColumn($name, ColumnType::inet(), $nullable, $default); +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function schema_column_cidr(string $name, bool $nullable = true, ?string $default = null) : SchemaColumn +{ + return new SchemaColumn($name, ColumnType::cidr(), $nullable, $default); +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function schema_column_macaddr(string $name, bool $nullable = true, ?string $default = null) : SchemaColumn +{ + return new SchemaColumn($name, ColumnType::macaddr(), $nullable, $default); +} + +/** + * @param non-empty-list $columns + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function schema_primary_key(array $columns, ?string $name = null) : SchemaPrimaryKey +{ + return new SchemaPrimaryKey($columns, $name); +} + +/** + * @param non-empty-list $columns + * @param non-empty-list $referenceColumns + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function schema_foreign_key( + array $columns, + string $referenceTable, + array $referenceColumns, + ?string $name = null, + string $referenceSchema = 'public', + ReferentialAction $onUpdate = ReferentialAction::NO_ACTION, + ReferentialAction $onDelete = ReferentialAction::NO_ACTION, + bool $deferrable = false, + bool $initiallyDeferred = false, +) : SchemaForeignKey { + return new SchemaForeignKey($name, $columns, $referenceSchema, $referenceTable, $referenceColumns, $onUpdate, $onDelete, $deferrable, $initiallyDeferred); +} + +/** + * @param non-empty-list $columns + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function schema_unique(array $columns, ?string $name = null, bool $nullsNotDistinct = false) : SchemaUniqueConstraint +{ + return new SchemaUniqueConstraint($columns, $name, $nullsNotDistinct); +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function schema_check(string $expression, ?string $name = null, bool $noInherit = false) : SchemaCheckConstraint +{ + return new SchemaCheckConstraint($expression, $name, $noInherit); +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function schema_exclude(string $definition, ?string $name = null) : SchemaExcludeConstraint +{ + return new SchemaExcludeConstraint($definition, $name); +} + +/** + * @param non-empty-list $columns + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function schema_index( + string $name, + array $columns, + bool $unique = false, + SchemaIndexMethod $method = SchemaIndexMethod::BTREE, + bool $primary = false, + ?string $predicate = null, +) : SchemaIndex { + return new SchemaIndex($name, $columns, $unique, $method, $primary, $predicate); +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function schema_sequence( + string $name, + string $dataType = 'bigint', + int|string $startValue = 1, + int|string $minValue = 1, + int|string|null $maxValue = null, + int|string $incrementBy = 1, + bool $cycle = false, + int|string $cacheValue = 1, + ?string $ownedByTable = null, + ?string $ownedByColumn = null, +) : SchemaSequence { + return new SchemaSequence($name, $dataType, $startValue, $minValue, $maxValue, $incrementBy, $cycle, $cacheValue, $ownedByTable, $ownedByColumn); +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function schema_view(string $name, string $definition, bool $isUpdatable = false) : SchemaView +{ + return new SchemaView($name, $definition, $isUpdatable); +} + +/** + * @param list $indexes + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function schema_materialized_view(string $name, string $definition, array $indexes = []) : SchemaMaterializedView +{ + return new SchemaMaterializedView($name, $definition, $indexes); +} + +/** + * @param list $argumentTypes + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function schema_function( + string $name, + string $returnType, + array $argumentTypes = [], + string $language = 'sql', + ?string $definition = null, + bool $isStrict = false, + ?SchemaFunctionVolatility $volatility = null, +) : SchemaFunction { + return new SchemaFunction($name, $returnType, $argumentTypes, $language, $definition, $isStrict, $volatility); +} + +/** + * @param list $argumentTypes + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function schema_procedure( + string $name, + array $argumentTypes = [], + string $language = 'sql', + ?string $definition = null, +) : SchemaProcedure { + return new SchemaProcedure($name, $argumentTypes, $language, $definition); +} + +/** + * @param non-empty-list $events + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function schema_trigger( + string $name, + string $tableName, + TriggerTiming $timing, + array $events, + string $functionName, + bool $forEachRow = false, + ?string $whenCondition = null, +) : SchemaTrigger { + return new SchemaTrigger($name, $tableName, $timing, $events, $functionName, $forEachRow, $whenCondition); +} + +/** + * @param list $checkConstraints + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function schema_domain( + string $name, + ColumnType $baseType, + bool $nullable = true, + ?string $default = null, + array $checkConstraints = [], +) : SchemaDomain { + return new SchemaDomain($name, $baseType, $nullable, $default, $checkConstraints); +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function schema_extension(string $name, ?string $version = null) : SchemaExtension +{ + return new SchemaExtension($name, $version); +} + +/** + * @param ?list $schemaNames + * @param list $excludeTables + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function client_catalog_provider(Client\Client $client, ?array $schemaNames = null, array $excludeTables = []) : CatalogProvider +{ + return new PgCatalogProvider($client, $schemaNames, $excludeTables); +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function manual_catalog_provider(Catalog $catalog) : CatalogProvider +{ + return new ManualCatalogProvider($catalog); +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function chain_catalog_provider(CatalogProvider ...$providers) : ChainCatalogProvider +{ + return new ChainCatalogProvider(...$providers); +} + +/** + * @param null|ExecutionOrderStrategy<\Flow\PostgreSql\Schema\Table> $tableOrderStrategy + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function catalog_comparator(?RenameStrategy $renameStrategy = null, ?ViewDependencyResolver $viewDependencyResolver = null, ?ExecutionOrderStrategy $tableOrderStrategy = null) : CatalogComparator +{ + return CatalogComparator::create($renameStrategy, $viewDependencyResolver, $tableOrderStrategy); +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function ast_view_dependency_resolver() : AstViewDependencyResolver +{ + return new AstViewDependencyResolver(new Parser()); +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function noop_view_dependency_resolver() : NoopViewDependencyResolver +{ + return new NoopViewDependencyResolver(); +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function foreign_key_dependency_order() : ForeignKeyDependencyOrder +{ + return new ForeignKeyDependencyOrder(); +} + +/** + * @return NoExecutionOrder + */ +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function no_execution_order() : NoExecutionOrder +{ + return new NoExecutionOrder(); +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function view_dependency_order() : ViewDependencyOrder +{ + return new ViewDependencyOrder(new Parser()); +} + +#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)] +function materialized_view_dependency_order() : MaterializedViewDependencyOrder +{ + return new MaterializedViewDependencyOrder(new Parser()); +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Migrations/Configuration.php b/src/lib/postgresql/src/Flow/PostgreSql/Migrations/Configuration.php new file mode 100644 index 0000000000..32aa78500e --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Migrations/Configuration.php @@ -0,0 +1,25 @@ +getMessage()), 0, $previous); + } + + public static function missingMigrationFile(string $directory) : self + { + return new self(\sprintf('Migration directory "%s" must contain migration.php.', $directory)); + } + + public static function noChangesDetected() : self + { + return new self('No changes detected between source and target catalog.'); + } + + public static function versionNotFound(Version $version) : self + { + return new self(\sprintf('Migration version "%s" not found.', $version)); + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Migrations/ExecutedMigration.php b/src/lib/postgresql/src/Flow/PostgreSql/Migrations/ExecutedMigration.php new file mode 100644 index 0000000000..159d3b498a --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Migrations/ExecutedMigration.php @@ -0,0 +1,15 @@ +direction) { + Direction::UP => $this->executeUp($plan, $context), + Direction::DOWN => $this->executeDown($plan, $context), + }; + } catch (\Throwable $e) { + return new ExecutionResult( + $plan->version, + $plan->direction, + (int) ((\hrtime(true) - $start) / 1_000_000), + false, + $e, + ); + } + + return new ExecutionResult( + $plan->version, + $plan->direction, + (int) ((\hrtime(true) - $start) / 1_000_000), + false, + null, + ); + } + + private function executeDown(MigrationPlan $plan, MigrationContext $context) : void + { + if ($plan->rollback === null) { + throw MigrationException::irreversibleMigration($plan->version); + } + + if ($plan->rollback->transactional()) { + $context->client->transaction(static function () use ($plan, $context) : void { + $plan->rollback->rollback($context); + }); + + return; + } + + $plan->rollback->rollback($context); + } + + private function executeUp(MigrationPlan $plan, MigrationContext $context) : void + { + if ($plan->migration->transactional()) { + $context->client->transaction(static function () use ($plan, $context) : void { + $plan->migration->migrate($context); + }); + + return; + } + + $plan->migration->migrate($context); + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Migrations/Executor/ExecutionResult.php b/src/lib/postgresql/src/Flow/PostgreSql/Migrations/Executor/ExecutionResult.php new file mode 100644 index 0000000000..d8bf4fdf18 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Migrations/Executor/ExecutionResult.php @@ -0,0 +1,24 @@ +error === null && !$this->skipped; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Migrations/Executor/MigrationExecutor.php b/src/lib/postgresql/src/Flow/PostgreSql/Migrations/Executor/MigrationExecutor.php new file mode 100644 index 0000000000..06883e8ccb --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Migrations/Executor/MigrationExecutor.php @@ -0,0 +1,12 @@ +sourceCatalog->get(); + $target = $this->targetCatalog->get(); + + $diff = $this->comparator->compare($source, $target); + + if ($diff->isEmpty() && !$allowEmpty) { + throw MigrationException::noChangesDetected(); + } + + $upSql = \array_map( + static fn (Sql $query) => $query->toSql(), + $diff->generate(), + ); + + $downSql = null; + + if ($this->generateRollback) { + $downSql = \array_map( + static fn (Sql $query) => $query->toSql(), + $this->comparator->compare($target, $this->sourceCatalog->get())->generate(), + ); + } + + return $this->generator->generateSchemaMigration($name, $upSql, $downSql); + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Migrations/Generator/MigrationGenerator.php b/src/lib/postgresql/src/Flow/PostgreSql/Migrations/Generator/MigrationGenerator.php new file mode 100644 index 0000000000..a7846498db --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Migrations/Generator/MigrationGenerator.php @@ -0,0 +1,18 @@ + $upSql + * @param ?list $downSql + */ + public function generateSchemaMigration(?string $name, array $upSql, ?array $downSql = null) : Version; +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Migrations/Migration.php b/src/lib/postgresql/src/Flow/PostgreSql/Migrations/Migration.php new file mode 100644 index 0000000000..cb8a5ee4dc --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Migrations/Migration.php @@ -0,0 +1,12 @@ + + */ +final readonly class MigrationPlanList implements \Countable, \IteratorAggregate +{ + /** + * @var list + */ + private array $plans; + + public function __construct(MigrationPlan ...$plans) + { + $this->plans = \array_values($plans); + } + + public function count() : int + { + return \count($this->plans); + } + + /** + * @return \ArrayIterator + */ + public function getIterator() : \ArrayIterator + { + return new \ArrayIterator($this->plans); + } + + public function isEmpty() : bool + { + return $this->plans === []; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Migrations/MigrationState.php b/src/lib/postgresql/src/Flow/PostgreSql/Migrations/MigrationState.php new file mode 100644 index 0000000000..53f2064668 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Migrations/MigrationState.php @@ -0,0 +1,12 @@ + + */ +final readonly class MigrationStatusList implements \Countable, \IteratorAggregate +{ + /** + * @var list + */ + private array $statuses; + + public function __construct(MigrationStatus ...$statuses) + { + $this->statuses = \array_values($statuses); + } + + public function count() : int + { + return \count($this->statuses); + } + + public function executed() : self + { + return new self(...\array_filter( + $this->statuses, + static fn (MigrationStatus $s) : bool => $s->state === MigrationState::EXECUTED, + )); + } + + /** + * @return \ArrayIterator + */ + public function getIterator() : \ArrayIterator + { + return new \ArrayIterator($this->statuses); + } + + public function isEmpty() : bool + { + return $this->statuses === []; + } + + public function pending() : self + { + return new self(...\array_filter( + $this->statuses, + static fn (MigrationStatus $s) : bool => $s->state === MigrationState::PENDING, + )); + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Migrations/MigrationsFactory.php b/src/lib/postgresql/src/Flow/PostgreSql/Migrations/MigrationsFactory.php new file mode 100644 index 0000000000..ea2344af02 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Migrations/MigrationsFactory.php @@ -0,0 +1,61 @@ +configuration->client, excludeTables: [$this->configuration->tableName]), + $this->configuration->targetCatalogProvider, + catalog_comparator(), + $generator, + $this->configuration->generateRollback, + ); + } + + public function createExecutor() : MigrationExecutor + { + return new DefaultMigrationExecutor(); + } + + public function createMigrator() : Migrator + { + return new Migrator( + $this->repository, + $this->createStore(), + $this->createExecutor(), + $this->configuration->client, + $this->configuration, + ); + } + + public function createStore() : MigrationStore + { + return new PostgreSqlMigrationStore($this->configuration->client, $this->configuration); + } + + public function createVersionResolver() : VersionResolver + { + return new VersionResolver( + $this->repository, + $this->createStore(), + ); + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Migrations/Migrator.php b/src/lib/postgresql/src/Flow/PostgreSql/Migrations/Migrator.php new file mode 100644 index 0000000000..661d2754fc --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Migrations/Migrator.php @@ -0,0 +1,231 @@ +store->initialize(); + + $available = $this->repository->get($version); + $plan = new MigrationPlan($available->version, $available->migration, $available->rollback, $direction); + $context = new MigrationContext($this->client); + + if ($dryRun) { + $this->client->beginTransaction(); + } + + $result = $this->executor->execute($plan, $context); + + if ($dryRun) { + $this->client->rollBack(); + + return $result; + } + + if ($result->isSuccessful()) { + match ($direction) { + Direction::UP => $this->store->complete($result->version, $result->executionTimeMs), + Direction::DOWN => $this->store->remove($result->version), + }; + } + + return $result; + } + + /** + * @return list + */ + public function migrate(?Version $to = null, bool $dryRun = false, ?bool $allOrNothing = null) : array + { + $this->store->initialize(); + + $available = $this->repository->all(); + $executed = $this->store->executedMigrations(); + $latestExecuted = $executed->latest(); + + if ($available->isEmpty() && $to === null) { + return []; + } + + $target = $to ?? $available->last()?->version; + + if ($target === null) { + return []; + } + + if ($latestExecuted !== null && $latestExecuted->version->equals($target)) { + return []; + } + + $plans = []; + + if ($latestExecuted === null || $target->isAfter($latestExecuted->version)) { + $pending = $latestExecuted === null + ? $available->upTo($target) + : $available->after($latestExecuted->version)->upTo($target); + + foreach ($pending as $migration) { + $plans[] = new MigrationPlan($migration->version, $migration->migration, $migration->rollback, Direction::UP); + } + } elseif ($latestExecuted->version->isAfter($target)) { + $toRollback = []; + + foreach ($executed as $em) { + if ($em->version->isAfter($target)) { + $toRollback[] = $em; + } + } + + $toRollback = \array_reverse($toRollback); + + foreach ($toRollback as $em) { + $migration = $this->repository->get($em->version); + $plans[] = new MigrationPlan($migration->version, $migration->migration, $migration->rollback, Direction::DOWN); + } + } + + if ($plans === []) { + return []; + } + + if ($dryRun) { + return $this->executeWithDryRun($plans); + } + + if ($allOrNothing ?? $this->configuration->allOrNothing) { + return $this->executeAllOrNothing($plans); + } + + return $this->executePlans($plans); + } + + public function status() : MigrationStatusList + { + $this->store->initialize(); + + $available = $this->repository->all(); + $executed = $this->store->executedMigrations(); + $statuses = []; + + foreach ($available as $migration) { + if ($executed->has($migration->version)) { + $em = $executed->get($migration->version); + $statuses[] = new MigrationStatus($migration->version, $migration->name, MigrationState::EXECUTED, $em->executedAt); + } else { + $statuses[] = new MigrationStatus($migration->version, $migration->name, MigrationState::PENDING, null); + } + } + + foreach ($executed as $em) { + if (!$available->has($em->version)) { + $statuses[] = new MigrationStatus($em->version, (string) $em->version, MigrationState::UNAVAILABLE, $em->executedAt); + } + } + + return new MigrationStatusList(...$statuses); + } + + /** + * @param list $plans + * + * @return list + */ + private function executeAllOrNothing(array $plans) : array + { + /** @var list $results */ + $results = []; + + $this->client->transaction(function () use ($plans, &$results) : void { + $context = new MigrationContext($this->client); + + foreach ($plans as $plan) { + $result = $this->executor->execute($plan, $context); + $results[] = $result; + + if (!$result->isSuccessful()) { + throw $result->error ?? new \RuntimeException('Migration failed'); + } + + match ($plan->direction) { + Direction::UP => $this->store->complete($result->version, $result->executionTimeMs), + Direction::DOWN => $this->store->remove($result->version), + }; + } + }); + + return $results; + } + + /** + * @param list $plans + * + * @return list + */ + private function executePlans(array $plans) : array + { + $context = new MigrationContext($this->client); + $results = []; + + foreach ($plans as $plan) { + $result = $this->executor->execute($plan, $context); + $results[] = $result; + + if (!$result->isSuccessful()) { + break; + } + + match ($plan->direction) { + Direction::UP => $this->store->complete($result->version, $result->executionTimeMs), + Direction::DOWN => $this->store->remove($result->version), + }; + } + + return $results; + } + + /** + * @param list $plans + * + * @return list + */ + private function executeWithDryRun(array $plans) : array + { + $this->client->beginTransaction(); + + try { + $context = new MigrationContext($this->client); + $results = []; + + foreach ($plans as $plan) { + $result = $this->executor->execute($plan, $context); + $results[] = $result; + + if (!$result->isSuccessful()) { + break; + } + } + + return $results; + } finally { + $this->client->rollBack(); + } + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Migrations/Repository/AvailableMigration.php b/src/lib/postgresql/src/Flow/PostgreSql/Migrations/Repository/AvailableMigration.php new file mode 100644 index 0000000000..b7a99f29a5 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Migrations/Repository/AvailableMigration.php @@ -0,0 +1,18 @@ + + */ +final readonly class AvailableMigrations implements \Countable, \IteratorAggregate +{ + /** + * @var list + */ + private array $migrations; + + public function __construct(AvailableMigration ...$migrations) + { + $sorted = \array_values($migrations); + + \usort($sorted, static fn (AvailableMigration $a, AvailableMigration $b) : int => $a->version->isAfter($b->version) ? 1 : ($b->version->isAfter($a->version) ? -1 : 0)); + + $this->migrations = $sorted; + } + + public function after(Version $version) : self + { + return new self(...\array_filter($this->migrations, static fn (AvailableMigration $m) : bool => $m->version->isAfter($version))); + } + + public function count() : int + { + return \count($this->migrations); + } + + public function first() : ?AvailableMigration + { + return $this->migrations[0] ?? null; + } + + public function get(Version $version) : AvailableMigration + { + foreach ($this->migrations as $migration) { + if ($migration->version->equals($version)) { + return $migration; + } + } + + throw MigrationException::versionNotFound($version); + } + + /** + * @return \ArrayIterator + */ + public function getIterator() : \ArrayIterator + { + return new \ArrayIterator($this->migrations); + } + + public function has(Version $version) : bool + { + foreach ($this->migrations as $migration) { + if ($migration->version->equals($version)) { + return true; + } + } + + return false; + } + + public function isEmpty() : bool + { + return $this->migrations === []; + } + + public function last() : ?AvailableMigration + { + if ($this->migrations === []) { + return null; + } + + return $this->migrations[\count($this->migrations) - 1]; + } + + public function upTo(Version $version) : self + { + return new self(...\array_filter($this->migrations, static fn (AvailableMigration $m) : bool => !$m->version->isAfter($version))); + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Migrations/Repository/MigrationRepository.php b/src/lib/postgresql/src/Flow/PostgreSql/Migrations/Repository/MigrationRepository.php new file mode 100644 index 0000000000..87a6549c45 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Migrations/Repository/MigrationRepository.php @@ -0,0 +1,16 @@ + + */ +final readonly class ExecutedMigrations implements \Countable, \IteratorAggregate +{ + /** + * @var list + */ + private array $migrations; + + public function __construct(ExecutedMigration ...$migrations) + { + $sorted = \array_values($migrations); + + \usort($sorted, static fn (ExecutedMigration $a, ExecutedMigration $b) : int => $a->version->isAfter($b->version) ? 1 : ($b->version->isAfter($a->version) ? -1 : 0)); + + $this->migrations = $sorted; + } + + public function count() : int + { + return \count($this->migrations); + } + + public function get(Version $version) : ExecutedMigration + { + foreach ($this->migrations as $migration) { + if ($migration->version->equals($version)) { + return $migration; + } + } + + throw MigrationException::versionNotFound($version); + } + + /** + * @return \ArrayIterator + */ + public function getIterator() : \ArrayIterator + { + return new \ArrayIterator($this->migrations); + } + + public function has(Version $version) : bool + { + foreach ($this->migrations as $migration) { + if ($migration->version->equals($version)) { + return true; + } + } + + return false; + } + + public function isEmpty() : bool + { + return $this->migrations === []; + } + + public function latest() : ?ExecutedMigration + { + if ($this->migrations === []) { + return null; + } + + return $this->migrations[\count($this->migrations) - 1]; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Migrations/Store/MigrationStore.php b/src/lib/postgresql/src/Flow/PostgreSql/Migrations/Store/MigrationStore.php new file mode 100644 index 0000000000..2fe25c5607 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Migrations/Store/MigrationStore.php @@ -0,0 +1,22 @@ +client->execute( + insert()->into($this->qualifiedTableName()) + ->columns('version', 'execution_time_ms') + ->values(...parameters(2)), + [(string) $version, $executionTimeMs], + ); + } + + public function executedMigrations() : ExecutedMigrations + { + $rows = $this->client->fetchAll( + select(col('version'), col('executed_at'), col('execution_time_ms')) + ->from($this->qualifiedTableName()) + ->orderBy(asc('version')), + ); + + return new ExecutedMigrations( + ...\array_map( + static function (array $row) : ExecutedMigration { + /** @var string $version */ + $version = $row['version']; + /** @var string $executedAt */ + $executedAt = $row['executed_at']; + /** @var null|int $executionTimeMs */ + $executionTimeMs = $row['execution_time_ms']; + + return new ExecutedMigration( + Version::fromString($version), + new \DateTimeImmutable($executedAt), + $executionTimeMs, + ); + }, + $rows, + ), + ); + } + + public function initialize() : void + { + $this->client->execute( + create()->table($this->configuration->tableName, $this->configuration->tableSchema) + ->column(column('version', column_type_varchar(255))->primaryKey()) + ->column(column('executed_at', column_type_timestamptz())->notNull()->default(func('now'))) + ->column(column('execution_time_ms', column_type_integer())) + ->ifNotExists(), + ); + } + + public function isInitialized() : bool + { + return $this->client->fetch( + select(col('table_name')) + ->from('information_schema.tables') + ->where(and_( + eq(col('table_schema'), param(1)), + eq(col('table_name'), param(2)), + )), + [$this->configuration->tableSchema, $this->configuration->tableName], + ) !== null; + } + + public function remove(Version $version) : void + { + $this->client->execute( + delete()->from($this->qualifiedTableName()) + ->where(eq(col('version'), param(1))), + [(string) $version], + ); + } + + public function reset() : void + { + $this->client->execute( + delete()->from($this->qualifiedTableName()), + ); + } + + private function qualifiedTableName() : string + { + return $this->configuration->tableSchema . '.' . $this->configuration->tableName; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Migrations/Version.php b/src/lib/postgresql/src/Flow/PostgreSql/Migrations/Version.php new file mode 100644 index 0000000000..620105698b --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Migrations/Version.php @@ -0,0 +1,39 @@ + 255) { + throw MigrationException::invalidVersionFormat($version); + } + + return new self($version); + } + + public function __toString() : string + { + return $this->version; + } + + public function equals(self $other) : bool + { + return $this->version === $other->version; + } + + public function isAfter(self $other) : bool + { + return \strcmp($this->version, $other->version) > 0; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Migrations/VersionAlias.php b/src/lib/postgresql/src/Flow/PostgreSql/Migrations/VersionAlias.php new file mode 100644 index 0000000000..17ac6a6e78 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Migrations/VersionAlias.php @@ -0,0 +1,13 @@ +length / 2))))); + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Migrations/VersionGenerator/SequentialVersionGenerator.php b/src/lib/postgresql/src/Flow/PostgreSql/Migrations/VersionGenerator/SequentialVersionGenerator.php new file mode 100644 index 0000000000..035ac7edd8 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Migrations/VersionGenerator/SequentialVersionGenerator.php @@ -0,0 +1,25 @@ +store->executedMigrations()->latest(); + $next = $latest === null ? 1 : ((int) (string) $latest->version) + 1; + + return Version::fromString(\str_pad((string) $next, $this->padding, '0', \STR_PAD_LEFT)); + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Migrations/VersionGenerator/TimestampVersionGenerator.php b/src/lib/postgresql/src/Flow/PostgreSql/Migrations/VersionGenerator/TimestampVersionGenerator.php new file mode 100644 index 0000000000..15dc8b5dac --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Migrations/VersionGenerator/TimestampVersionGenerator.php @@ -0,0 +1,20 @@ +format)); + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Migrations/VersionResolver.php b/src/lib/postgresql/src/Flow/PostgreSql/Migrations/VersionResolver.php new file mode 100644 index 0000000000..32ee3b94cd --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Migrations/VersionResolver.php @@ -0,0 +1,97 @@ + $this->resolveFirst(), + VersionAlias::LATEST => $this->resolveLatest(), + VersionAlias::PREV => $this->resolvePrev(), + VersionAlias::NEXT => $this->resolveNext(), + }; + } + + private function resolveFirst() : Version + { + $first = $this->repository->all()->first(); + + if ($first === null) { + throw MigrationException::versionNotFound(Version::fromString('first')); + } + + return $first->version; + } + + private function resolveLatest() : Version + { + $last = $this->repository->all()->last(); + + if ($last === null) { + throw MigrationException::versionNotFound(Version::fromString('latest')); + } + + return $last->version; + } + + private function resolveNext() : Version + { + $latest = $this->store->executedMigrations()->latest(); + $available = $this->repository->all(); + + if ($latest === null) { + $first = $available->first(); + + if ($first === null) { + throw MigrationException::versionNotFound(Version::fromString('next')); + } + + return $first->version; + } + + $next = $available->after($latest->version)->first(); + + if ($next === null) { + throw MigrationException::versionNotFound(Version::fromString('next')); + } + + return $next->version; + } + + private function resolvePrev() : Version + { + $latest = $this->store->executedMigrations()->latest(); + + if ($latest === null) { + throw MigrationException::versionNotFound(Version::fromString('prev')); + } + + $items = \iterator_to_array($this->repository->all()->upTo($latest->version)); + + if (\count($items) < 2) { + return Version::fromString('0'); + } + + return $items[\count($items) - 2]->version; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Parser/ColumnTypeParser.php b/src/lib/postgresql/src/Flow/PostgreSql/Parser/ColumnTypeParser.php new file mode 100644 index 0000000000..5d4f7099f9 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Parser/ColumnTypeParser.php @@ -0,0 +1,66 @@ +parse("SELECT NULL::{$typeName}"); + + $stmts = $parsed->raw()->getStmts(); + + if ($stmts === null || \count($stmts) === 0) { + throw InvalidAstException::invalidFieldValue('stmts', 'ParseResult', 'expected at least one statement'); + } + + $selectStmt = $stmts[0]->getStmt()?->getSelectStmt(); + + if ($selectStmt === null) { + throw InvalidAstException::unexpectedNodeType('SelectStmt', 'unknown'); + } + + $targetList = $selectStmt->getTargetList(); + + if ($targetList === null || \count($targetList) === 0) { + throw InvalidAstException::invalidFieldValue('targetList', 'SelectStmt', 'expected at least one target'); + } + + $resTarget = $targetList[0]->getResTarget(); + + if ($resTarget === null) { + throw InvalidAstException::unexpectedNodeType('ResTarget', 'unknown'); + } + + $val = $resTarget->getVal(); + + if ($val === null) { + throw InvalidAstException::missingRequiredField('val', 'ResTarget'); + } + + $typeCast = $val->getTypeCast(); + + if ($typeCast === null) { + throw InvalidAstException::unexpectedNodeType('TypeCast', 'unknown'); + } + + $typeNameAst = $typeCast->getTypeName(); + + if ($typeNameAst === null) { + throw InvalidAstException::missingRequiredField('typeName', 'TypeCast'); + } + + return ColumnType::fromAst($typeNameAst); + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Parser/ConditionParser.php b/src/lib/postgresql/src/Flow/PostgreSql/Parser/ConditionParser.php new file mode 100644 index 0000000000..3b62dc665e --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Parser/ConditionParser.php @@ -0,0 +1,42 @@ +parser->parse("SELECT * FROM t WHERE {$condition}"); + + $stmts = $parsed->raw()->getStmts(); + + if ($stmts === null || \count($stmts) === 0) { + throw InvalidAstException::invalidFieldValue('stmts', 'ParseResult', 'expected at least one statement'); + } + + $selectStmt = $stmts[0]->getStmt()?->getSelectStmt(); + + if ($selectStmt === null) { + throw InvalidAstException::unexpectedNodeType('SelectStmt', 'unknown'); + } + + $whereClause = $selectStmt->getWhereClause(); + + if ($whereClause === null) { + throw InvalidAstException::missingRequiredField('whereClause', 'SelectStmt'); + } + + return $whereClause; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Parser/ExpressionParser.php b/src/lib/postgresql/src/Flow/PostgreSql/Parser/ExpressionParser.php new file mode 100644 index 0000000000..de20eebd37 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Parser/ExpressionParser.php @@ -0,0 +1,54 @@ +parser->parse("SELECT {$expression} AS x"); + + $stmts = $parsed->raw()->getStmts(); + + if ($stmts === null || \count($stmts) === 0) { + throw InvalidAstException::invalidFieldValue('stmts', 'ParseResult', 'expected at least one statement'); + } + + $selectStmt = $stmts[0]->getStmt()?->getSelectStmt(); + + if ($selectStmt === null) { + throw InvalidAstException::unexpectedNodeType('SelectStmt', 'unknown'); + } + + $targetList = $selectStmt->getTargetList(); + + if ($targetList === null || \count($targetList) === 0) { + throw InvalidAstException::invalidFieldValue('targetList', 'SelectStmt', 'expected at least one target'); + } + + $resTarget = $targetList[0]->getResTarget(); + + if ($resTarget === null) { + throw InvalidAstException::unexpectedNodeType('ResTarget', 'unknown'); + } + + $val = $resTarget->getVal(); + + if ($val === null) { + throw InvalidAstException::missingRequiredField('val', 'ResTarget'); + } + + return $val; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/All.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/All.php index d369b370dd..50e7c8c1c4 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/All.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/All.php @@ -6,7 +6,7 @@ use Flow\PostgreSql\Protobuf\AST\{A_Expr, A_Expr_Kind, Node, PBString, SubLink, SubLinkType}; use Flow\PostgreSql\QueryBuilder\Exception\InvalidAstException; -use Flow\PostgreSql\QueryBuilder\Expression\{Expression, ExpressionFactory}; +use Flow\PostgreSql\QueryBuilder\Expression\{AliasedExpression, Expression, ExpressionFactory}; final readonly class All implements Condition { @@ -137,6 +137,11 @@ public function and(Condition $other) : AndCondition return new AndCondition($this, $other); } + public function as(string $alias) : AliasedExpression + { + return new AliasedExpression($this, $alias); + } + public function not() : NotCondition { return new NotCondition($this); diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/AndCondition.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/AndCondition.php index 01460f1aea..e86390ab3f 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/AndCondition.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/AndCondition.php @@ -7,6 +7,7 @@ use Flow\PostgreSql\Protobuf\AST\{A_Expr_Kind, SubLinkType}; use Flow\PostgreSql\Protobuf\AST\{BoolExpr, BoolExprType, Node}; use Flow\PostgreSql\QueryBuilder\Exception\{InvalidAstException, UnsupportedNodeException}; +use Flow\PostgreSql\QueryBuilder\Expression\AliasedExpression; final readonly class AndCondition implements Condition { @@ -58,6 +59,11 @@ public function and(Condition $other) : self return new self(...[...$this->conditions, $other]); } + public function as(string $alias) : AliasedExpression + { + return new AliasedExpression($this, $alias); + } + public function not() : NotCondition { return new NotCondition($this); diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/Any.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/Any.php index 43c1404b4b..d601264df9 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/Any.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/Any.php @@ -6,7 +6,7 @@ use Flow\PostgreSql\Protobuf\AST\{A_Expr, A_Expr_Kind, Node, PBString, SubLink, SubLinkType}; use Flow\PostgreSql\QueryBuilder\Exception\InvalidAstException; -use Flow\PostgreSql\QueryBuilder\Expression\{Expression, ExpressionFactory}; +use Flow\PostgreSql\QueryBuilder\Expression\{AliasedExpression, Expression, ExpressionFactory}; final readonly class Any implements Condition { @@ -137,6 +137,11 @@ public function and(Condition $other) : AndCondition return new AndCondition($this, $other); } + public function as(string $alias) : AliasedExpression + { + return new AliasedExpression($this, $alias); + } + public function not() : NotCondition { return new NotCondition($this); diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/Between.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/Between.php index 63bd0814f8..8e548f7095 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/Between.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/Between.php @@ -6,7 +6,7 @@ use Flow\PostgreSql\Protobuf\AST\{A_Expr, A_Expr_Kind, Node, PBList, PBString}; use Flow\PostgreSql\QueryBuilder\Exception\InvalidAstException; -use Flow\PostgreSql\QueryBuilder\Expression\{Expression, ExpressionFactory}; +use Flow\PostgreSql\QueryBuilder\Expression\{AliasedExpression, Expression, ExpressionFactory}; final readonly class Between implements Condition { @@ -79,6 +79,11 @@ public function and(Condition $other) : AndCondition return new AndCondition($this, $other); } + public function as(string $alias) : AliasedExpression + { + return new AliasedExpression($this, $alias); + } + public function not() : NotCondition { return new NotCondition($this); diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/BooleanCondition.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/BooleanCondition.php new file mode 100644 index 0000000000..99399281da --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/BooleanCondition.php @@ -0,0 +1,67 @@ +hasColumnRef()) { + return new self(Column::fromAst($node)); + } + + if ($node->hasAConst()) { + $aConst = $node->getAConst(); + + if ($aConst !== null && $aConst->hasBoolval()) { + $boolval = $aConst->getBoolval(); + \assert($boolval instanceof Boolean); + + return new self(Literal::bool($boolval->getBoolval())); + } + } + + return new self(ExpressionFactory::fromAst($node)); + } + + public function and(Condition $other) : AndCondition + { + return new AndCondition($this, $other); + } + + public function as(string $alias) : AliasedExpression + { + return new AliasedExpression($this, $alias); + } + + public function not() : NotCondition + { + return new NotCondition($this); + } + + public function or(Condition $other) : OrCondition + { + return new OrCondition($this, $other); + } + + public function toAst() : Node + { + return $this->expression->toAst(); + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/Comparison.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/Comparison.php index 0bdff59413..062e79b7b9 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/Comparison.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/Comparison.php @@ -6,7 +6,7 @@ use Flow\PostgreSql\Protobuf\AST\{A_Expr, A_Expr_Kind, Node, PBString}; use Flow\PostgreSql\QueryBuilder\Exception\InvalidAstException; -use Flow\PostgreSql\QueryBuilder\Expression\{Expression, ExpressionFactory}; +use Flow\PostgreSql\QueryBuilder\Expression\{AliasedExpression, Expression, ExpressionFactory}; final readonly class Comparison implements Condition { @@ -77,6 +77,11 @@ public function and(Condition $other) : AndCondition return new AndCondition($this, $other); } + public function as(string $alias) : AliasedExpression + { + return new AliasedExpression($this, $alias); + } + public function not() : NotCondition { return new NotCondition($this); diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/Condition.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/Condition.php index 9e4e232ea7..18aaebd18b 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/Condition.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/Condition.php @@ -4,12 +4,15 @@ namespace Flow\PostgreSql\QueryBuilder\Condition; -use Flow\PostgreSql\QueryBuilder\Bridge\AstConvertible; +use Flow\PostgreSql\QueryBuilder\Expression\Expression; /** * Base interface for all SQL conditions (WHERE, HAVING, ON, etc.). + * + * Conditions are expressions that evaluate to boolean — they can be used + * anywhere an expression is expected (SELECT list, CASE WHEN, etc.). */ -interface Condition extends AstConvertible +interface Condition extends Expression { public function and(self $other) : AndCondition; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/ConditionBuilder.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/ConditionBuilder.php index 8792d1bf5f..208b9778fe 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/ConditionBuilder.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/ConditionBuilder.php @@ -36,6 +36,9 @@ public function getCondition() : ?Condition return $this->condition; } + /** + * @phpstan-assert-if-true Condition $this->condition + */ public function isEmpty() : bool { return $this->condition === null; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/ConditionFactory.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/ConditionFactory.php index 3daddf532c..db5711c450 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/ConditionFactory.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/ConditionFactory.php @@ -62,12 +62,8 @@ public static function fromAst(Node $node) : Condition }; } - if ($node->getTypeCast() !== null) { - return RawCondition::fromTypeCast($node); - } - - if ($node->getAConst() !== null) { - return RawCondition::fromAConst($node); + if ($node->getAConst() !== null || $node->getColumnRef() !== null) { + return BooleanCondition::fromAst($node); } throw UnsupportedNodeException::forNodeType('Unknown condition node type'); diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/Exists.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/Exists.php index 7c3bff8a38..cc81ddd4ff 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/Exists.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/Exists.php @@ -6,6 +6,7 @@ use Flow\PostgreSql\Protobuf\AST\{Node, SubLink, SubLinkType}; use Flow\PostgreSql\QueryBuilder\Exception\InvalidAstException; +use Flow\PostgreSql\QueryBuilder\Expression\AliasedExpression; final readonly class Exists implements Condition { @@ -40,6 +41,11 @@ public function and(Condition $other) : AndCondition return new AndCondition($this, $other); } + public function as(string $alias) : AliasedExpression + { + return new AliasedExpression($this, $alias); + } + public function not() : NotCondition { return new NotCondition($this); diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/In.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/In.php index ab434f6f8d..bac0000301 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/In.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/In.php @@ -6,7 +6,7 @@ use Flow\PostgreSql\Protobuf\AST\{A_Expr, A_Expr_Kind, Node, PBList, PBString}; use Flow\PostgreSql\QueryBuilder\Exception\InvalidAstException; -use Flow\PostgreSql\QueryBuilder\Expression\{Expression, ExpressionFactory}; +use Flow\PostgreSql\QueryBuilder\Expression\{AliasedExpression, Expression, ExpressionFactory}; final readonly class In implements Condition { @@ -73,6 +73,11 @@ public function and(Condition $other) : AndCondition return new AndCondition($this, $other); } + public function as(string $alias) : AliasedExpression + { + return new AliasedExpression($this, $alias); + } + public function not() : NotCondition { return new NotCondition($this); diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/IsDistinctFrom.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/IsDistinctFrom.php index ea7ba19e4b..1388a4bee7 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/IsDistinctFrom.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/IsDistinctFrom.php @@ -6,7 +6,7 @@ use Flow\PostgreSql\Protobuf\AST\{A_Expr, A_Expr_Kind, Node, PBString}; use Flow\PostgreSql\QueryBuilder\Exception\InvalidAstException; -use Flow\PostgreSql\QueryBuilder\Expression\{Expression, ExpressionFactory}; +use Flow\PostgreSql\QueryBuilder\Expression\{AliasedExpression, Expression, ExpressionFactory}; final readonly class IsDistinctFrom implements Condition { @@ -57,6 +57,11 @@ public function and(Condition $other) : AndCondition return new AndCondition($this, $other); } + public function as(string $alias) : AliasedExpression + { + return new AliasedExpression($this, $alias); + } + public function not() : NotCondition { return new NotCondition($this); diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/IsNull.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/IsNull.php index fe3f3a32c3..fbc2c4f447 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/IsNull.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/IsNull.php @@ -6,7 +6,7 @@ use Flow\PostgreSql\Protobuf\AST\{Node, NullTest, NullTestType}; use Flow\PostgreSql\QueryBuilder\Exception\InvalidAstException; -use Flow\PostgreSql\QueryBuilder\Expression\{Expression, ExpressionFactory}; +use Flow\PostgreSql\QueryBuilder\Expression\{AliasedExpression, Expression, ExpressionFactory}; final readonly class IsNull implements Condition { @@ -49,6 +49,11 @@ public function and(Condition $other) : AndCondition return new AndCondition($this, $other); } + public function as(string $alias) : AliasedExpression + { + return new AliasedExpression($this, $alias); + } + public function not() : NotCondition { return new NotCondition($this); diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/Like.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/Like.php index e95860ecf1..cfd51d04c5 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/Like.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/Like.php @@ -4,9 +4,9 @@ namespace Flow\PostgreSql\QueryBuilder\Condition; -use Flow\PostgreSql\Protobuf\AST\{A_Expr, A_Expr_Kind, Node, PBString}; +use Flow\PostgreSql\Protobuf\AST\{A_Expr, A_Expr_Kind, BoolExpr, BoolExprType, Node, PBString}; use Flow\PostgreSql\QueryBuilder\Exception\InvalidAstException; -use Flow\PostgreSql\QueryBuilder\Expression\{Expression, ExpressionFactory}; +use Flow\PostgreSql\QueryBuilder\Expression\{AliasedExpression, Expression, ExpressionFactory}; final readonly class Like implements Condition { @@ -15,6 +15,7 @@ public function __construct( public Expression $pattern, public bool $caseInsensitive = false, public ?Expression $escape = null, + public bool $negated = false, ) { } @@ -59,6 +60,11 @@ public function and(Condition $other) : AndCondition return new AndCondition($this, $other); } + public function as(string $alias) : AliasedExpression + { + return new AliasedExpression($this, $alias); + } + public function not() : NotCondition { return new NotCondition($this); @@ -83,6 +89,16 @@ public function toAst() : Node 'rexpr' => $this->pattern->toAst(), ]); - return new Node(['a_expr' => $aExpr]); + $likeNode = new Node(['a_expr' => $aExpr]); + + if ($this->negated) { + $boolExpr = new BoolExpr(); + $boolExpr->setBoolop(BoolExprType::NOT_EXPR); + $boolExpr->setArgs([$likeNode]); + + return new Node(['bool_expr' => $boolExpr]); + } + + return $likeNode; } } diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/NotCondition.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/NotCondition.php index 7a143f228d..d2c8dd8ab1 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/NotCondition.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/NotCondition.php @@ -7,11 +7,12 @@ use Flow\PostgreSql\Protobuf\AST\{A_Expr_Kind, SubLinkType}; use Flow\PostgreSql\Protobuf\AST\{BoolExpr, BoolExprType, Node}; use Flow\PostgreSql\QueryBuilder\Exception\{InvalidAstException, UnsupportedNodeException}; +use Flow\PostgreSql\QueryBuilder\Expression\{AliasedExpression, Expression, ExpressionFactory}; final readonly class NotCondition implements Condition { public function __construct( - private Condition $condition, + private Expression $expression, ) { } @@ -46,7 +47,7 @@ public static function fromAst(Node $node) : static $argNode = $args[0]; - return new self(self::conditionFromNode($argNode)); + return new self(self::expressionFromNode($argNode)); } public function and(Condition $other) : AndCondition @@ -54,6 +55,11 @@ public function and(Condition $other) : AndCondition return new AndCondition($this, $other); } + public function as(string $alias) : AliasedExpression + { + return new AliasedExpression($this, $alias); + } + public function not() : self { return new self($this); @@ -68,7 +74,7 @@ public function toAst() : Node { $boolExpr = new BoolExpr(); $boolExpr->setBoolop(BoolExprType::NOT_EXPR); - $boolExpr->setArgs([$this->condition->toAst()]); + $boolExpr->setArgs([$this->expression->toAst()]); $node = new Node(); $node->setBoolExpr($boolExpr); @@ -76,7 +82,7 @@ public function toAst() : Node return $node; } - private static function conditionFromNode(Node $node) : Condition + private static function expressionFromNode(Node $node) : Expression { if ($node->hasBoolExpr()) { $boolExpr = $node->getBoolExpr(); @@ -132,6 +138,6 @@ private static function conditionFromNode(Node $node) : Condition }; } - throw UnsupportedNodeException::forNodeType('unknown node type in condition'); + return ExpressionFactory::fromAst($node); } } diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/OperatorCondition.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/OperatorCondition.php index db10d35392..945101c945 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/OperatorCondition.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/OperatorCondition.php @@ -6,7 +6,7 @@ use Flow\PostgreSql\Protobuf\AST\{A_Expr, A_Expr_Kind, Node, PBString}; use Flow\PostgreSql\QueryBuilder\Exception\InvalidAstException; -use Flow\PostgreSql\QueryBuilder\Expression\{Expression, ExpressionFactory}; +use Flow\PostgreSql\QueryBuilder\Expression\{AliasedExpression, Expression, ExpressionFactory}; /** * Generic operator condition for any binary operator (e.g., @>, <@, &&, ~, @@). @@ -71,6 +71,11 @@ public function and(Condition $other) : AndCondition return new AndCondition($this, $other); } + public function as(string $alias) : AliasedExpression + { + return new AliasedExpression($this, $alias); + } + public function not() : NotCondition { return new NotCondition($this); diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/OrCondition.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/OrCondition.php index 3d5be81995..cbda859947 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/OrCondition.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/OrCondition.php @@ -7,6 +7,7 @@ use Flow\PostgreSql\Protobuf\AST\{A_Expr_Kind, SubLinkType}; use Flow\PostgreSql\Protobuf\AST\{BoolExpr, BoolExprType, Node}; use Flow\PostgreSql\QueryBuilder\Exception\{InvalidAstException, UnsupportedNodeException}; +use Flow\PostgreSql\QueryBuilder\Expression\AliasedExpression; final readonly class OrCondition implements Condition { @@ -54,6 +55,11 @@ public function and(Condition $other) : AndCondition return new AndCondition($this, $other); } + public function as(string $alias) : AliasedExpression + { + return new AliasedExpression($this, $alias); + } + public function not() : NotCondition { return new NotCondition($this); diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/RawCondition.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/RawCondition.php deleted file mode 100644 index 0e34b36b9e..0000000000 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/RawCondition.php +++ /dev/null @@ -1,156 +0,0 @@ -getAConst(); - - if ($aConst === null) { - throw InvalidAstException::unexpectedNodeType('A_Const', 'unknown'); - } - - if ($aConst->hasBoolval()) { - $boolval = $aConst->getBoolval(); - \assert($boolval instanceof Boolean); - - return new self($boolval->getBoolval() ? 'true' : 'false'); - } - - throw UnsupportedNodeException::cannotReconstruct(self::class . ' from A_Const'); - } - - public static function fromAst(Node $node) : static - { - throw UnsupportedNodeException::cannotReconstruct(self::class); - } - - public static function fromTypeCast(Node $node) : static - { - $typeCast = $node->getTypeCast(); - - if ($typeCast === null) { - throw InvalidAstException::unexpectedNodeType('TypeCast', 'unknown'); - } - - $typeName = $typeCast->getTypeName(); - - if ($typeName === null) { - throw InvalidAstException::missingRequiredField('type_name', 'TypeCast'); - } - - $names = $typeName->getNames(); - - if ($names !== null) { - foreach ($names as $nameNode) { - $stringNode = $nameNode->getString(); - - if ($stringNode !== null && $stringNode->getSval() === 'bool') { - $arg = $typeCast->getArg(); - - if ($arg !== null) { - $aConst = $arg->getAConst(); - - if ($aConst !== null) { - $sval = $aConst->getSval(); - - if ($sval !== null) { - return new self($sval->getSval()); - } - } - } - } - } - } - - throw UnsupportedNodeException::cannotReconstruct(self::class . ' from TypeCast'); - } - - public function and(Condition $other) : AndCondition - { - return new AndCondition($this, $other); - } - - public function not() : NotCondition - { - return new NotCondition($this); - } - - public function or(Condition $other) : OrCondition - { - return new OrCondition($this, $other); - } - - public function toAst() : Node - { - $parser = new Parser(); - $parsed = $parser->parse("SELECT 1 WHERE {$this->sql}"); - - $stmts = $parsed->raw()->getStmts(); - - if (\count($stmts) === 0) { - throw InvalidAstException::invalidFieldValue('sql', 'RawCondition', 'Cannot parse SQL condition'); - } - - $firstStmt = $stmts[0]; - - if (!$firstStmt->hasStmt()) { - throw InvalidAstException::invalidFieldValue('sql', 'RawCondition', 'Statement does not have stmt field'); - } - - $stmt = $firstStmt->getStmt(); - - if ($stmt === null) { - throw InvalidAstException::missingRequiredField('stmt', 'RawPgQuery_Stmt'); - } - - if (!$stmt->hasSelectStmt()) { - throw InvalidAstException::invalidFieldValue('sql', 'RawCondition', 'Expected SelectStmt'); - } - - $selectStmt = $stmt->getSelectStmt(); - - if ($selectStmt === null) { - throw InvalidAstException::missingRequiredField('select_stmt', 'Node'); - } - - if (!$selectStmt->hasWhereClause()) { - throw InvalidAstException::invalidFieldValue('sql', 'RawCondition', 'WHERE clause is missing'); - } - - $whereClause = $selectStmt->getWhereClause(); - - if ($whereClause === null) { - throw InvalidAstException::missingRequiredField('where_clause', 'SelectStmt'); - } - - return $whereClause; - } -} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/SimilarTo.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/SimilarTo.php index 2a9b3e0b3a..cc997055a2 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/SimilarTo.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/SimilarTo.php @@ -6,7 +6,7 @@ use Flow\PostgreSql\Protobuf\AST\{A_Expr, A_Expr_Kind, CoercionForm, FuncCall, Node, PBString}; use Flow\PostgreSql\QueryBuilder\Exception\InvalidAstException; -use Flow\PostgreSql\QueryBuilder\Expression\{Expression, ExpressionFactory}; +use Flow\PostgreSql\QueryBuilder\Expression\{AliasedExpression, Expression, ExpressionFactory}; final readonly class SimilarTo implements Condition { @@ -77,6 +77,11 @@ public function and(Condition $other) : AndCondition return new AndCondition($this, $other); } + public function as(string $alias) : AliasedExpression + { + return new AliasedExpression($this, $alias); + } + public function not() : NotCondition { return new NotCondition($this); diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Copy/CopyFromFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Copy/CopyFromFinalStep.php index ab9c2d94b9..aadd3f341c 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Copy/CopyFromFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Copy/CopyFromFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Copy; use Flow\PostgreSql\Protobuf\AST\CopyStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface CopyFromFinalStep extends SqlQuery +interface CopyFromFinalStep extends Sql { public function toAst() : CopyStmt; } diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Copy/CopyToFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Copy/CopyToFinalStep.php index 9e61e19459..e6f32f3738 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Copy/CopyToFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Copy/CopyToFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Copy; use Flow\PostgreSql\Protobuf\AST\CopyStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface CopyToFinalStep extends SqlQuery +interface CopyToFinalStep extends Sql { public function toAst() : CopyStmt; } diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Cursor/CloseCursorFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Cursor/CloseCursorFinalStep.php index 2e38dae520..566adbb279 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Cursor/CloseCursorFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Cursor/CloseCursorFinalStep.php @@ -4,8 +4,8 @@ namespace Flow\PostgreSql\QueryBuilder\Cursor; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface CloseCursorFinalStep extends SqlQuery +interface CloseCursorFinalStep extends Sql { } diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Cursor/DeclareCursorBuilder.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Cursor/DeclareCursorBuilder.php index 0e1eade1a2..05fd0c523a 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Cursor/DeclareCursorBuilder.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Cursor/DeclareCursorBuilder.php @@ -6,7 +6,7 @@ use Flow\PostgreSql\Parser; use Flow\PostgreSql\Protobuf\AST\{DeclareCursorStmt, Node}; -use Flow\PostgreSql\QueryBuilder\{AstToSql, SqlQuery}; +use Flow\PostgreSql\QueryBuilder\{AstToSql, Sql}; use Flow\PostgreSql\QueryBuilder\Select\SelectFinalStep; final class DeclareCursorBuilder implements DeclareCursorOptionsStep @@ -29,9 +29,9 @@ public static function create(string $cursorName, SelectFinalStep $query) : Decl return new self($cursorName, $node); } - public static function createFromSql(string $cursorName, string|SqlQuery $query) : DeclareCursorOptionsStep + public static function createFromSql(string $cursorName, string|Sql $query) : DeclareCursorOptionsStep { - $sql = $query instanceof SqlQuery ? $query->toSql() : $query; + $sql = $query instanceof Sql ? $query->toSql() : $query; $parser = new Parser(); $parsed = $parser->parse($sql); $rawStmts = $parsed->raw()->getStmts(); diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Cursor/DeclareCursorFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Cursor/DeclareCursorFinalStep.php index e1a9372bd6..0ffc9ae040 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Cursor/DeclareCursorFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Cursor/DeclareCursorFinalStep.php @@ -4,8 +4,8 @@ namespace Flow\PostgreSql\QueryBuilder\Cursor; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface DeclareCursorFinalStep extends SqlQuery +interface DeclareCursorFinalStep extends Sql { } diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Cursor/FetchCursorFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Cursor/FetchCursorFinalStep.php index 8b6d04dade..325fcc6b67 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Cursor/FetchCursorFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Cursor/FetchCursorFinalStep.php @@ -4,8 +4,8 @@ namespace Flow\PostgreSql\QueryBuilder\Cursor; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface FetchCursorFinalStep extends SqlQuery +interface FetchCursorFinalStep extends Sql { } diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Delete/DeleteBuilder.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Delete/DeleteBuilder.php index 26aaf52bc5..4da5f90cdb 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Delete/DeleteBuilder.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Delete/DeleteBuilder.php @@ -254,8 +254,20 @@ public function toAst() : DeleteStmt return $deleteStmt; } - public function using(TableReference ...$tables) : DeleteWhereStep + public function using(string|TableReference ...$tables) : DeleteWhereStep { + $tables = \array_map( + static function (string|TableReference $t) : TableReference { + if ($t instanceof TableReference) { + return $t; + } + $id = QualifiedIdentifier::parse($t); + + return new Table($id->name(), $id->schema()); + }, + $tables, + ); + return new self( with: $this->with, table: $this->table, diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Delete/DeleteFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Delete/DeleteFinalStep.php index 851177221e..bcc8bdad5d 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Delete/DeleteFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Delete/DeleteFinalStep.php @@ -5,13 +5,13 @@ namespace Flow\PostgreSql\QueryBuilder\Delete; use Flow\PostgreSql\Protobuf\AST\DeleteStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; /** * Terminal interface for DELETE query builder. * Represents a complete DELETE statement that can be converted to AST. */ -interface DeleteFinalStep extends SqlQuery +interface DeleteFinalStep extends Sql { /** * Convert this DELETE query to a protobuf AST DeleteStmt. diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Delete/DeleteUsingStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Delete/DeleteUsingStep.php index ddb1d20054..557e057050 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Delete/DeleteUsingStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Delete/DeleteUsingStep.php @@ -18,5 +18,5 @@ interface DeleteUsingStep extends DeleteWhereStep * * @param TableReference ...$tables Tables to join for conditional deletion */ - public function using(TableReference ...$tables) : DeleteWhereStep; + public function using(string|TableReference ...$tables) : DeleteWhereStep; } diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/RawExpression.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/RawExpression.php deleted file mode 100644 index bda3a90f8e..0000000000 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/RawExpression.php +++ /dev/null @@ -1,88 +0,0 @@ -sql === '') { - throw new \InvalidArgumentException('RawExpression SQL cannot be empty'); - } - } - - public static function fromAst(Node $node) : static - { - throw UnsupportedNodeException::cannotReconstruct('RawExpression - cannot convert AST back to raw SQL string'); - } - - public function as(string $alias) : AliasedExpression - { - return new AliasedExpression($this, $alias); - } - - public function sql() : string - { - return $this->sql; - } - - public function toAst() : Node - { - $parser = new Parser(); - $parsed = $parser->parse("SELECT {$this->sql} AS x"); - - $stmts = $parsed->raw()->getStmts(); - - if ($stmts === null || \count($stmts) === 0) { - throw InvalidAstException::invalidFieldValue('stmts', 'ParseResult', 'expected at least one statement'); - } - - $firstStmt = $stmts[0]; - $selectStmt = $firstStmt->getStmt()?->getSelectStmt(); - - if ($selectStmt === null) { - throw InvalidAstException::unexpectedNodeType('SelectStmt', 'unknown'); - } - - $targetList = $selectStmt->getTargetList(); - - if ($targetList === null || \count($targetList) === 0) { - throw InvalidAstException::invalidFieldValue('targetList', 'SelectStmt', 'expected at least one target'); - } - - $firstTarget = $targetList[0]; - $resTarget = $firstTarget->getResTarget(); - - if ($resTarget === null) { - throw InvalidAstException::unexpectedNodeType('ResTarget', 'unknown'); - } - - $val = $resTarget->getVal(); - - if ($val === null) { - throw InvalidAstException::missingRequiredField('val', 'ResTarget'); - } - - return $val; - } -} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/TypeCast.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/TypeCast.php index cb26da10a2..d2ec548d6c 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/TypeCast.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/TypeCast.php @@ -6,7 +6,7 @@ use Flow\PostgreSql\Protobuf\AST\{Node, TypeCast as AstTypeCast}; use Flow\PostgreSql\QueryBuilder\Exception\InvalidAstException; -use Flow\PostgreSql\QueryBuilder\Schema\DataType; +use Flow\PostgreSql\QueryBuilder\Schema\ColumnType; /** * Represents a type cast expression: expr::type or CAST(expr AS type). @@ -15,11 +15,11 @@ { /** * @param Expression $expression Expression to cast - * @param DataType $dataType Target data type + * @param ColumnType $dataType Target data type */ public function __construct( private Expression $expression, - private DataType $dataType, + private ColumnType $dataType, ) { } @@ -45,7 +45,7 @@ public static function fromAst(Node $node) : static throw InvalidAstException::missingRequiredField('typeName', 'TypeCast'); } - $dataType = DataType::fromAst($typeNameNode); + $dataType = ColumnType::fromAst($typeNameNode); return new self($expression, $dataType); } @@ -55,7 +55,7 @@ public function as(string $alias) : AliasedExpression return new AliasedExpression($this, $alias); } - public function getDataType() : DataType + public function getColumnType() : ColumnType { return $this->dataType; } @@ -77,7 +77,7 @@ public function toAst() : Node return $node; } - public function withDataType(DataType $dataType) : self + public function withColumnType(ColumnType $dataType) : self { return new self($this->expression, $dataType); } diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Factory/CreateFactory.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Factory/CreateFactory.php index 7d857cd49a..f906b67ac3 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Factory/CreateFactory.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Factory/CreateFactory.php @@ -8,6 +8,7 @@ use Flow\PostgreSql\QueryBuilder\Schema\CreateSequence\{CreateSequenceBuilder, CreateSequenceOptionsStep}; use Flow\PostgreSql\QueryBuilder\Schema\CreateTable\{CreateTableBuilder, CreateTableColumnsStep, CreateTemporaryTableColumnsStep}; use Flow\PostgreSql\QueryBuilder\Schema\CreateTableAs\{CreateTableAsBuilder, CreateTableAsFinalStep}; +use Flow\PostgreSql\QueryBuilder\Schema\Database\{CreateDatabaseBuilder, CreateDatabaseOptionsStep}; use Flow\PostgreSql\QueryBuilder\Schema\Domain\{CreateDomainBuilder, CreateDomainTypeStep}; use Flow\PostgreSql\QueryBuilder\Schema\Extension\{CreateExtensionBuilder, CreateExtensionOptionsStep}; use Flow\PostgreSql\QueryBuilder\Schema\Function\{CreateFunctionArgsStep, CreateFunctionBuilder, CreateProcedureArgsStep, CreateProcedureBuilder}; @@ -28,6 +29,11 @@ public function compositeType(string $name) : CreateCompositeTypeAttributesStep return CreateCompositeTypeBuilder::create($name); } + public function database(string $name) : CreateDatabaseOptionsStep + { + return CreateDatabaseBuilder::create($name); + } + public function domain(string $name) : CreateDomainTypeStep { return CreateDomainBuilder::create($name); diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Factory/DropFactory.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Factory/DropFactory.php index 4cd1a6d998..5a8e3caa9b 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Factory/DropFactory.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Factory/DropFactory.php @@ -4,6 +4,7 @@ namespace Flow\PostgreSql\QueryBuilder\Factory; +use Flow\PostgreSql\QueryBuilder\Schema\Database\{DropDatabaseBuilder, DropDatabaseFinalStep}; use Flow\PostgreSql\QueryBuilder\Schema\Domain\{DropDomainBuilder, DropDomainFinalStep}; use Flow\PostgreSql\QueryBuilder\Schema\DropSequence\{DropSequenceBuilder, DropSequenceFinalStep}; use Flow\PostgreSql\QueryBuilder\Schema\DropTable\{DropTableBuilder, DropTableFinalStep}; @@ -21,6 +22,11 @@ final readonly class DropFactory { + public function database(string $name) : DropDatabaseFinalStep + { + return DropDatabaseBuilder::create($name); + } + public function domain(string ...$domains) : DropDomainFinalStep { return DropDomainBuilder::create(...$domains); diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Insert/BulkInsert.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Insert/BulkInsert.php index 592ab74bf0..c64dfca679 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Insert/BulkInsert.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Insert/BulkInsert.php @@ -5,7 +5,7 @@ namespace Flow\PostgreSql\QueryBuilder\Insert; use Flow\PostgreSql\QueryBuilder\Clause\ConflictTarget; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; /** * Optimized bulk INSERT query builder for high-performance multi-row inserts. @@ -15,7 +15,7 @@ * * Uses PostgreSQL-style numbered placeholders ($1, $2, $3...). */ -final readonly class BulkInsert implements SqlQuery +final readonly class BulkInsert implements Sql { /** * @param list $columns diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Insert/InsertFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Insert/InsertFinalStep.php index c9bd3c6f14..877f967931 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Insert/InsertFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Insert/InsertFinalStep.php @@ -5,12 +5,12 @@ namespace Flow\PostgreSql\QueryBuilder\Insert; use Flow\PostgreSql\Protobuf\AST\InsertStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; /** * Terminal interface for INSERT query builder. */ -interface InsertFinalStep extends SqlQuery +interface InsertFinalStep extends Sql { /** * Convert this INSERT query to protobuf AST. diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Merge/MergeFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Merge/MergeFinalStep.php index 44813ee620..ea95d069d5 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Merge/MergeFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Merge/MergeFinalStep.php @@ -5,12 +5,12 @@ namespace Flow\PostgreSql\QueryBuilder\Merge; use Flow\PostgreSql\Protobuf\AST\MergeStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; /** * Terminal interface for MERGE query builder. */ -interface MergeFinalStep extends SqlQuery +interface MergeFinalStep extends Sql { /** * Convert this MERGE query to protobuf AST. diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterSequence/AlterSequenceFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterSequence/AlterSequenceFinalStep.php index adf2140224..e8fd9c7740 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterSequence/AlterSequenceFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterSequence/AlterSequenceFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\AlterSequence; use Flow\PostgreSql\Protobuf\AST\AlterSeqStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface AlterSequenceFinalStep extends SqlQuery +interface AlterSequenceFinalStep extends Sql { public function toAst() : AlterSeqStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterSequence/AlterSequenceLoggingFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterSequence/AlterSequenceLoggingFinalStep.php index f1ec293640..6e44075f97 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterSequence/AlterSequenceLoggingFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterSequence/AlterSequenceLoggingFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\AlterSequence; use Flow\PostgreSql\Protobuf\AST\AlterTableStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface AlterSequenceLoggingFinalStep extends SqlQuery +interface AlterSequenceLoggingFinalStep extends Sql { public function toAst() : AlterTableStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterSequence/AlterSequenceOwnerFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterSequence/AlterSequenceOwnerFinalStep.php index 985c65ea75..8dfe29f7d3 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterSequence/AlterSequenceOwnerFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterSequence/AlterSequenceOwnerFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\AlterSequence; use Flow\PostgreSql\Protobuf\AST\AlterTableStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface AlterSequenceOwnerFinalStep extends SqlQuery +interface AlterSequenceOwnerFinalStep extends Sql { public function toAst() : AlterTableStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterSequence/AlterSequenceSchemaFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterSequence/AlterSequenceSchemaFinalStep.php index 834bd87cb9..39abded448 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterSequence/AlterSequenceSchemaFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterSequence/AlterSequenceSchemaFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\AlterSequence; use Flow\PostgreSql\Protobuf\AST\AlterObjectSchemaStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface AlterSequenceSchemaFinalStep extends SqlQuery +interface AlterSequenceSchemaFinalStep extends Sql { public function toAst() : AlterObjectSchemaStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterSequence/RenameSequenceFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterSequence/RenameSequenceFinalStep.php index b656237dbd..1b942cac1f 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterSequence/RenameSequenceFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterSequence/RenameSequenceFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\AlterSequence; use Flow\PostgreSql\Protobuf\AST\RenameStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface RenameSequenceFinalStep extends SqlQuery +interface RenameSequenceFinalStep extends Sql { public function toAst() : RenameStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterTable/AlterTableBuilder.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterTable/AlterTableBuilder.php index d328a2765f..dd878f33f9 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterTable/AlterTableBuilder.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterTable/AlterTableBuilder.php @@ -4,12 +4,11 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\AlterTable; -use Flow\PostgreSql\Parser; use Flow\PostgreSql\Protobuf\AST\{AlterTableCmd, AlterTableStmt, AlterTableType, DropBehavior, Node, ObjectType, RangeVar}; use Flow\PostgreSql\Protobuf\AST\ColumnDef; use Flow\PostgreSql\QueryBuilder\AstToSql; -use Flow\PostgreSql\QueryBuilder\Exception\InvalidAstException; -use Flow\PostgreSql\QueryBuilder\Schema\{ColumnDefinition, DataType}; +use Flow\PostgreSql\QueryBuilder\Expression\Expression; +use Flow\PostgreSql\QueryBuilder\Schema\{ColumnDefinition, ColumnType}; use Flow\PostgreSql\QueryBuilder\Schema\Constraint\TableConstraint; final readonly class AlterTableBuilder implements AlterTableFinalStep @@ -66,6 +65,28 @@ public function addConstraint(TableConstraint $constraint) : AlterTableFinalStep ); } + public function addInherit(string $table) : AlterTableFinalStep + { + $cmd = new AlterTableCmd(); + $cmd->setSubtype(AlterTableType::AT_AddInherit); + + $rangeVar = new RangeVar(); + $rangeVar->setRelname($table); + $rangeVar->setInh(true); + $rangeVar->setRelpersistence('p'); + + $node = new Node(); + $node->setRangeVar($rangeVar); + $cmd->setDef($node); + + return new self( + $this->table, + $this->schema, + [...$this->commands, $cmd], + $this->ifExists, + ); + } + public function alterColumnDropDefault(string $column) : AlterTableFinalStep { $cmd = new AlterTableCmd(); @@ -94,13 +115,13 @@ public function alterColumnDropNotNull(string $column) : AlterTableFinalStep ); } - public function alterColumnSetDefault(string $column, string $defaultExpression) : AlterTableFinalStep + public function alterColumnSetDefault(string $column, Expression $defaultExpression) : AlterTableFinalStep { $cmd = new AlterTableCmd(); $cmd->setSubtype(AlterTableType::AT_ColumnDefault); $cmd->setName($column); - $cmd->setDef($this->parseExpression($defaultExpression)); + $cmd->setDef($defaultExpression->toAst()); return new self( $this->table, @@ -124,7 +145,7 @@ public function alterColumnSetNotNull(string $column) : AlterTableFinalStep ); } - public function alterColumnType(string $column, DataType $type) : AlterTableFinalStep + public function alterColumnType(string $column, ColumnType $type) : AlterTableFinalStep { $cmd = new AlterTableCmd(); $cmd->setSubtype(AlterTableType::AT_AlterColumnType); @@ -259,6 +280,28 @@ public function dropConstraintIfExists(string $constraintName, bool $cascade = f ); } + public function dropInherit(string $table) : AlterTableFinalStep + { + $cmd = new AlterTableCmd(); + $cmd->setSubtype(AlterTableType::AT_DropInherit); + + $rangeVar = new RangeVar(); + $rangeVar->setRelname($table); + $rangeVar->setInh(true); + $rangeVar->setRelpersistence('p'); + + $node = new Node(); + $node->setRangeVar($rangeVar); + $cmd->setDef($node); + + return new self( + $this->table, + $this->schema, + [...$this->commands, $cmd], + $this->ifExists, + ); + } + public function enableTrigger(string $trigger) : AlterTableFinalStep { $cmd = new AlterTableCmd(); @@ -352,11 +395,35 @@ public function renameTo(string $newName) : RenameTableBuilder return RenameTableBuilder::renameTo($this->table, $this->schema, $newName, $this->ifExists); } + public function setLogged() : AlterTableLoggingFinalStep + { + return AlterTableLoggingBuilder::createLogged($this->table, $this->schema, $this->ifExists); + } + public function setSchema(string $schema) : AlterTableSchemaBuilder { return AlterTableSchemaBuilder::create($this->table, $this->schema, $schema, $this->ifExists); } + public function setTablespace(string $tablespace) : AlterTableFinalStep + { + $cmd = new AlterTableCmd(); + $cmd->setSubtype(AlterTableType::AT_SetTableSpace); + $cmd->setName($tablespace); + + return new self( + $this->table, + $this->schema, + [...$this->commands, $cmd], + $this->ifExists, + ); + } + + public function setUnlogged() : AlterTableLoggingFinalStep + { + return AlterTableLoggingBuilder::createUnlogged($this->table, $this->schema, $this->ifExists); + } + public function toAst() : AlterTableStmt { $stmt = new AlterTableStmt(); @@ -391,44 +458,4 @@ public function toAst() : AlterTableStmt return $stmt; } - - private function parseExpression(string $expression) : Node - { - $parser = new Parser(); - $parsed = $parser->parse("SELECT {$expression} AS x"); - - $stmts = $parsed->raw()->getStmts(); - - if ($stmts === null || \count($stmts) === 0) { - throw InvalidAstException::invalidFieldValue('stmts', 'ParseResult', 'expected at least one statement'); - } - - $firstStmt = $stmts[0]; - $selectStmt = $firstStmt->getStmt()?->getSelectStmt(); - - if ($selectStmt === null) { - throw InvalidAstException::unexpectedNodeType('SelectStmt', 'unknown'); - } - - $targetList = $selectStmt->getTargetList(); - - if ($targetList === null || \count($targetList) === 0) { - throw InvalidAstException::invalidFieldValue('targetList', 'SelectStmt', 'expected at least one target'); - } - - $firstTarget = $targetList[0]; - $resTarget = $firstTarget->getResTarget(); - - if ($resTarget === null) { - throw InvalidAstException::unexpectedNodeType('ResTarget', 'unknown'); - } - - $val = $resTarget->getVal(); - - if ($val === null) { - throw InvalidAstException::missingRequiredField('val', 'ResTarget'); - } - - return $val; - } } diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterTable/AlterTableFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterTable/AlterTableFinalStep.php index 77707d9713..5bae42d085 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterTable/AlterTableFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterTable/AlterTableFinalStep.php @@ -5,25 +5,28 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\AlterTable; use Flow\PostgreSql\Protobuf\AST\AlterTableStmt; -use Flow\PostgreSql\QueryBuilder\Schema\{ColumnDefinition, DataType}; +use Flow\PostgreSql\QueryBuilder\Expression\Expression; +use Flow\PostgreSql\QueryBuilder\Schema\{ColumnDefinition, ColumnType}; use Flow\PostgreSql\QueryBuilder\Schema\Constraint\TableConstraint; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface AlterTableFinalStep extends SqlQuery +interface AlterTableFinalStep extends Sql { public function addColumn(ColumnDefinition $column) : self; public function addConstraint(TableConstraint $constraint) : self; + public function addInherit(string $table) : self; + public function alterColumnDropDefault(string $column) : self; public function alterColumnDropNotNull(string $column) : self; - public function alterColumnSetDefault(string $column, string $defaultExpression) : self; + public function alterColumnSetDefault(string $column, Expression $defaultExpression) : self; public function alterColumnSetNotNull(string $column) : self; - public function alterColumnType(string $column, DataType $type) : self; + public function alterColumnType(string $column, ColumnType $type) : self; public function disableTrigger(string $trigger) : self; @@ -39,6 +42,8 @@ public function dropConstraint(string $constraintName, bool $cascade = false) : public function dropConstraintIfExists(string $constraintName, bool $cascade = false) : self; + public function dropInherit(string $table) : self; + public function enableTrigger(string $trigger) : self; public function enableTriggerAll() : self; @@ -57,8 +62,14 @@ public function renameConstraint(string $oldName, string $newName) : RenameTable public function renameTo(string $newName) : RenameTableBuilder; + public function setLogged() : AlterTableLoggingFinalStep; + public function setSchema(string $schema) : AlterTableSchemaBuilder; + public function setTablespace(string $tablespace) : self; + + public function setUnlogged() : AlterTableLoggingFinalStep; + public function toAst() : AlterTableStmt; public function toSql() : string; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterTable/AlterTableLoggingBuilder.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterTable/AlterTableLoggingBuilder.php new file mode 100644 index 0000000000..85cfd2a1ab --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterTable/AlterTableLoggingBuilder.php @@ -0,0 +1,63 @@ +setObjtype(ObjectType::OBJECT_TABLE); + + $rangeVar = new RangeVar(); + $rangeVar->setRelname($this->table); + $rangeVar->setInh(true); + $rangeVar->setRelpersistence('p'); + + if ($this->schema !== null) { + $rangeVar->setSchemaname($this->schema); + } + + $stmt->setRelation($rangeVar); + + if ($this->ifExists) { + $stmt->setMissingOk(true); + } + + $cmd = new AlterTableCmd(); + $cmd->setSubtype($this->logged ? AlterTableType::AT_SetLogged : AlterTableType::AT_SetUnLogged); + $cmd->setBehavior(DropBehavior::DROP_RESTRICT); + + $cmdNode = new Node(); + $cmdNode->setAlterTableCmd($cmd); + + $stmt->setCmds([$cmdNode]); + + return $stmt; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterTable/AlterTableLoggingFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterTable/AlterTableLoggingFinalStep.php new file mode 100644 index 0000000000..5f039ac141 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterTable/AlterTableLoggingFinalStep.php @@ -0,0 +1,15 @@ +setContype(ConstrType::CONSTR_CHECK); - $constraint->setRawExpr($this->parseExpression($expression)); + $constraint->setRawExpr($condition->toAst()); return new self( $this->name, @@ -65,20 +64,20 @@ public function default(bool|float|int|string|Expression|null $value) : self ); } - public function defaultRaw(string $expression) : self + public function defaultRaw(Expression $expression) : self { return new self( $this->name, $this->type, $this->notNull, - $this->parseExpression($expression), + $expression->toAst(), $this->identity, $this->generatedExpression, $this->constraints, ); } - public function generatedAs(string $expression) : self + public function generatedAs(Expression $expression) : self { return new self( $this->name, @@ -86,21 +85,19 @@ public function generatedAs(string $expression) : self $this->notNull, $this->defaultValue, $this->identity, - $this->parseExpression($expression), + $expression->toAst(), $this->constraints, ); } - public function identity(string $type = 'ALWAYS') : self + public function identity(IdentityGeneration $type = IdentityGeneration::ALWAYS) : self { - $identityChar = \strtoupper($type) === 'ALWAYS' ? 'a' : 'd'; - return new self( $this->name, $this->type, $this->notNull, $this->defaultValue, - $identityChar, + $type, $this->generatedExpression, $this->constraints, ); @@ -184,10 +181,6 @@ public function toAst() : ColumnDef $columnDef->setTypeName($this->type->toAst()); $columnDef->setIsLocal(true); - if ($this->identity !== null) { - $columnDef->setIdentity($this->identity); - } - $allConstraints = []; if ($this->notNull) { @@ -207,6 +200,13 @@ public function toAst() : ColumnDef $allConstraints[] = $constraint; } + if ($this->identity !== null) { + $identityConstraint = new Constraint(); + $identityConstraint->setContype(ConstrType::CONSTR_IDENTITY); + $identityConstraint->setGeneratedWhen($this->identity->value); + $allConstraints[] = $identityConstraint; + } + if ($this->generatedExpression !== null) { $columnDef->setGenerated('s'); @@ -251,50 +251,26 @@ public function unique() : self private function createLiteralNode(bool|float|int|string|null $value) : Node { - $parser = new Parser(); - - $literal = match (true) { - $value === null => 'NULL', - \is_bool($value) => $value ? 'TRUE' : 'FALSE', - \is_string($value) => "'" . \str_replace("'", "''", $value) . "'", - default => (string) $value, - }; - - $parsed = $parser->parse("SELECT {$literal} AS x"); - - $stmts = $parsed->raw()->getStmts(); - - if ($stmts === null || \count($stmts) === 0) { - throw InvalidAstException::invalidFieldValue('stmts', 'ParseResult', 'expected at least one statement'); + $aConst = new A_Const(); + + if ($value === null) { + $aConst->setIsnull(true); + } elseif (\is_bool($value)) { + /** @phpstan-ignore-next-line */ + $aConst->setBoolval((new PBBoolean())->setBoolval($value)); + } elseif (\is_int($value)) { + /** @phpstan-ignore-next-line */ + $aConst->setIval((new PBInteger())->setIval($value)); + } elseif (\is_float($value)) { + $aConst->setFval((new PBFloat())->setFval((string) $value)); + } else { + $aConst->setSval((new PBString())->setSval($value)); } - $firstStmt = $stmts[0]; - $selectStmt = $firstStmt->getStmt()?->getSelectStmt(); - - if ($selectStmt === null) { - throw InvalidAstException::unexpectedNodeType('SelectStmt', 'unknown'); - } - - $targetList = $selectStmt->getTargetList(); - - if ($targetList === null || \count($targetList) === 0) { - throw InvalidAstException::invalidFieldValue('targetList', 'SelectStmt', 'expected at least one target'); - } - - $firstTarget = $targetList[0]; - $resTarget = $firstTarget->getResTarget(); - - if ($resTarget === null) { - throw InvalidAstException::unexpectedNodeType('ResTarget', 'unknown'); - } - - $val = $resTarget->getVal(); - - if ($val === null) { - throw InvalidAstException::missingRequiredField('val', 'ResTarget'); - } + $node = new Node(); + $node->setAConst($aConst); - return $val; + return $node; } private function createStringNode(string $value) : Node @@ -307,44 +283,4 @@ private function createStringNode(string $value) : Node return $node; } - - private function parseExpression(string $expression) : Node - { - $parser = new Parser(); - $parsed = $parser->parse("SELECT {$expression} AS x"); - - $stmts = $parsed->raw()->getStmts(); - - if ($stmts === null || \count($stmts) === 0) { - throw InvalidAstException::invalidFieldValue('stmts', 'ParseResult', 'expected at least one statement'); - } - - $firstStmt = $stmts[0]; - $selectStmt = $firstStmt->getStmt()?->getSelectStmt(); - - if ($selectStmt === null) { - throw InvalidAstException::unexpectedNodeType('SelectStmt', 'unknown'); - } - - $targetList = $selectStmt->getTargetList(); - - if ($targetList === null || \count($targetList) === 0) { - throw InvalidAstException::invalidFieldValue('targetList', 'SelectStmt', 'expected at least one target'); - } - - $firstTarget = $targetList[0]; - $resTarget = $firstTarget->getResTarget(); - - if ($resTarget === null) { - throw InvalidAstException::unexpectedNodeType('ResTarget', 'unknown'); - } - - $val = $resTarget->getVal(); - - if ($val === null) { - throw InvalidAstException::missingRequiredField('val', 'ResTarget'); - } - - return $val; - } } diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/DataType.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/ColumnType.php similarity index 51% rename from src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/DataType.php rename to src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/ColumnType.php index f623b0c949..2022d1df7e 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/DataType.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/ColumnType.php @@ -7,71 +7,69 @@ use Flow\PostgreSql\Protobuf\AST\{A_Const, Integer, Node, PBString, TypeName}; use Flow\PostgreSql\QueryBuilder\Exception\InvalidAstException; -final readonly class DataType +/** + * @phpstan-type ColumnTypeShape = array{name: string, schema: ?string, precision: ?int, scale: ?int, is_array: bool} + */ +final readonly class ColumnType { - /** - * @param list $names - * @param list $typmods - * @param list $arrayBounds - */ private function __construct( - private array $names, - private array $typmods = [], - private array $arrayBounds = [], + private string $name, + private ?string $schema = null, + private ?int $precision = null, + private ?int $scale = null, + private bool $isArray = false, ) { } public static function array(self $elementType) : self { return new self( - $elementType->names, - $elementType->typmods, - [-1], + $elementType->name, + $elementType->schema, + $elementType->precision, + $elementType->scale, + true, ); } public static function bigint() : self { - return new self(['pg_catalog', 'int8']); + return new self('int8', 'pg_catalog'); } public static function bigserial() : self { - return new self(['bigserial']); + return new self('bigserial'); } public static function boolean() : self { - return new self(['pg_catalog', 'bool']); + return new self('bool', 'pg_catalog'); } public static function bytea() : self { - return new self(['pg_catalog', 'bytea']); + return new self('bytea', 'pg_catalog'); } public static function char(int $length) : self { - return new self(['pg_catalog', 'bpchar'], [$length]); + return new self('bpchar', 'pg_catalog', $length); } public static function cidr() : self { - return new self(['pg_catalog', 'cidr']); + return new self('cidr', 'pg_catalog'); } public static function custom(string $typeName, ?string $schema = null) : self { - if ($schema !== null) { - return new self([$schema, $typeName]); - } - - return new self([$typeName]); + return new self($typeName, $schema); } public static function date() : self { - return new self(['pg_catalog', 'date']); + return new self('date', 'pg_catalog'); } public static function decimal(?int $precision = null, ?int $scale = null) : self @@ -81,7 +79,21 @@ public static function decimal(?int $precision = null, ?int $scale = null) : sel public static function doublePrecision() : self { - return new self(['pg_catalog', 'float8']); + return new self('float8', 'pg_catalog'); + } + + /** + * @param ColumnTypeShape $data + */ + public static function fromArray(array $data) : self + { + return new self( + name: $data['name'], + schema: $data['schema'] ?? null, + precision: $data['precision'] ?? null, + scale: $data['scale'] ?? null, + isArray: $data['is_array'] ?? false, + ); } public static function fromAst(TypeName $typeName) : self @@ -104,6 +116,9 @@ public static function fromAst(TypeName $typeName) : self $names[] = $stringNode->getSval(); } + $schema = \count($names) > 1 ? $names[0] : null; + $name = $names[\count($names) - 1]; + $typmods = []; $typmodsNodes = $typeName->getTypmods(); @@ -120,7 +135,7 @@ public static function fromAst(TypeName $typeName) : self } } - $arrayBounds = []; + $isArray = false; $arrayBoundsNodes = $typeName->getArrayBounds(); foreach ($arrayBoundsNodes as $boundNode) { @@ -130,126 +145,134 @@ public static function fromAst(TypeName $typeName) : self $ival = $aConst->getIval(); if ($ival !== null) { - /** @phpstan-ignore method.nonObject (protobuf PHPDoc says int but getIval() actually returns Integer object) */ - $arrayBounds[] = $ival->getIval(); + $isArray = true; + + continue; } } + + $integer = $boundNode->getInteger(); + + if ($integer !== null) { + $isArray = true; + } } - return new self($names, $typmods, $arrayBounds); + return new self( + $name, + $schema, + $typmods[0] ?? null, + $typmods[1] ?? null, + $isArray, + ); } public static function inet() : self { - return new self(['pg_catalog', 'inet']); + return new self('inet', 'pg_catalog'); } public static function integer() : self { - return new self(['pg_catalog', 'int4']); + return new self('int4', 'pg_catalog'); } public static function interval() : self { - return new self(['pg_catalog', 'interval']); + return new self('interval', 'pg_catalog'); } public static function json() : self { - return new self(['pg_catalog', 'json']); + return new self('json', 'pg_catalog'); } public static function jsonb() : self { - return new self(['pg_catalog', 'jsonb']); + return new self('jsonb', 'pg_catalog'); } public static function macaddr() : self { - return new self(['pg_catalog', 'macaddr']); + return new self('macaddr', 'pg_catalog'); } public static function numeric(?int $precision = null, ?int $scale = null) : self { - $typmods = []; - - if ($precision !== null) { - $typmods[] = $precision; - - if ($scale !== null) { - $typmods[] = $scale; - } - } - - return new self(['pg_catalog', 'numeric'], $typmods); + return new self('numeric', 'pg_catalog', $precision, $scale); } public static function real() : self { - return new self(['pg_catalog', 'float4']); + return new self('float4', 'pg_catalog'); } public static function serial() : self { - return new self(['serial']); + return new self('serial'); } public static function smallint() : self { - return new self(['pg_catalog', 'int2']); + return new self('int2', 'pg_catalog'); } public static function smallserial() : self { - return new self(['smallserial']); + return new self('smallserial'); } public static function text() : self { - return new self(['pg_catalog', 'text']); + return new self('text', 'pg_catalog'); } public static function time(?int $precision = null) : self { - $typmods = []; - - if ($precision !== null) { - $typmods[] = $precision; - } - - return new self(['pg_catalog', 'time'], $typmods); + return new self('time', 'pg_catalog', $precision); } public static function timestamp(?int $precision = null) : self { - $typmods = []; - - if ($precision !== null) { - $typmods[] = $precision; - } - - return new self(['pg_catalog', 'timestamp'], $typmods); + return new self('timestamp', 'pg_catalog', $precision); } public static function timestamptz(?int $precision = null) : self { - $typmods = []; - - if ($precision !== null) { - $typmods[] = $precision; - } - - return new self(['pg_catalog', 'timestamptz'], $typmods); + return new self('timestamptz', 'pg_catalog', $precision); } public static function uuid() : self { - return new self(['pg_catalog', 'uuid']); + return new self('uuid', 'pg_catalog'); } public static function varchar(int $length) : self { - return new self(['pg_catalog', 'varchar'], [$length]); + return new self('varchar', 'pg_catalog', $length); + } + + public function isEqual(self $other) : bool + { + return self::normalizedName($this->name) === self::normalizedName($other->name) + && $this->normalizedSchema() === $other->normalizedSchema() + && $this->precision === $other->precision + && $this->scale === $other->scale + && $this->isArray === $other->isArray; + } + + /** + * @return ColumnTypeShape + */ + public function normalize() : array + { + return [ + 'name' => $this->name, + 'schema' => $this->normalizedSchema(), + 'precision' => $this->precision, + 'scale' => $this->scale, + 'is_array' => $this->isArray, + ]; } public function toAst() : TypeName @@ -258,30 +281,29 @@ public function toAst() : TypeName $names = []; - foreach ($this->names as $name) { - $names[] = $this->createStringNode($name); + if ($this->schema !== null) { + $names[] = $this->createStringNode($this->schema); } + $names[] = $this->createStringNode($this->name); $typeName->setNames($names); - if ($this->typmods !== []) { - $typmods = []; + $typmods = []; + + if ($this->precision !== null) { + $typmods[] = $this->createIntegerConstNode($this->precision); - foreach ($this->typmods as $typmod) { - $typmods[] = $this->createIntegerConstNode($typmod); + if ($this->scale !== null) { + $typmods[] = $this->createIntegerConstNode($this->scale); } + } + if ($typmods !== []) { $typeName->setTypmods($typmods); } - if ($this->arrayBounds !== []) { - $arrayBounds = []; - - foreach ($this->arrayBounds as $bound) { - $arrayBounds[] = $this->createIntegerConstNode($bound); - } - - $typeName->setArrayBounds($arrayBounds); + if ($this->isArray) { + $typeName->setArrayBounds([$this->createIntegerConstNode(-1)]); } return $typeName; @@ -311,4 +333,26 @@ private function createStringNode(string $value) : Node return $node; } + + private function normalizedSchema() : ?string + { + if ($this->schema === 'pg_catalog') { + return null; + } + + return $this->schema; + } + + /** + * Serial types are syntactic sugar — PostgreSQL stores them as their base integer types. + */ + private static function normalizedName(string $name) : string + { + return match ($name) { + 'bigserial' => 'int8', + 'serial' => 'int4', + 'smallserial' => 'int2', + default => $name, + }; + } } diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Constraint/CheckConstraint.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Constraint/CheckConstraint.php index 3eb09717dc..3ca8f0b144 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Constraint/CheckConstraint.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Constraint/CheckConstraint.php @@ -4,32 +4,31 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Constraint; -use Flow\PostgreSql\Parser; -use Flow\PostgreSql\Protobuf\AST\{ConstrType, Constraint, Node}; -use Flow\PostgreSql\QueryBuilder\Exception\InvalidAstException; +use Flow\PostgreSql\Protobuf\AST\{ConstrType, Constraint}; +use Flow\PostgreSql\QueryBuilder\Condition\Condition; final readonly class CheckConstraint implements TableConstraint { private function __construct( - private string $expression, + private Condition $condition, private ?string $name = null, private bool $noInherit = false, ) { } - public static function create(string $expression) : self + public static function create(Condition $condition) : self { - return new self($expression); + return new self($condition); } public function name(string $name) : self { - return new self($this->expression, $name, $this->noInherit); + return new self($this->condition, $name, $this->noInherit); } public function noInherit() : self { - return new self($this->expression, $this->name, true); + return new self($this->condition, $this->name, true); } public function toAst() : Constraint @@ -45,48 +44,8 @@ public function toAst() : Constraint $constraint->setIsNoInherit(true); } - $constraint->setRawExpr($this->parseExpression($this->expression)); + $constraint->setRawExpr($this->condition->toAst()); return $constraint; } - - private function parseExpression(string $expression) : Node - { - $parser = new Parser(); - $parsed = $parser->parse("SELECT {$expression} AS x"); - - $stmts = $parsed->raw()->getStmts(); - - if ($stmts === null || \count($stmts) === 0) { - throw InvalidAstException::invalidFieldValue('stmts', 'ParseResult', 'expected at least one statement'); - } - - $firstStmt = $stmts[0]; - $selectStmt = $firstStmt->getStmt()?->getSelectStmt(); - - if ($selectStmt === null) { - throw InvalidAstException::unexpectedNodeType('SelectStmt', 'unknown'); - } - - $targetList = $selectStmt->getTargetList(); - - if ($targetList === null || \count($targetList) === 0) { - throw InvalidAstException::invalidFieldValue('targetList', 'SelectStmt', 'expected at least one target'); - } - - $firstTarget = $targetList[0]; - $resTarget = $firstTarget->getResTarget(); - - if ($resTarget === null) { - throw InvalidAstException::unexpectedNodeType('ResTarget', 'unknown'); - } - - $val = $resTarget->getVal(); - - if ($val === null) { - throw InvalidAstException::missingRequiredField('val', 'ResTarget'); - } - - return $val; - } } diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Constraint/ExcludeConstraint.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Constraint/ExcludeConstraint.php index f5286f81d0..1ab12505f8 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Constraint/ExcludeConstraint.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Constraint/ExcludeConstraint.php @@ -4,21 +4,21 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Constraint; -use Flow\PostgreSql\Parser; use Flow\PostgreSql\Protobuf\AST\{ConstrType, Constraint, Node, PBString}; use Flow\PostgreSql\Protobuf\AST\PBList; -use Flow\PostgreSql\QueryBuilder\Exception\InvalidAstException; +use Flow\PostgreSql\QueryBuilder\Condition\Condition; +use Flow\PostgreSql\QueryBuilder\Expression\Expression; final readonly class ExcludeConstraint implements TableConstraint { /** - * @param list $elements + * @param list $elements */ private function __construct( private string $accessMethod, private array $elements = [], private ?string $name = null, - private ?string $whereClause = null, + private ?Condition $whereCondition = null, ) { } @@ -27,13 +27,13 @@ public static function create(string $accessMethod = 'gist') : self return new self($accessMethod); } - public function element(string $element, string $operator) : self + public function element(Expression $element, string $operator) : self { return new self( $this->accessMethod, [...$this->elements, ['element' => $element, 'operator' => $operator]], $this->name, - $this->whereClause, + $this->whereCondition, ); } @@ -43,7 +43,7 @@ public function name(string $name) : self $this->accessMethod, $this->elements, $name, - $this->whereClause, + $this->whereCondition, ); } @@ -61,27 +61,27 @@ public function toAst() : Constraint $exclusions = []; foreach ($this->elements as $element) { - $exclusions[] = $this->parseExpression($element['element']); + $exclusions[] = $element['element']->toAst(); $exclusions[] = $this->createOperatorNode($element['operator']); } $constraint->setExclusions($exclusions); } - if ($this->whereClause !== null) { - $constraint->setWhereClause($this->parseExpression($this->whereClause)); + if ($this->whereCondition !== null) { + $constraint->setWhereClause($this->whereCondition->toAst()); } return $constraint; } - public function where(string $whereClause) : self + public function where(Condition $condition) : self { return new self( $this->accessMethod, $this->elements, $this->name, - $whereClause, + $condition, ); } @@ -104,44 +104,4 @@ private function createOperatorNode(string $operator) : Node return $resultNode; } - - private function parseExpression(string $expression) : Node - { - $parser = new Parser(); - $parsed = $parser->parse("SELECT {$expression} AS x"); - - $stmts = $parsed->raw()->getStmts(); - - if ($stmts === null || \count($stmts) === 0) { - throw InvalidAstException::invalidFieldValue('stmts', 'ParseResult', 'expected at least one statement'); - } - - $firstStmt = $stmts[0]; - $selectStmt = $firstStmt->getStmt()?->getSelectStmt(); - - if ($selectStmt === null) { - throw InvalidAstException::unexpectedNodeType('SelectStmt', 'unknown'); - } - - $targetList = $selectStmt->getTargetList(); - - if ($targetList === null || \count($targetList) === 0) { - throw InvalidAstException::invalidFieldValue('targetList', 'SelectStmt', 'expected at least one target'); - } - - $firstTarget = $targetList[0]; - $resTarget = $firstTarget->getResTarget(); - - if ($resTarget === null) { - throw InvalidAstException::unexpectedNodeType('ResTarget', 'unknown'); - } - - $val = $resTarget->getVal(); - - if ($val === null) { - throw InvalidAstException::missingRequiredField('val', 'ResTarget'); - } - - return $val; - } } diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Constraint/ForeignKeyConstraint.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Constraint/ForeignKeyConstraint.php index 7b11e8c57e..779a6fd5ca 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Constraint/ForeignKeyConstraint.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Constraint/ForeignKeyConstraint.php @@ -5,6 +5,7 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Constraint; use Flow\PostgreSql\Protobuf\AST\{ConstrType, Constraint, Node, PBString, RangeVar}; +use Flow\PostgreSql\QueryBuilder\QualifiedIdentifier; use Flow\PostgreSql\QueryBuilder\Schema\ReferentialAction; final readonly class ForeignKeyConstraint implements TableConstraint @@ -32,7 +33,9 @@ private function __construct( */ public static function create(array $columns, string $referenceTable, array $referenceColumns = []) : self { - return new self($columns, $referenceTable, $referenceColumns); + $identifier = QualifiedIdentifier::parse($referenceTable); + + return new self($columns, $identifier->name(), $referenceColumns, $identifier->schema()); } public function deferrable(bool $initiallyDeferred = false) : self diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/CreateSequence/CreateSequenceFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/CreateSequence/CreateSequenceFinalStep.php index 30b6703057..88f422cf3d 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/CreateSequence/CreateSequenceFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/CreateSequence/CreateSequenceFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\CreateSequence; use Flow\PostgreSql\Protobuf\AST\CreateSeqStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface CreateSequenceFinalStep extends SqlQuery +interface CreateSequenceFinalStep extends Sql { public function toAst() : CreateSeqStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/CreateTable/CreateTableFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/CreateTable/CreateTableFinalStep.php index 03bbb0f877..e73007fa68 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/CreateTable/CreateTableFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/CreateTable/CreateTableFinalStep.php @@ -6,9 +6,9 @@ use Flow\PostgreSql\Protobuf\AST\CreateStmt; use Flow\PostgreSql\QueryBuilder\Schema\Constraint\TableConstraint; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface CreateTableFinalStep extends SqlQuery +interface CreateTableFinalStep extends Sql { public function constraint(TableConstraint $constraint) : self; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/CreateTableAs/CreateTableAsFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/CreateTableAs/CreateTableAsFinalStep.php index 615db78e77..941bed19d1 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/CreateTableAs/CreateTableAsFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/CreateTableAs/CreateTableAsFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\CreateTableAs; use Flow\PostgreSql\Protobuf\AST\CreateTableAsStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface CreateTableAsFinalStep extends SqlQuery +interface CreateTableAsFinalStep extends Sql { public function columnNames(string ...$names) : self; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Database/CreateDatabaseBuilder.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Database/CreateDatabaseBuilder.php new file mode 100644 index 0000000000..557339630c --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Database/CreateDatabaseBuilder.php @@ -0,0 +1,190 @@ + $options + */ + private function __construct( + private string $name, + private array $options = [], + ) { + } + + public static function create(string $name) : CreateDatabaseOptionsStep + { + return new self($name); + } + + public function allowConnections(bool $allow) : self + { + return $this->withOption('allow_connections', $this->booleanNode($allow)); + } + + public function builtinLocale(string $locale) : self + { + return $this->withOption('builtin_locale', $this->stringNode($locale)); + } + + public function collationVersion(string $version) : self + { + return $this->withOption('collation_version', $this->stringNode($version)); + } + + public function connectionLimit(int $limit) : self + { + return $this->withOption('connection_limit', $this->integerNode($limit)); + } + + public function encoding(string $encoding) : self + { + return $this->withOption('encoding', $this->stringNode($encoding)); + } + + public function icuLocale(string $locale) : self + { + return $this->withOption('icu_locale', $this->stringNode($locale)); + } + + public function icuRules(string $rules) : self + { + return $this->withOption('icu_rules', $this->stringNode($rules)); + } + + public function ifNotExists() : self + { + return $this->withOption('if_not_exists', $this->booleanNode(true)); + } + + public function isTemplate(bool $template) : self + { + return $this->withOption('is_template', $this->booleanNode($template)); + } + + public function lcCollate(string $collate) : self + { + return $this->withOption('lc_collate', $this->stringNode($collate)); + } + + public function lcCtype(string $ctype) : self + { + return $this->withOption('lc_ctype', $this->stringNode($ctype)); + } + + public function locale(string $locale) : self + { + return $this->withOption('locale', $this->stringNode($locale)); + } + + public function localeProvider(string $provider) : self + { + return $this->withOption('locale_provider', $this->stringNode($provider)); + } + + public function oid(int $oid) : self + { + return $this->withOption('oid', $this->integerNode($oid)); + } + + public function owner(string $role) : self + { + return $this->withOption('owner', $this->stringNode($role)); + } + + public function strategy(string $strategy) : self + { + return $this->withOption('strategy', $this->stringNode($strategy)); + } + + public function tablespace(string $name) : self + { + return $this->withOption('tablespace', $this->stringNode($name)); + } + + public function template(string $name) : self + { + return $this->withOption('template', $this->stringNode($name)); + } + + public function toAst() : CreatedbStmt + { + $stmt = new CreatedbStmt(); + $stmt->setDbname($this->name); + + $optionNodes = []; + + foreach ($this->options as $option) { + $defElem = new DefElem(); + $defElem->setDefname($option['name']); + + if ($option['arg'] !== null) { + $defElem->setArg($option['arg']); + } + + $node = new Node(); + $node->setDefElem($defElem); + $optionNodes[] = $node; + } + + if ($optionNodes !== []) { + $stmt->setOptions($optionNodes); + } + + return $stmt; + } + + private function booleanNode(bool $value) : Node + { + $integer = new Integer(); + $integer->setIval($value ? 1 : 0); + + $node = new Node(); + /** @phpstan-ignore argument.type (protobuf PHPDoc says int but actually expects Integer) */ + $node->setInteger($integer); + + return $node; + } + + private function integerNode(int $value) : Node + { + $integer = new Integer(); + $integer->setIval($value); + + $node = new Node(); + /** @phpstan-ignore argument.type (protobuf PHPDoc says int but actually expects Integer) */ + $node->setInteger($integer); + + return $node; + } + + private function stringNode(string $value) : Node + { + $str = new PBString(); + $str->setSval($value); + + $node = new Node(); + $node->setString($str); + + return $node; + } + + private function withOption(string $name, ?Node $arg) : self + { + $newOptions = $this->options; + $newOptions[] = ['name' => $name, 'arg' => $arg]; + + return new self( + $this->name, + $newOptions, + ); + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Database/CreateDatabaseFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Database/CreateDatabaseFinalStep.php new file mode 100644 index 0000000000..384dc5fa9b --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Database/CreateDatabaseFinalStep.php @@ -0,0 +1,15 @@ +name, $this->ifExists, true); + } + + public function ifExists() : self + { + return new self($this->name, true, $this->force); + } + + public function toAst() : DropdbStmt + { + $stmt = new DropdbStmt(); + $stmt->setDbname($this->name); + $stmt->setMissingOk($this->ifExists); + + if ($this->force) { + $defElem = new DefElem(); + $defElem->setDefname('force'); + $node = new Node(); + $node->setDefElem($defElem); + $stmt->setOptions([$node]); + } + + return $stmt; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Database/DropDatabaseFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Database/DropDatabaseFinalStep.php new file mode 100644 index 0000000000..d2f791a328 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Database/DropDatabaseFinalStep.php @@ -0,0 +1,19 @@ +name(), $identifier->schema()); } - public function addConstraint(string $name, string $expression) : AlterDomainFinalStep + public function addConstraint(string $name, Condition $condition) : AlterDomainFinalStep { return new self( $this->name, $this->schema, 'C', $name, - $expression, + $condition, $this->behavior, $this->missingOk, ); @@ -122,7 +122,7 @@ public function restrict() : AlterDomainFinalStep ); } - public function setDefault(string $expression) : AlterDomainFinalStep + public function setDefault(Expression $expression) : AlterDomainFinalStep { return new self( $this->name, @@ -178,7 +178,7 @@ public function toAst() : AlterDomainStmt if ($this->subtype === 'C' && $this->expression !== null) { $constraint = new Constraint(); $constraint->setContype(ConstrType::CONSTR_CHECK); - $constraint->setRawExpr($this->parseExpression($this->expression)); + $constraint->setRawExpr($this->expression->toAst()); if ($this->constraintName !== null) { $constraint->setConname($this->constraintName); @@ -188,7 +188,7 @@ public function toAst() : AlterDomainStmt $defNode->setConstraint($constraint); $stmt->setDef($defNode); } elseif ($this->subtype === 'T' && $this->expression !== null) { - $stmt->setDef($this->parseExpression($this->expression)); + $stmt->setDef($this->expression->toAst()); } $stmt->setBehavior($this->behavior); @@ -209,44 +209,4 @@ public function validateConstraint(string $name) : AlterDomainFinalStep $this->missingOk, ); } - - private function parseExpression(string $expression) : Node - { - $parser = new Parser(); - $parsed = $parser->parse("SELECT {$expression} AS x"); - - $stmts = $parsed->raw()->getStmts(); - - if ($stmts === null || \count($stmts) === 0) { - throw InvalidAstException::invalidFieldValue('stmts', 'ParseResult', 'expected at least one statement'); - } - - $firstStmt = $stmts[0]; - $selectStmt = $firstStmt->getStmt()?->getSelectStmt(); - - if ($selectStmt === null) { - throw InvalidAstException::unexpectedNodeType('SelectStmt', 'unknown'); - } - - $targetList = $selectStmt->getTargetList(); - - if ($targetList === null || \count($targetList) === 0) { - throw InvalidAstException::invalidFieldValue('targetList', 'SelectStmt', 'expected at least one target'); - } - - $firstTarget = $targetList[0]; - $resTarget = $firstTarget->getResTarget(); - - if ($resTarget === null) { - throw InvalidAstException::unexpectedNodeType('ResTarget', 'unknown'); - } - - $val = $resTarget->getVal(); - - if ($val === null) { - throw InvalidAstException::missingRequiredField('val', 'ResTarget'); - } - - return $val; - } } diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Domain/AlterDomainFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Domain/AlterDomainFinalStep.php index 52806238a8..cec729ee6f 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Domain/AlterDomainFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Domain/AlterDomainFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Domain; use Flow\PostgreSql\Protobuf\AST\AlterDomainStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface AlterDomainFinalStep extends SqlQuery +interface AlterDomainFinalStep extends Sql { public function cascade() : self; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Domain/CreateDomainBuilder.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Domain/CreateDomainBuilder.php index 8d85d80703..d915d57e36 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Domain/CreateDomainBuilder.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Domain/CreateDomainBuilder.php @@ -4,11 +4,11 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Domain; -use Flow\PostgreSql\Parser; use Flow\PostgreSql\Protobuf\AST\{CollateClause, ConstrType, Constraint, CreateDomainStmt, Node, PBString}; use Flow\PostgreSql\QueryBuilder\{AstToSql, QualifiedIdentifier}; -use Flow\PostgreSql\QueryBuilder\Exception\InvalidAstException; -use Flow\PostgreSql\QueryBuilder\Schema\DataType; +use Flow\PostgreSql\QueryBuilder\Condition\Condition; +use Flow\PostgreSql\QueryBuilder\Expression\Expression; +use Flow\PostgreSql\QueryBuilder\Schema\ColumnType; final readonly class CreateDomainBuilder implements CreateDomainOptionsStep, CreateDomainTypeStep { @@ -20,7 +20,7 @@ private function __construct( private string $name, private ?string $schema = null, - private ?DataType $dataType = null, + private ?ColumnType $dataType = null, private ?string $collation = null, private array $constraints = [], private ?string $currentConstraintName = null, @@ -34,7 +34,7 @@ public static function create(string $name) : CreateDomainTypeStep return new self($identifier->name(), $identifier->schema()); } - public function as(DataType $dataType) : CreateDomainOptionsStep + public function as(ColumnType $dataType) : CreateDomainOptionsStep { return new self( $this->name, @@ -46,11 +46,11 @@ public function as(DataType $dataType) : CreateDomainOptionsStep ); } - public function check(string $expression) : CreateDomainOptionsStep + public function check(Condition $condition) : CreateDomainOptionsStep { $constraint = new Constraint(); $constraint->setContype(ConstrType::CONSTR_CHECK); - $constraint->setRawExpr($this->parseExpression($expression)); + $constraint->setRawExpr($condition->toAst()); if ($this->currentConstraintName !== null) { $constraint->setConname($this->currentConstraintName); @@ -93,11 +93,11 @@ public function constraint(string $name) : CreateDomainOptionsStep ); } - public function default(string $expression) : CreateDomainOptionsStep + public function default(Expression $expression) : CreateDomainOptionsStep { $constraint = new Constraint(); $constraint->setContype(ConstrType::CONSTR_DEFAULT); - $constraint->setRawExpr($this->parseExpression($expression)); + $constraint->setRawExpr($expression->toAst()); $newConstraints = $this->constraints; $newConstraints[] = $constraint; @@ -206,44 +206,4 @@ public function toAst() : CreateDomainStmt return $stmt; } - - private function parseExpression(string $expression) : Node - { - $parser = new Parser(); - $parsed = $parser->parse("SELECT {$expression} AS x"); - - $stmts = $parsed->raw()->getStmts(); - - if ($stmts === null || \count($stmts) === 0) { - throw InvalidAstException::invalidFieldValue('stmts', 'ParseResult', 'expected at least one statement'); - } - - $firstStmt = $stmts[0]; - $selectStmt = $firstStmt->getStmt()?->getSelectStmt(); - - if ($selectStmt === null) { - throw InvalidAstException::unexpectedNodeType('SelectStmt', 'unknown'); - } - - $targetList = $selectStmt->getTargetList(); - - if ($targetList === null || \count($targetList) === 0) { - throw InvalidAstException::invalidFieldValue('targetList', 'SelectStmt', 'expected at least one target'); - } - - $firstTarget = $targetList[0]; - $resTarget = $firstTarget->getResTarget(); - - if ($resTarget === null) { - throw InvalidAstException::unexpectedNodeType('ResTarget', 'unknown'); - } - - $val = $resTarget->getVal(); - - if ($val === null) { - throw InvalidAstException::missingRequiredField('val', 'ResTarget'); - } - - return $val; - } } diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Domain/CreateDomainFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Domain/CreateDomainFinalStep.php index 3c90306658..71f4e0ad2f 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Domain/CreateDomainFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Domain/CreateDomainFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Domain; use Flow\PostgreSql\Protobuf\AST\CreateDomainStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface CreateDomainFinalStep extends SqlQuery +interface CreateDomainFinalStep extends Sql { public function toAst() : CreateDomainStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Domain/CreateDomainOptionsStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Domain/CreateDomainOptionsStep.php index fd52519807..1b29b7b2df 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Domain/CreateDomainOptionsStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Domain/CreateDomainOptionsStep.php @@ -4,15 +4,18 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Domain; +use Flow\PostgreSql\QueryBuilder\Condition\Condition; +use Flow\PostgreSql\QueryBuilder\Expression\Expression; + interface CreateDomainOptionsStep extends CreateDomainFinalStep { - public function check(string $expression) : self; + public function check(Condition $condition) : self; public function collate(string $collation) : self; public function constraint(string $name) : self; - public function default(string $expression) : self; + public function default(Expression $expression) : self; public function notNull() : self; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Domain/CreateDomainTypeStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Domain/CreateDomainTypeStep.php index 882186b309..04d22a4262 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Domain/CreateDomainTypeStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Domain/CreateDomainTypeStep.php @@ -4,9 +4,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Domain; -use Flow\PostgreSql\QueryBuilder\Schema\DataType; +use Flow\PostgreSql\QueryBuilder\Schema\ColumnType; interface CreateDomainTypeStep { - public function as(DataType $dataType) : CreateDomainOptionsStep; + public function as(ColumnType $dataType) : CreateDomainOptionsStep; } diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Domain/DropDomainFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Domain/DropDomainFinalStep.php index 7d9bbcab0c..8f374a0c97 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Domain/DropDomainFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Domain/DropDomainFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Domain; use Flow\PostgreSql\Protobuf\AST\DropStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface DropDomainFinalStep extends SqlQuery +interface DropDomainFinalStep extends Sql { public function cascade() : self; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/DropSequence/DropSequenceFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/DropSequence/DropSequenceFinalStep.php index d6fb3b4f01..c6bf5e0b43 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/DropSequence/DropSequenceFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/DropSequence/DropSequenceFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\DropSequence; use Flow\PostgreSql\Protobuf\AST\DropStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface DropSequenceFinalStep extends SqlQuery +interface DropSequenceFinalStep extends Sql { public function cascade() : self; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/DropTable/DropTableFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/DropTable/DropTableFinalStep.php index 6afc6f0ad0..b5eb1d965d 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/DropTable/DropTableFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/DropTable/DropTableFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\DropTable; use Flow\PostgreSql\Protobuf\AST\DropStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface DropTableFinalStep extends SqlQuery +interface DropTableFinalStep extends Sql { public function cascade() : self; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Extension/AlterExtensionFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Extension/AlterExtensionFinalStep.php index e47931fdbd..90e25ca873 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Extension/AlterExtensionFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Extension/AlterExtensionFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Extension; use Flow\PostgreSql\Protobuf\AST\{AlterExtensionContentsStmt, AlterExtensionStmt}; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface AlterExtensionFinalStep extends SqlQuery +interface AlterExtensionFinalStep extends Sql { public function toAst() : AlterExtensionStmt|AlterExtensionContentsStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Extension/CreateExtensionFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Extension/CreateExtensionFinalStep.php index ec8b66c911..f9b7f94cae 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Extension/CreateExtensionFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Extension/CreateExtensionFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Extension; use Flow\PostgreSql\Protobuf\AST\CreateExtensionStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface CreateExtensionFinalStep extends SqlQuery +interface CreateExtensionFinalStep extends Sql { public function toAst() : CreateExtensionStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Extension/DropExtensionFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Extension/DropExtensionFinalStep.php index cb123c5151..d231eb3098 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Extension/DropExtensionFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Extension/DropExtensionFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Extension; use Flow\PostgreSql\Protobuf\AST\DropStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface DropExtensionFinalStep extends SqlQuery +interface DropExtensionFinalStep extends Sql { public function cascade() : self; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/AlterFunctionFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/AlterFunctionFinalStep.php index 540684a0c5..d02a23eb98 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/AlterFunctionFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/AlterFunctionFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Function; use Flow\PostgreSql\Protobuf\AST\{AlterFunctionStmt, RenameStmt}; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface AlterFunctionFinalStep extends SqlQuery +interface AlterFunctionFinalStep extends Sql { public function cost(int $cost) : self; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/AlterProcedureFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/AlterProcedureFinalStep.php index bb4a250c20..b09d74c119 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/AlterProcedureFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/AlterProcedureFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Function; use Flow\PostgreSql\Protobuf\AST\{AlterFunctionStmt, RenameStmt}; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface AlterProcedureFinalStep extends SqlQuery +interface AlterProcedureFinalStep extends Sql { public function renameTo(string $newName) : self; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/CallFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/CallFinalStep.php index a139604bf2..772b0b6c5d 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/CallFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/CallFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Function; use Flow\PostgreSql\Protobuf\AST\CallStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface CallFinalStep extends SqlQuery +interface CallFinalStep extends Sql { public function toAst() : CallStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/CreateFunctionBuilder.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/CreateFunctionBuilder.php index 89c178da3e..dcae50d78d 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/CreateFunctionBuilder.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/CreateFunctionBuilder.php @@ -5,8 +5,8 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Function; use Flow\PostgreSql\Protobuf\AST\{A_Const, CreateFunctionStmt, DefElem, FunctionParameter, FunctionParameterMode, Integer, Node, PBList, PBString}; -use Flow\PostgreSql\QueryBuilder\AstToSql; -use Flow\PostgreSql\QueryBuilder\Schema\DataType; +use Flow\PostgreSql\QueryBuilder\{AstToSql, QualifiedIdentifier}; +use Flow\PostgreSql\QueryBuilder\Schema\ColumnType; final readonly class CreateFunctionBuilder implements CreateFunctionArgsStep, CreateFunctionFinalStep, CreateFunctionOptionsStep, CreateFunctionReturnsStep { @@ -15,13 +15,14 @@ /** * @param list $arguments * @param list $options - * @param null|array $tableColumns + * @param null|array $tableColumns */ private function __construct( private string $name, + private ?string $schema = null, private bool $replace = false, private array $arguments = [], - private ?DataType $returnType = null, + private ?ColumnType $returnType = null, private bool $setof = false, private ?array $tableColumns = null, private array $options = [], @@ -30,13 +31,16 @@ private function __construct( public static function create(string $name) : CreateFunctionArgsStep { - return new self($name); + $identifier = QualifiedIdentifier::parse($name); + + return new self($identifier->name(), $identifier->schema()); } public function arguments(FunctionArgument ...$args) : CreateFunctionReturnsStep { return new self( $this->name, + $this->schema, $this->replace, \array_values($args), $this->returnType, @@ -80,6 +84,7 @@ public function orReplace() : CreateFunctionArgsStep { return new self( $this->name, + $this->schema, true, $this->arguments, $this->returnType, @@ -94,10 +99,11 @@ public function parallel(ParallelSafety $safety) : CreateFunctionOptionsStep return $this->withStringOption('parallel', $safety->value); } - public function returns(DataType $type) : CreateFunctionOptionsStep + public function returns(ColumnType $type) : CreateFunctionOptionsStep { return new self( $this->name, + $this->schema, $this->replace, $this->arguments, $type, @@ -107,10 +113,11 @@ public function returns(DataType $type) : CreateFunctionOptionsStep ); } - public function returnsSetOf(DataType $type) : CreateFunctionOptionsStep + public function returnsSetOf(ColumnType $type) : CreateFunctionOptionsStep { return new self( $this->name, + $this->schema, $this->replace, $this->arguments, $type, @@ -121,12 +128,13 @@ public function returnsSetOf(DataType $type) : CreateFunctionOptionsStep } /** - * @param array $columns + * @param array $columns */ public function returnsTable(array $columns) : CreateFunctionOptionsStep { return new self( $this->name, + $this->schema, $this->replace, $this->arguments, null, @@ -140,9 +148,10 @@ public function returnsVoid() : CreateFunctionOptionsStep { return new self( $this->name, + $this->schema, $this->replace, $this->arguments, - DataType::custom('void'), + ColumnType::custom('void'), false, null, $this->options, @@ -188,6 +197,7 @@ public function set(string $parameter, string $value) : CreateFunctionOptionsSte return new self( $this->name, + $this->schema, $this->replace, $this->arguments, $this->returnType, @@ -214,6 +224,15 @@ public function toAst() : CreateFunctionStmt $stmt->setReplace($this->replace); $funcnameNodes = []; + + if ($this->schema !== null) { + $str = new PBString(); + $str->setSval($this->schema); + $node = new Node(); + $node->setString($str); + $funcnameNodes[] = $node; + } + $str = new PBString(); $str->setSval($this->name); $node = new Node(); @@ -373,6 +392,7 @@ private function withOption(string $name, ?Node $arg) : self return new self( $this->name, + $this->schema, $this->replace, $this->arguments, $this->returnType, diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/CreateFunctionFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/CreateFunctionFinalStep.php index 46fcaa83bd..d9155a8ae1 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/CreateFunctionFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/CreateFunctionFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Function; use Flow\PostgreSql\Protobuf\AST\CreateFunctionStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface CreateFunctionFinalStep extends SqlQuery +interface CreateFunctionFinalStep extends Sql { public function toAst() : CreateFunctionStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/CreateFunctionReturnsStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/CreateFunctionReturnsStep.php index 07090157b8..7e6f0a5b6d 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/CreateFunctionReturnsStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/CreateFunctionReturnsStep.php @@ -4,16 +4,16 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Function; -use Flow\PostgreSql\QueryBuilder\Schema\DataType; +use Flow\PostgreSql\QueryBuilder\Schema\ColumnType; interface CreateFunctionReturnsStep { - public function returns(DataType $type) : CreateFunctionOptionsStep; + public function returns(ColumnType $type) : CreateFunctionOptionsStep; - public function returnsSetOf(DataType $type) : CreateFunctionOptionsStep; + public function returnsSetOf(ColumnType $type) : CreateFunctionOptionsStep; /** - * @param array $columns + * @param array $columns */ public function returnsTable(array $columns) : CreateFunctionOptionsStep; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/CreateProcedureBuilder.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/CreateProcedureBuilder.php index 512cc45643..f00477bb35 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/CreateProcedureBuilder.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/CreateProcedureBuilder.php @@ -6,7 +6,7 @@ use Flow\PostgreSql\Protobuf\AST\{A_Const, CreateFunctionStmt, DefElem, FunctionParameter, Node, PBList, PBString}; use Flow\PostgreSql\Protobuf\AST\Integer; -use Flow\PostgreSql\QueryBuilder\AstToSql; +use Flow\PostgreSql\QueryBuilder\{AstToSql, QualifiedIdentifier}; final readonly class CreateProcedureBuilder implements CreateProcedureArgsStep, CreateProcedureFinalStep, CreateProcedureOptionsStep { @@ -18,6 +18,7 @@ */ private function __construct( private string $name, + private ?string $schema = null, private bool $replace = false, private array $arguments = [], private array $options = [], @@ -26,13 +27,16 @@ private function __construct( public static function create(string $name) : CreateProcedureArgsStep { - return new self($name); + $identifier = QualifiedIdentifier::parse($name); + + return new self($identifier->name(), $identifier->schema()); } public function arguments(FunctionArgument ...$args) : CreateProcedureOptionsStep { return new self( $this->name, + $this->schema, $this->replace, \array_values($args), $this->options, @@ -53,6 +57,7 @@ public function orReplace() : CreateProcedureArgsStep { return new self( $this->name, + $this->schema, true, $this->arguments, $this->options, @@ -107,6 +112,7 @@ public function set(string $parameter, string $value) : CreateProcedureOptionsSt return new self( $this->name, + $this->schema, $this->replace, $this->arguments, $newOptions, @@ -120,6 +126,15 @@ public function toAst() : CreateFunctionStmt $stmt->setReplace($this->replace); $funcnameNodes = []; + + if ($this->schema !== null) { + $str = new PBString(); + $str->setSval($this->schema); + $node = new Node(); + $node->setString($str); + $funcnameNodes[] = $node; + } + $str = new PBString(); $str->setSval($this->name); $node = new Node(); @@ -216,6 +231,7 @@ private function withOption(string $name, ?Node $arg) : self return new self( $this->name, + $this->schema, $this->replace, $this->arguments, $newOptions, diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/CreateProcedureFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/CreateProcedureFinalStep.php index e7bb0821ab..dbecc0774c 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/CreateProcedureFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/CreateProcedureFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Function; use Flow\PostgreSql\Protobuf\AST\CreateFunctionStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface CreateProcedureFinalStep extends SqlQuery +interface CreateProcedureFinalStep extends Sql { public function toAst() : CreateFunctionStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/DoFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/DoFinalStep.php index faf1b525f3..f61f7f4fde 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/DoFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/DoFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Function; use Flow\PostgreSql\Protobuf\AST\DoStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface DoFinalStep extends SqlQuery +interface DoFinalStep extends Sql { public function language(string $language) : self; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/DropFunctionFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/DropFunctionFinalStep.php index 1e23e9b675..1feb8620f2 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/DropFunctionFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/DropFunctionFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Function; use Flow\PostgreSql\Protobuf\AST\DropStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface DropFunctionFinalStep extends SqlQuery +interface DropFunctionFinalStep extends Sql { public function arguments(FunctionArgument ...$args) : self; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/DropProcedureFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/DropProcedureFinalStep.php index b6d4870782..a557bda355 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/DropProcedureFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/DropProcedureFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Function; use Flow\PostgreSql\Protobuf\AST\DropStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface DropProcedureFinalStep extends SqlQuery +interface DropProcedureFinalStep extends Sql { public function arguments(FunctionArgument ...$args) : self; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/FunctionArgument.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/FunctionArgument.php index a1d1e4c6ad..418bb953a1 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/FunctionArgument.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/FunctionArgument.php @@ -4,19 +4,19 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Function; -use Flow\PostgreSql\QueryBuilder\Schema\DataType; +use Flow\PostgreSql\QueryBuilder\Schema\ColumnType; final readonly class FunctionArgument { private function __construct( - public DataType $type, + public ColumnType $type, public ?string $name = null, public ArgumentMode $mode = ArgumentMode::IN, public ?string $default = null, ) { } - public static function of(DataType $type) : self + public static function of(ColumnType $type) : self { return new self($type); } diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Grant/GrantFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Grant/GrantFinalStep.php index b3ad7bf5e0..f61448c999 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Grant/GrantFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Grant/GrantFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Grant; use Flow\PostgreSql\Protobuf\AST\GrantStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface GrantFinalStep extends SqlQuery +interface GrantFinalStep extends Sql { public function toAst() : GrantStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Grant/GrantRoleFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Grant/GrantRoleFinalStep.php index 74d0393855..3fa59e4442 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Grant/GrantRoleFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Grant/GrantRoleFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Grant; use Flow\PostgreSql\Protobuf\AST\GrantRoleStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface GrantRoleFinalStep extends SqlQuery +interface GrantRoleFinalStep extends Sql { public function toAst() : GrantRoleStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Grant/RevokeFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Grant/RevokeFinalStep.php index e2da84d594..d94ba79f13 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Grant/RevokeFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Grant/RevokeFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Grant; use Flow\PostgreSql\Protobuf\AST\GrantStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface RevokeFinalStep extends SqlQuery +interface RevokeFinalStep extends Sql { public function cascade() : self; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Grant/RevokeRoleFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Grant/RevokeRoleFinalStep.php index 2be0aea703..07095913f0 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Grant/RevokeRoleFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Grant/RevokeRoleFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Grant; use Flow\PostgreSql\Protobuf\AST\GrantRoleStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface RevokeRoleFinalStep extends SqlQuery +interface RevokeRoleFinalStep extends Sql { public function cascade() : self; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Index/AlterIndex/AlterTablespaceIndexFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Index/AlterIndex/AlterTablespaceIndexFinalStep.php index 3dba14fe11..4122a00303 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Index/AlterIndex/AlterTablespaceIndexFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Index/AlterIndex/AlterTablespaceIndexFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Index\AlterIndex; use Flow\PostgreSql\Protobuf\AST\AlterTableStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface AlterTablespaceIndexFinalStep extends SqlQuery +interface AlterTablespaceIndexFinalStep extends Sql { public function toAst() : AlterTableStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Index/AlterIndex/RenameIndexFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Index/AlterIndex/RenameIndexFinalStep.php index 0f0dec4410..e0029e6542 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Index/AlterIndex/RenameIndexFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Index/AlterIndex/RenameIndexFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Index\AlterIndex; use Flow\PostgreSql\Protobuf\AST\RenameStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface RenameIndexFinalStep extends SqlQuery +interface RenameIndexFinalStep extends Sql { public function toAst() : RenameStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Index/CreateIndex/CreateIndexBuilder.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Index/CreateIndex/CreateIndexBuilder.php index f1fbe28a4a..664ce42af4 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Index/CreateIndex/CreateIndexBuilder.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Index/CreateIndex/CreateIndexBuilder.php @@ -5,7 +5,7 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Index\CreateIndex; use Flow\PostgreSql\Protobuf\AST\{IndexElem, IndexStmt, Node, RangeVar}; -use Flow\PostgreSql\QueryBuilder\AstToSql; +use Flow\PostgreSql\QueryBuilder\{AstToSql, QualifiedIdentifier}; use Flow\PostgreSql\QueryBuilder\Condition\Condition; use Flow\PostgreSql\QueryBuilder\Schema\Index\{IndexColumn, IndexMethod}; @@ -165,6 +165,12 @@ public function nullsNotDistinct() : CreateIndexFinalStep public function on(string $table, ?string $schema = null) : CreateIndexColumnsStep { + if ($schema === null) { + $identifier = QualifiedIdentifier::parse($table); + $table = $identifier->name(); + $schema = $identifier->schema(); + } + return new self( $this->name, $table, @@ -184,6 +190,12 @@ public function on(string $table, ?string $schema = null) : CreateIndexColumnsSt public function onOnly(string $table, ?string $schema = null) : CreateIndexColumnsStep { + if ($schema === null) { + $identifier = QualifiedIdentifier::parse($table); + $table = $identifier->name(); + $schema = $identifier->schema(); + } + return new self( $this->name, $table, diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Index/CreateIndex/CreateIndexFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Index/CreateIndex/CreateIndexFinalStep.php index 489f8b4feb..6c5b4345b2 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Index/CreateIndex/CreateIndexFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Index/CreateIndex/CreateIndexFinalStep.php @@ -6,9 +6,9 @@ use Flow\PostgreSql\Protobuf\AST\IndexStmt; use Flow\PostgreSql\QueryBuilder\Condition\Condition; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface CreateIndexFinalStep extends SqlQuery +interface CreateIndexFinalStep extends Sql { public function include(string ...$columns) : self; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Index/DropIndex/DropIndexFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Index/DropIndex/DropIndexFinalStep.php index a2708e45c0..0b229c43a3 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Index/DropIndex/DropIndexFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Index/DropIndex/DropIndexFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Index\DropIndex; use Flow\PostgreSql\Protobuf\AST\DropStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface DropIndexFinalStep extends SqlQuery +interface DropIndexFinalStep extends Sql { public function cascade() : self; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Index/Reindex/ReindexFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Index/Reindex/ReindexFinalStep.php index bb757bd699..862dac0a8e 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Index/Reindex/ReindexFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Index/Reindex/ReindexFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Index\Reindex; use Flow\PostgreSql\Protobuf\AST\ReindexStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface ReindexFinalStep extends SqlQuery +interface ReindexFinalStep extends Sql { public function concurrently() : self; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Ownership/DropOwnedFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Ownership/DropOwnedFinalStep.php index b091cd532b..140e58cd95 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Ownership/DropOwnedFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Ownership/DropOwnedFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Ownership; use Flow\PostgreSql\Protobuf\AST\DropOwnedStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface DropOwnedFinalStep extends SqlQuery +interface DropOwnedFinalStep extends Sql { public function cascade() : self; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Ownership/ReassignOwnedFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Ownership/ReassignOwnedFinalStep.php index ffeb0fd62e..67e1b43b43 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Ownership/ReassignOwnedFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Ownership/ReassignOwnedFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Ownership; use Flow\PostgreSql\Protobuf\AST\ReassignOwnedStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface ReassignOwnedFinalStep extends SqlQuery +interface ReassignOwnedFinalStep extends Sql { public function toAst() : ReassignOwnedStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Role/AlterRoleFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Role/AlterRoleFinalStep.php index f0808e2565..6878eae547 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Role/AlterRoleFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Role/AlterRoleFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Role; use Flow\PostgreSql\Protobuf\AST\AlterRoleStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface AlterRoleFinalStep extends SqlQuery +interface AlterRoleFinalStep extends Sql { public function bypassRls() : self; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Role/AlterRoleRenameFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Role/AlterRoleRenameFinalStep.php index 3ab082be4d..283eba1ad9 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Role/AlterRoleRenameFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Role/AlterRoleRenameFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Role; use Flow\PostgreSql\Protobuf\AST\RenameStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface AlterRoleRenameFinalStep extends SqlQuery +interface AlterRoleRenameFinalStep extends Sql { public function toAst() : RenameStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Role/CreateRoleFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Role/CreateRoleFinalStep.php index d72197864e..92223e74b1 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Role/CreateRoleFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Role/CreateRoleFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Role; use Flow\PostgreSql\Protobuf\AST\CreateRoleStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface CreateRoleFinalStep extends SqlQuery +interface CreateRoleFinalStep extends Sql { public function toAst() : CreateRoleStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Role/DropRoleFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Role/DropRoleFinalStep.php index cbad212f6d..a5c9efafc1 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Role/DropRoleFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Role/DropRoleFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Role; use Flow\PostgreSql\Protobuf\AST\DropRoleStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface DropRoleFinalStep extends SqlQuery +interface DropRoleFinalStep extends Sql { public function ifExists() : self; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Rule/CreateRuleBuilder.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Rule/CreateRuleBuilder.php index c64c58dba8..e4e2eb9dcf 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Rule/CreateRuleBuilder.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Rule/CreateRuleBuilder.php @@ -7,6 +7,7 @@ use Flow\PostgreSql\Parser; use Flow\PostgreSql\Protobuf\AST\{Node, RangeVar, RuleStmt}; use Flow\PostgreSql\QueryBuilder\{AstToSql, QualifiedIdentifier}; +use Flow\PostgreSql\QueryBuilder\Condition\Condition; use Flow\PostgreSql\QueryBuilder\Exception\InvalidAstException; final readonly class CreateRuleBuilder implements CreateRuleDoStep, CreateRuleEventStep, CreateRuleFinalStep, CreateRuleToStep, CreateRuleWhereStep @@ -22,7 +23,7 @@ private function __construct( private ?RuleEvent $event = null, private ?string $table = null, private ?string $schema = null, - private ?string $whereCondition = null, + private ?Condition $whereCondition = null, private bool $instead = false, private array $actions = [], ) { @@ -189,7 +190,7 @@ public function toAst() : RuleStmt } if ($this->whereCondition !== null) { - $stmt->setWhereClause($this->parseCondition($this->whereCondition)); + $stmt->setWhereClause($this->whereCondition->toAst()); } $stmt->setInstead($this->instead); @@ -201,7 +202,7 @@ public function toAst() : RuleStmt return $stmt; } - public function where(string $condition) : CreateRuleDoStep + public function where(Condition $condition) : CreateRuleDoStep { return new self( $this->name, @@ -234,30 +235,4 @@ private function parseCommand(string $command) : Node return $stmt; } - - private function parseCondition(string $condition) : Node - { - $parser = new Parser(); - $parsed = $parser->parse("SELECT * FROM t WHERE {$condition}"); - - $stmts = $parsed->raw()->getStmts(); - - if ($stmts === null || \count($stmts) === 0) { - throw InvalidAstException::invalidFieldValue('stmts', 'ParseResult', 'expected at least one statement'); - } - - $selectStmt = $stmts[0]->getStmt()?->getSelectStmt(); - - if ($selectStmt === null) { - throw InvalidAstException::unexpectedNodeType('SelectStmt', 'unknown'); - } - - $whereClause = $selectStmt->getWhereClause(); - - if ($whereClause === null) { - throw InvalidAstException::missingRequiredField('whereClause', 'SelectStmt'); - } - - return $whereClause; - } } diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Rule/CreateRuleFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Rule/CreateRuleFinalStep.php index ba00c30f73..8e43d5daaf 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Rule/CreateRuleFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Rule/CreateRuleFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Rule; use Flow\PostgreSql\Protobuf\AST\RuleStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface CreateRuleFinalStep extends SqlQuery +interface CreateRuleFinalStep extends Sql { public function toAst() : RuleStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Rule/CreateRuleWhereStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Rule/CreateRuleWhereStep.php index 0a9dc67e43..d7670b09e7 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Rule/CreateRuleWhereStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Rule/CreateRuleWhereStep.php @@ -4,7 +4,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Rule; +use Flow\PostgreSql\QueryBuilder\Condition\Condition; + interface CreateRuleWhereStep extends CreateRuleDoStep { - public function where(string $condition) : CreateRuleDoStep; + public function where(Condition $condition) : CreateRuleDoStep; } diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Rule/DropRuleFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Rule/DropRuleFinalStep.php index 260dbbb59d..4517c95319 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Rule/DropRuleFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Rule/DropRuleFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Rule; use Flow\PostgreSql\Protobuf\AST\DropStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface DropRuleFinalStep extends SqlQuery +interface DropRuleFinalStep extends Sql { public function cascade() : self; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Schema/AlterSchemaOwnerFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Schema/AlterSchemaOwnerFinalStep.php index 93d62fbf1e..9c3a77eee0 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Schema/AlterSchemaOwnerFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Schema/AlterSchemaOwnerFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Schema; use Flow\PostgreSql\Protobuf\AST\AlterOwnerStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface AlterSchemaOwnerFinalStep extends SqlQuery +interface AlterSchemaOwnerFinalStep extends Sql { public function toAst() : AlterOwnerStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Schema/AlterSchemaRenameFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Schema/AlterSchemaRenameFinalStep.php index 5fda1e04aa..3483eef962 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Schema/AlterSchemaRenameFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Schema/AlterSchemaRenameFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Schema; use Flow\PostgreSql\Protobuf\AST\RenameStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface AlterSchemaRenameFinalStep extends SqlQuery +interface AlterSchemaRenameFinalStep extends Sql { public function toAst() : RenameStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Schema/CreateSchemaFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Schema/CreateSchemaFinalStep.php index e028ea57e3..dc40634ce6 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Schema/CreateSchemaFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Schema/CreateSchemaFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Schema; use Flow\PostgreSql\Protobuf\AST\CreateSchemaStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface CreateSchemaFinalStep extends SqlQuery +interface CreateSchemaFinalStep extends Sql { public function toAst() : CreateSchemaStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Schema/DropSchemaFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Schema/DropSchemaFinalStep.php index e4187cb9c7..76c1fcf626 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Schema/DropSchemaFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Schema/DropSchemaFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Schema; use Flow\PostgreSql\Protobuf\AST\DropStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface DropSchemaFinalStep extends SqlQuery +interface DropSchemaFinalStep extends Sql { public function cascade() : self; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Session/ResetRoleFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Session/ResetRoleFinalStep.php index f7fd1f9759..5a42145b50 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Session/ResetRoleFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Session/ResetRoleFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Session; use Flow\PostgreSql\Protobuf\AST\VariableSetStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface ResetRoleFinalStep extends SqlQuery +interface ResetRoleFinalStep extends Sql { public function toAst() : VariableSetStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Session/SetRoleFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Session/SetRoleFinalStep.php index 49dae37bdf..f6edaf3b42 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Session/SetRoleFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Session/SetRoleFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Session; use Flow\PostgreSql\Protobuf\AST\VariableSetStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface SetRoleFinalStep extends SqlQuery +interface SetRoleFinalStep extends Sql { public function toAst() : VariableSetStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Trigger/AlterTriggerFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Trigger/AlterTriggerFinalStep.php index 7eca58996d..2f29d11b92 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Trigger/AlterTriggerFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Trigger/AlterTriggerFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Trigger; use Flow\PostgreSql\Protobuf\AST\{AlterObjectDependsStmt, RenameStmt}; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface AlterTriggerFinalStep extends SqlQuery +interface AlterTriggerFinalStep extends Sql { public function toAst() : RenameStmt|AlterObjectDependsStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Trigger/CreateTriggerFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Trigger/CreateTriggerFinalStep.php index 8369c31f9d..a5207d903e 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Trigger/CreateTriggerFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Trigger/CreateTriggerFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Trigger; use Flow\PostgreSql\Protobuf\AST\CreateTrigStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface CreateTriggerFinalStep extends SqlQuery +interface CreateTriggerFinalStep extends Sql { public function toAst() : CreateTrigStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Trigger/DropTriggerFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Trigger/DropTriggerFinalStep.php index 19a44c9bf7..aa085654a8 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Trigger/DropTriggerFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Trigger/DropTriggerFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Trigger; use Flow\PostgreSql\Protobuf\AST\DropStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface DropTriggerFinalStep extends SqlQuery +interface DropTriggerFinalStep extends Sql { public function cascade() : self; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Truncate/TruncateFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Truncate/TruncateFinalStep.php index 700d7e1923..317984857b 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Truncate/TruncateFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Truncate/TruncateFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Truncate; use Flow\PostgreSql\Protobuf\AST\TruncateStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface TruncateFinalStep extends SqlQuery +interface TruncateFinalStep extends Sql { public function cascade() : self; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Type/AlterEnumTypeFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Type/AlterEnumTypeFinalStep.php index ea2d0eb504..e37ea5d616 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Type/AlterEnumTypeFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Type/AlterEnumTypeFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Type; use Flow\PostgreSql\Protobuf\AST\AlterEnumStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface AlterEnumTypeFinalStep extends SqlQuery +interface AlterEnumTypeFinalStep extends Sql { public function ifNotExists() : self; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Type/CreateCompositeTypeFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Type/CreateCompositeTypeFinalStep.php index 769b2afeb6..769ee6e8f0 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Type/CreateCompositeTypeFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Type/CreateCompositeTypeFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Type; use Flow\PostgreSql\Protobuf\AST\CompositeTypeStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface CreateCompositeTypeFinalStep extends SqlQuery +interface CreateCompositeTypeFinalStep extends Sql { public function toAst() : CompositeTypeStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Type/CreateEnumTypeFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Type/CreateEnumTypeFinalStep.php index 1052947185..856984ab86 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Type/CreateEnumTypeFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Type/CreateEnumTypeFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Type; use Flow\PostgreSql\Protobuf\AST\CreateEnumStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface CreateEnumTypeFinalStep extends SqlQuery +interface CreateEnumTypeFinalStep extends Sql { public function toAst() : CreateEnumStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Type/CreateRangeTypeFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Type/CreateRangeTypeFinalStep.php index 0ed38a45a2..bf76cd2d34 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Type/CreateRangeTypeFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Type/CreateRangeTypeFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Type; use Flow\PostgreSql\Protobuf\AST\CreateRangeStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface CreateRangeTypeFinalStep extends SqlQuery +interface CreateRangeTypeFinalStep extends Sql { public function toAst() : CreateRangeStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Type/DropTypeFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Type/DropTypeFinalStep.php index e6dfebcde8..b8aba0411f 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Type/DropTypeFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Type/DropTypeFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Type; use Flow\PostgreSql\Protobuf\AST\DropStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface DropTypeFinalStep extends SqlQuery +interface DropTypeFinalStep extends Sql { public function cascade() : self; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Type/TypeAttribute.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Type/TypeAttribute.php index c1a6810b45..bc00a3acb0 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Type/TypeAttribute.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Type/TypeAttribute.php @@ -4,18 +4,18 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\Type; -use Flow\PostgreSql\QueryBuilder\Schema\DataType; +use Flow\PostgreSql\QueryBuilder\Schema\ColumnType; final readonly class TypeAttribute { public function __construct( public string $name, - public DataType $type, + public ColumnType $type, public ?string $collation = null, ) { } - public static function of(string $name, DataType $type) : self + public static function of(string $name, ColumnType $type) : self { return new self($name, $type); } diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterMaterializedView/AlterMatViewOwnerFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterMaterializedView/AlterMatViewOwnerFinalStep.php index 5b62f04630..6cad03bbc2 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterMaterializedView/AlterMatViewOwnerFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterMaterializedView/AlterMatViewOwnerFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\View\AlterMaterializedView; use Flow\PostgreSql\Protobuf\AST\AlterTableStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface AlterMatViewOwnerFinalStep extends SqlQuery +interface AlterMatViewOwnerFinalStep extends Sql { public function toAst() : AlterTableStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterMaterializedView/AlterMatViewSchemaFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterMaterializedView/AlterMatViewSchemaFinalStep.php index 8bcef1d8e2..bbb622c484 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterMaterializedView/AlterMatViewSchemaFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterMaterializedView/AlterMatViewSchemaFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\View\AlterMaterializedView; use Flow\PostgreSql\Protobuf\AST\AlterObjectSchemaStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface AlterMatViewSchemaFinalStep extends SqlQuery +interface AlterMatViewSchemaFinalStep extends Sql { public function toAst() : AlterObjectSchemaStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterMaterializedView/AlterMatViewTablespaceFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterMaterializedView/AlterMatViewTablespaceFinalStep.php index cae4f43929..f85a42cdf6 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterMaterializedView/AlterMatViewTablespaceFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterMaterializedView/AlterMatViewTablespaceFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\View\AlterMaterializedView; use Flow\PostgreSql\Protobuf\AST\AlterTableStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface AlterMatViewTablespaceFinalStep extends SqlQuery +interface AlterMatViewTablespaceFinalStep extends Sql { public function toAst() : AlterTableStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterMaterializedView/RenameMatViewFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterMaterializedView/RenameMatViewFinalStep.php index 8b05282e63..a343ce72d5 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterMaterializedView/RenameMatViewFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterMaterializedView/RenameMatViewFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\View\AlterMaterializedView; use Flow\PostgreSql\Protobuf\AST\RenameStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface RenameMatViewFinalStep extends SqlQuery +interface RenameMatViewFinalStep extends Sql { public function toAst() : RenameStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterView/AlterViewOwnerFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterView/AlterViewOwnerFinalStep.php index 81d8d72f0e..0fde569fd9 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterView/AlterViewOwnerFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterView/AlterViewOwnerFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\View\AlterView; use Flow\PostgreSql\Protobuf\AST\AlterTableStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface AlterViewOwnerFinalStep extends SqlQuery +interface AlterViewOwnerFinalStep extends Sql { public function toAst() : AlterTableStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterView/AlterViewSchemaFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterView/AlterViewSchemaFinalStep.php index 6a6bfb5075..75baccb2d5 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterView/AlterViewSchemaFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterView/AlterViewSchemaFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\View\AlterView; use Flow\PostgreSql\Protobuf\AST\AlterObjectSchemaStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface AlterViewSchemaFinalStep extends SqlQuery +interface AlterViewSchemaFinalStep extends Sql { public function toAst() : AlterObjectSchemaStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterView/RenameViewFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterView/RenameViewFinalStep.php index 595ffe99ab..cbd166f9d6 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterView/RenameViewFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterView/RenameViewFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\View\AlterView; use Flow\PostgreSql\Protobuf\AST\RenameStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface RenameViewFinalStep extends SqlQuery +interface RenameViewFinalStep extends Sql { public function toAst() : RenameStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/CreateMaterializedView/CreateMatViewFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/CreateMaterializedView/CreateMatViewFinalStep.php index a6c9856118..4449260081 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/CreateMaterializedView/CreateMatViewFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/CreateMaterializedView/CreateMatViewFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\View\CreateMaterializedView; use Flow\PostgreSql\Protobuf\AST\CreateTableAsStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface CreateMatViewFinalStep extends SqlQuery +interface CreateMatViewFinalStep extends Sql { public function toAst() : CreateTableAsStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/CreateView/CreateViewFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/CreateView/CreateViewFinalStep.php index 12a8b1774a..fdc05c7cc1 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/CreateView/CreateViewFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/CreateView/CreateViewFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\View\CreateView; use Flow\PostgreSql\Protobuf\AST\ViewStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface CreateViewFinalStep extends SqlQuery +interface CreateViewFinalStep extends Sql { public function toAst() : ViewStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/DropMaterializedView/DropMatViewFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/DropMaterializedView/DropMatViewFinalStep.php index b4d51b750d..bc06f05d6b 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/DropMaterializedView/DropMatViewFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/DropMaterializedView/DropMatViewFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\View\DropMaterializedView; use Flow\PostgreSql\Protobuf\AST\DropStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface DropMatViewFinalStep extends SqlQuery +interface DropMatViewFinalStep extends Sql { public function cascade() : self; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/DropView/DropViewFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/DropView/DropViewFinalStep.php index 4f84d6e26b..1cd834234e 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/DropView/DropViewFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/DropView/DropViewFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\View\DropView; use Flow\PostgreSql\Protobuf\AST\DropStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface DropViewFinalStep extends SqlQuery +interface DropViewFinalStep extends Sql { public function cascade() : self; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/RefreshMaterializedView/RefreshMatViewFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/RefreshMaterializedView/RefreshMatViewFinalStep.php index f30b231f44..a483ef9587 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/RefreshMaterializedView/RefreshMatViewFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/RefreshMaterializedView/RefreshMatViewFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Schema\View\RefreshMaterializedView; use Flow\PostgreSql\Protobuf\AST\RefreshMatViewStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface RefreshMatViewFinalStep extends SqlQuery +interface RefreshMatViewFinalStep extends Sql { public function toAst() : RefreshMatViewStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Select/ParsedSelect.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Select/ParsedSelect.php new file mode 100644 index 0000000000..42f23b85f7 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Select/ParsedSelect.php @@ -0,0 +1,50 @@ +parse($sql); + + $stmt = $parsed->raw()->getStmts()[0]->getStmt(); + + if ($stmt === null) { + throw new \RuntimeException(\sprintf('Failed to parse SQL: "%s".', $sql)); + } + + $selectStmt = $stmt->getSelectStmt(); + + if ($selectStmt === null) { + throw new \RuntimeException(\sprintf('Expected SELECT statement, got: "%s".', $sql)); + } + + $this->ast = $selectStmt; + } + + public function toAst() : SelectStmt + { + return $this->ast; + } + + public function toSql() : string + { + $node = new Node(); + $node->setSelectStmt($this->ast); + + $rawStmt = new RawStmt(['stmt' => $node]); + $parseResult = new ParseResult(); + $parseResult->setStmts([$rawStmt]); + + return (new ParsedQuery($parseResult))->deparse(); + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Select/SelectBuilder.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Select/SelectBuilder.php index 5cf7c90f7a..dad4a1edb0 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Select/SelectBuilder.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Select/SelectBuilder.php @@ -5,11 +5,11 @@ namespace Flow\PostgreSql\QueryBuilder\Select; use Flow\PostgreSql\Protobuf\AST\{LimitOption, Node, ResTarget, SelectStmt as ProtobufSelectStmt}; -use Flow\PostgreSql\QueryBuilder\AstToSql; +use Flow\PostgreSql\QueryBuilder\{AstToSql, QualifiedIdentifier}; use Flow\PostgreSql\QueryBuilder\Clause\{LockingClause, OrderBy, WindowDefinition, WithClause}; use Flow\PostgreSql\QueryBuilder\Condition\{Condition, ConditionBuilder, ConditionFactory}; use Flow\PostgreSql\QueryBuilder\Exception\{InvalidAstException, InvalidBuilderStateException}; -use Flow\PostgreSql\QueryBuilder\Expression\{AliasedExpression, Expression, ExpressionFactory, Literal}; +use Flow\PostgreSql\QueryBuilder\Expression\{AliasedExpression, Column, Expression, ExpressionFactory, Literal}; use Flow\PostgreSql\QueryBuilder\Table\{AliasedTable, DerivedTable, JoinType, JoinedTable, Table, TableFunction, TableReference}; final readonly class SelectBuilder implements SelectFromStep, SelectJoinStep, SelectSelectStep @@ -221,8 +221,13 @@ public static function with(WithClause $with) : SelectSelectStep return new self(with: $with); } - public function crossJoin(TableReference $table) : SelectJoinStep + public function crossJoin(string|TableReference $table) : SelectJoinStep { + if (\is_string($table)) { + $id = QualifiedIdentifier::parse($table); + $table = new Table($id->name(), $id->schema()); + } + $join = new JoinedTable( left: $this->from[\count($this->from) - 1], right: $table, @@ -381,8 +386,20 @@ public function forUpdate(string ...$tables) : SelectFinalStep ); } - public function from(TableReference ...$tables) : SelectJoinStep + public function from(string|TableReference ...$tables) : SelectJoinStep { + $tables = \array_map( + static function (string|TableReference $t) : TableReference { + if ($t instanceof TableReference) { + return $t; + } + $id = QualifiedIdentifier::parse($t); + + return new Table($id->name(), $id->schema()); + }, + $tables, + ); + return new self( with: $this->with, selectList: $this->selectList, @@ -402,8 +419,13 @@ public function from(TableReference ...$tables) : SelectJoinStep ); } - public function fullJoin(TableReference $table, Condition $on) : SelectJoinStep + public function fullJoin(string|TableReference $table, Condition $on) : SelectJoinStep { + if (\is_string($table)) { + $id = QualifiedIdentifier::parse($table); + $table = new Table($id->name(), $id->schema()); + } + $join = new JoinedTable( left: $this->from[\count($this->from) - 1], right: $table, @@ -431,8 +453,13 @@ public function fullJoin(TableReference $table, Condition $on) : SelectJoinStep ); } - public function groupBy(Expression ...$expressions) : SelectHavingStep + public function groupBy(string|Expression ...$expressions) : SelectHavingStep { + $expressions = \array_map( + static fn (string|Expression $e) : Expression => $e instanceof Expression ? $e : Column::fromParts(QualifiedIdentifier::parse($e)->parts()), + $expressions, + ); + return new self( with: $this->with, selectList: $this->selectList, @@ -511,8 +538,13 @@ public function intersectAll(SelectFinalStep $other) : SelectOrderByStep ); } - public function join(TableReference $table, Condition $on) : SelectJoinStep + public function join(string|TableReference $table, Condition $on) : SelectJoinStep { + if (\is_string($table)) { + $id = QualifiedIdentifier::parse($table); + $table = new Table($id->name(), $id->schema()); + } + $join = new JoinedTable( left: $this->from[\count($this->from) - 1], right: $table, @@ -540,8 +572,13 @@ public function join(TableReference $table, Condition $on) : SelectJoinStep ); } - public function leftJoin(TableReference $table, Condition $on) : SelectJoinStep + public function leftJoin(string|TableReference $table, Condition $on) : SelectJoinStep { + if (\is_string($table)) { + $id = QualifiedIdentifier::parse($table); + $table = new Table($id->name(), $id->schema()); + } + $join = new JoinedTable( left: $this->from[\count($this->from) - 1], right: $table, @@ -635,8 +672,13 @@ public function orderBy(OrderBy ...$items) : SelectLimitStep ); } - public function rightJoin(TableReference $table, Condition $on) : SelectJoinStep + public function rightJoin(string|TableReference $table, Condition $on) : SelectJoinStep { + if (\is_string($table)) { + $id = QualifiedIdentifier::parse($table); + $table = new Table($id->name(), $id->schema()); + } + $join = new JoinedTable( left: $this->from[\count($this->from) - 1], right: $table, @@ -664,8 +706,13 @@ public function rightJoin(TableReference $table, Condition $on) : SelectJoinStep ); } - public function select(Expression ...$expressions) : self + public function select(string|Expression ...$expressions) : self { + $expressions = \array_map( + static fn (string|Expression $e) : Expression => $e instanceof Expression ? $e : Column::fromParts(QualifiedIdentifier::parse($e)->parts()), + $expressions, + ); + return new self( with: $this->with, selectList: $expressions, @@ -685,8 +732,13 @@ public function select(Expression ...$expressions) : self ); } - public function selectDistinct(Expression ...$expressions) : SelectFromStep + public function selectDistinct(string|Expression ...$expressions) : SelectFromStep { + $expressions = \array_map( + static fn (string|Expression $e) : Expression => $e instanceof Expression ? $e : Column::fromParts(QualifiedIdentifier::parse($e)->parts()), + $expressions, + ); + return new self( with: $this->with, selectList: $expressions, @@ -706,13 +758,15 @@ public function selectDistinct(Expression ...$expressions) : SelectFromStep ); } - public function selectDistinctOn(array $distinctExpressions, Expression ...$selectExpressions) : SelectFromStep + public function selectDistinctOn(array $distinctExpressions, string|Expression ...$selectExpressions) : SelectFromStep { + $coerce = static fn (string|Expression $e) : Expression => $e instanceof Expression ? $e : Column::fromParts(QualifiedIdentifier::parse($e)->parts()); + return new self( with: $this->with, - selectList: $selectExpressions, + selectList: \array_map($coerce, $selectExpressions), distinct: true, - distinctOn: $distinctExpressions, + distinctOn: \array_map($coerce, $distinctExpressions), from: $this->from, joins: $this->joins, where: $this->where, diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Select/SelectFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Select/SelectFinalStep.php index cbdb84b7c3..76bab6c5c1 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Select/SelectFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Select/SelectFinalStep.php @@ -5,13 +5,13 @@ namespace Flow\PostgreSql\QueryBuilder\Select; use Flow\PostgreSql\Protobuf\AST\SelectStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; /** * Terminal interface for SELECT query builder. * Represents a complete SELECT statement that can be converted to AST. */ -interface SelectFinalStep extends SqlQuery +interface SelectFinalStep extends Sql { /** * Convert this SELECT query to a protobuf AST SelectStmt. diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Select/SelectFromStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Select/SelectFromStep.php index 732de358ec..b727152d2b 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Select/SelectFromStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Select/SelectFromStep.php @@ -8,5 +8,5 @@ interface SelectFromStep extends SelectFinalStep { - public function from(TableReference ...$tables) : SelectJoinStep; + public function from(string|TableReference ...$tables) : SelectJoinStep; } diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Select/SelectGroupByStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Select/SelectGroupByStep.php index d9731fbb31..43f4a6ff39 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Select/SelectGroupByStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Select/SelectGroupByStep.php @@ -8,5 +8,5 @@ interface SelectGroupByStep extends SelectHavingStep { - public function groupBy(Expression ...$expressions) : SelectHavingStep; + public function groupBy(string|Expression ...$expressions) : SelectHavingStep; } diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Select/SelectJoinStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Select/SelectJoinStep.php index f5ce52e6e6..04eaed5fff 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Select/SelectJoinStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Select/SelectJoinStep.php @@ -9,13 +9,13 @@ interface SelectJoinStep extends SelectWhereStep { - public function crossJoin(TableReference $table) : self; + public function crossJoin(string|TableReference $table) : self; - public function fullJoin(TableReference $table, Condition $on) : self; + public function fullJoin(string|TableReference $table, Condition $on) : self; - public function join(TableReference $table, Condition $on) : self; + public function join(string|TableReference $table, Condition $on) : self; - public function leftJoin(TableReference $table, Condition $on) : self; + public function leftJoin(string|TableReference $table, Condition $on) : self; - public function rightJoin(TableReference $table, Condition $on) : self; + public function rightJoin(string|TableReference $table, Condition $on) : self; } diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Select/SelectSelectStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Select/SelectSelectStep.php index 17453fecaa..11b0b77c2e 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Select/SelectSelectStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Select/SelectSelectStep.php @@ -9,18 +9,18 @@ interface SelectSelectStep { /** - * @param Expression ...$expressions + * @param Expression|string ...$expressions */ - public function select(Expression ...$expressions) : SelectFromStep; + public function select(string|Expression ...$expressions) : SelectFromStep; /** - * @param Expression ...$expressions + * @param Expression|string ...$expressions */ - public function selectDistinct(Expression ...$expressions) : SelectFromStep; + public function selectDistinct(string|Expression ...$expressions) : SelectFromStep; /** - * @param array $distinctExpressions - * @param Expression ...$selectExpressions + * @param array $distinctExpressions + * @param Expression|string ...$selectExpressions */ - public function selectDistinctOn(array $distinctExpressions, Expression ...$selectExpressions) : SelectFromStep; + public function selectDistinctOn(array $distinctExpressions, string|Expression ...$selectExpressions) : SelectFromStep; } diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/SqlQuery.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Sql.php similarity index 95% rename from src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/SqlQuery.php rename to src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Sql.php index b037411e5f..efcc1fc238 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/SqlQuery.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Sql.php @@ -10,7 +10,7 @@ * Implemented by all query builder final step interfaces. * Allows the Client to accept both raw SQL strings and query builder objects. */ -interface SqlQuery +interface Sql { /** * Convert this query to a SQL string. diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/BeginFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/BeginFinalStep.php index 6477208cd6..161435918b 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/BeginFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/BeginFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Transaction; use Flow\PostgreSql\Protobuf\AST\TransactionStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface BeginFinalStep extends SqlQuery +interface BeginFinalStep extends Sql { public function toAst() : TransactionStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/CommitFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/CommitFinalStep.php index 5a8909c16e..7b3222626f 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/CommitFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/CommitFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Transaction; use Flow\PostgreSql\Protobuf\AST\TransactionStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface CommitFinalStep extends SqlQuery +interface CommitFinalStep extends Sql { public function toAst() : TransactionStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/PreparedTransactionFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/PreparedTransactionFinalStep.php index 4dbe7096e6..2b98aa97cd 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/PreparedTransactionFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/PreparedTransactionFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Transaction; use Flow\PostgreSql\Protobuf\AST\TransactionStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface PreparedTransactionFinalStep extends SqlQuery +interface PreparedTransactionFinalStep extends Sql { public function toAst() : TransactionStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/RollbackFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/RollbackFinalStep.php index a8354d8933..cf68a0a1ed 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/RollbackFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/RollbackFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Transaction; use Flow\PostgreSql\Protobuf\AST\TransactionStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface RollbackFinalStep extends SqlQuery +interface RollbackFinalStep extends Sql { public function toAst() : TransactionStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/SavepointFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/SavepointFinalStep.php index f2d9cbbccd..5defe1b3c4 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/SavepointFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/SavepointFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Transaction; use Flow\PostgreSql\Protobuf\AST\TransactionStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface SavepointFinalStep extends SqlQuery +interface SavepointFinalStep extends Sql { public function toAst() : TransactionStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/SetTransactionFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/SetTransactionFinalStep.php index 5bd4c666d8..e52ea29828 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/SetTransactionFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/SetTransactionFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Transaction; use Flow\PostgreSql\Protobuf\AST\VariableSetStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface SetTransactionFinalStep extends SqlQuery +interface SetTransactionFinalStep extends Sql { public function toAst() : VariableSetStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Update/UpdateBuilder.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Update/UpdateBuilder.php index a5c3a2fb9d..e9642f4c69 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Update/UpdateBuilder.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Update/UpdateBuilder.php @@ -142,8 +142,20 @@ public static function with(WithClause $with) : UpdateTableStep return new self(with: $with); } - public function from(TableReference ...$tables) : UpdateWhereStep + public function from(string|TableReference ...$tables) : UpdateWhereStep { + $tables = \array_map( + static function (string|TableReference $t) : TableReference { + if ($t instanceof TableReference) { + return $t; + } + $id = QualifiedIdentifier::parse($t); + + return new Table($id->name(), $id->schema()); + }, + $tables, + ); + return new self( with: $this->with, table: $this->table, diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Update/UpdateFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Update/UpdateFinalStep.php index 2ed29fa0f0..6001736d9c 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Update/UpdateFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Update/UpdateFinalStep.php @@ -5,12 +5,12 @@ namespace Flow\PostgreSql\QueryBuilder\Update; use Flow\PostgreSql\Protobuf\AST\UpdateStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; /** * Terminal interface for UPDATE query builder. */ -interface UpdateFinalStep extends SqlQuery +interface UpdateFinalStep extends Sql { /** * Convert this UPDATE query to protobuf AST. diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Update/UpdateFromStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Update/UpdateFromStep.php index 4f0633a42a..0c60837b3f 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Update/UpdateFromStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Update/UpdateFromStep.php @@ -16,5 +16,5 @@ interface UpdateFromStep extends UpdateWhereStep * * @param TableReference ...$tables Tables to reference in FROM clause */ - public function from(TableReference ...$tables) : UpdateWhereStep; + public function from(string|TableReference ...$tables) : UpdateWhereStep; } diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/AnalyzeFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/AnalyzeFinalStep.php index 8603fa4b98..e844e4f7d9 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/AnalyzeFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/AnalyzeFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Utility; use Flow\PostgreSql\Protobuf\AST\VacuumStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface AnalyzeFinalStep extends SqlQuery +interface AnalyzeFinalStep extends Sql { public function skipLocked() : self; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/ClusterFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/ClusterFinalStep.php index 95638c3020..8ed2a4a4c7 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/ClusterFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/ClusterFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Utility; use Flow\PostgreSql\Protobuf\AST\ClusterStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface ClusterFinalStep extends SqlQuery +interface ClusterFinalStep extends Sql { public function table(string $table) : self; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/CommentFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/CommentFinalStep.php index 3dd38bc808..3dcbc754be 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/CommentFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/CommentFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Utility; use Flow\PostgreSql\Protobuf\AST\CommentStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface CommentFinalStep extends SqlQuery +interface CommentFinalStep extends Sql { public function is(string $comment) : self; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/DiscardFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/DiscardFinalStep.php index 7b72557171..a69061ae90 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/DiscardFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/DiscardFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Utility; use Flow\PostgreSql\Protobuf\AST\DiscardStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface DiscardFinalStep extends SqlQuery +interface DiscardFinalStep extends Sql { public function toAst() : DiscardStmt; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/ExplainFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/ExplainFinalStep.php index aa8fdb0c93..96f45deede 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/ExplainFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/ExplainFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Utility; use Flow\PostgreSql\Protobuf\AST\ExplainStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface ExplainFinalStep extends SqlQuery +interface ExplainFinalStep extends Sql { public function analyze() : self; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/LockFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/LockFinalStep.php index a9564f8358..24cbbf20f3 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/LockFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/LockFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Utility; use Flow\PostgreSql\Protobuf\AST\LockStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface LockFinalStep extends SqlQuery +interface LockFinalStep extends Sql { public function accessExclusive() : self; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/VacuumFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/VacuumFinalStep.php index 7ba072a90c..35471f6b57 100644 --- a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/VacuumFinalStep.php +++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/VacuumFinalStep.php @@ -5,9 +5,9 @@ namespace Flow\PostgreSql\QueryBuilder\Utility; use Flow\PostgreSql\Protobuf\AST\VacuumStmt; -use Flow\PostgreSql\QueryBuilder\SqlQuery; +use Flow\PostgreSql\QueryBuilder\Sql; -interface VacuumFinalStep extends SqlQuery +interface VacuumFinalStep extends Sql { public function analyze() : self; diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Catalog.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Catalog.php new file mode 100644 index 0000000000..1dfa89ea9f --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Catalog.php @@ -0,0 +1,107 @@ +} + */ +final readonly class Catalog +{ + /** + * @param list $schemas + */ + public function __construct( + private array $schemas, + ) { + } + + /** + * @param CatalogShape $data + */ + public static function fromArray(array $data) : self + { + return new self( + schemas: \array_map( + static fn (array $s) : Schema => Schema::fromArray($s), + $data['schemas'], + ), + ); + } + + /** + * @return list + */ + public function all() : array + { + return $this->schemas; + } + + public function get(string $name) : Schema + { + foreach ($this->schemas as $schema) { + if ($schema->name === $name) { + return $schema; + } + } + + throw new SchemaException(\sprintf('Schema "%s" not found in catalog.', $name)); + } + + public function has(string $name) : bool + { + foreach ($this->schemas as $schema) { + if ($schema->name === $name) { + return true; + } + } + + return false; + } + + public function merge(self $other) : self + { + $schemas = []; + + foreach ($this->schemas as $schema) { + $schemas[$schema->name] = $schema; + } + + foreach ($other->schemas as $schema) { + $schemas[$schema->name] = \array_key_exists($schema->name, $schemas) + ? $schemas[$schema->name]->merge($schema) + : $schema; + } + + return new self(\array_values($schemas)); + } + + /** + * @return list + */ + public function names() : array + { + return \array_map( + static fn (Schema $s) : string => $s->name, + $this->schemas, + ); + } + + /** + * @return CatalogShape + */ + public function normalize() : array + { + return [ + 'schemas' => \array_map( + static fn (Schema $s) : array => $s->normalize(), + $this->schemas, + ), + ]; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/CatalogProvider.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/CatalogProvider.php new file mode 100644 index 0000000000..dbaf1c8a1b --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/CatalogProvider.php @@ -0,0 +1,10 @@ + + */ + private array $providers; + + public function __construct(CatalogProvider ...$providers) + { + $this->providers = \array_values($providers); + } + + public function get() : Catalog + { + $catalog = new Catalog([]); + + foreach ($this->providers as $provider) { + $catalog = $catalog->merge($provider->get()); + } + + return $catalog; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Column.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Column.php new file mode 100644 index 0000000000..6b9b8abb91 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Column.php @@ -0,0 +1,80 @@ +name === $other->name && $this->isEqualStructure($other); + } + + public function isEqualStructure(self $other) : bool + { + return $this->type->isEqual($other->type) + && $this->nullable === $other->nullable + && $this->default === $other->default + && $this->isIdentity === $other->isIdentity + && $this->identityGeneration === $other->identityGeneration + && $this->isGenerated === $other->isGenerated + && $this->generationExpression === $other->generationExpression; + } + + /** + * @return ColumnShape + */ + public function normalize() : array + { + return [ + 'name' => $this->name, + 'type' => $this->type->normalize(), + 'nullable' => $this->nullable, + 'default' => $this->default, + 'is_identity' => $this->isIdentity, + 'identity_generation' => $this->identityGeneration?->value, + 'is_generated' => $this->isGenerated, + 'generation_expression' => $this->generationExpression, + 'ordinal_position' => $this->ordinalPosition, + ]; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Constraint/CheckConstraint.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Constraint/CheckConstraint.php new file mode 100644 index 0000000000..4a20112948 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Constraint/CheckConstraint.php @@ -0,0 +1,53 @@ +name === $other->name && $this->isEqualStructure($other); + } + + public function isEqualStructure(self $other) : bool + { + return $this->expression === $other->expression + && $this->noInherit === $other->noInherit; + } + + /** + * @return CheckConstraintShape + */ + public function normalize() : array + { + return [ + 'expression' => $this->expression, + 'name' => $this->name, + 'no_inherit' => $this->noInherit, + ]; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Constraint/ExcludeConstraint.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Constraint/ExcludeConstraint.php new file mode 100644 index 0000000000..4a1c668339 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Constraint/ExcludeConstraint.php @@ -0,0 +1,49 @@ +name === $other->name && $this->isEqualStructure($other); + } + + public function isEqualStructure(self $other) : bool + { + return $this->definition === $other->definition; + } + + /** + * @return ExcludeConstraintShape + */ + public function normalize() : array + { + return [ + 'definition' => $this->definition, + 'name' => $this->name, + ]; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Constraint/ForeignKey.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Constraint/ForeignKey.php new file mode 100644 index 0000000000..0db4065c5d --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Constraint/ForeignKey.php @@ -0,0 +1,83 @@ +, reference_schema: string, reference_table: string, reference_columns: non-empty-list, on_update: string, on_delete: string, deferrable: bool, initially_deferred: bool} + */ +final readonly class ForeignKey +{ + /** + * @param non-empty-list $columns + * @param non-empty-list $referenceColumns + */ + public function __construct( + public ?string $name, + public array $columns, + public string $referenceSchema, + public string $referenceTable, + public array $referenceColumns, + public ReferentialAction $onUpdate = ReferentialAction::NO_ACTION, + public ReferentialAction $onDelete = ReferentialAction::NO_ACTION, + public bool $deferrable = false, + public bool $initiallyDeferred = false, + ) { + } + + /** + * @param ForeignKeyShape $data + */ + public static function fromArray(array $data) : self + { + return new self( + name: $data['name'], + columns: $data['columns'], + referenceSchema: $data['reference_schema'], + referenceTable: $data['reference_table'], + referenceColumns: $data['reference_columns'], + onUpdate: array_key_exists('on_update', $data) ? ReferentialAction::from($data['on_update']) : ReferentialAction::NO_ACTION, + onDelete: array_key_exists('on_delete', $data) ? ReferentialAction::from($data['on_delete']) : ReferentialAction::NO_ACTION, + deferrable: $data['deferrable'] ?? false, + initiallyDeferred: $data['initially_deferred'] ?? false, + ); + } + + public function isEqual(self $other) : bool + { + return $this->name === $other->name && $this->isEqualStructure($other); + } + + public function isEqualStructure(self $other) : bool + { + return $this->columns === $other->columns + && $this->referenceSchema === $other->referenceSchema + && $this->referenceTable === $other->referenceTable + && $this->referenceColumns === $other->referenceColumns + && $this->onUpdate === $other->onUpdate + && $this->onDelete === $other->onDelete + && $this->deferrable === $other->deferrable + && $this->initiallyDeferred === $other->initiallyDeferred; + } + + /** + * @return ForeignKeyShape + */ + public function normalize() : array + { + return [ + 'name' => $this->name, + 'columns' => $this->columns, + 'reference_schema' => $this->referenceSchema, + 'reference_table' => $this->referenceTable, + 'reference_columns' => $this->referenceColumns, + 'on_update' => $this->onUpdate->value, + 'on_delete' => $this->onDelete->value, + 'deferrable' => $this->deferrable, + 'initially_deferred' => $this->initiallyDeferred, + ]; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Constraint/PrimaryKey.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Constraint/PrimaryKey.php new file mode 100644 index 0000000000..edfc988864 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Constraint/PrimaryKey.php @@ -0,0 +1,57 @@ +, name: ?string} + */ +final readonly class PrimaryKey +{ + /** + * @param non-empty-list $columns + */ + public function __construct( + public array $columns, + public ?string $name = null, + ) { + } + + /** + * @param PrimaryKeyShape $data + */ + public static function fromArray(array $data) : self + { + return new self( + columns: $data['columns'], + name: $data['name'] ?? null, + ); + } + + public function isEqual(self $other) : bool + { + return $this->name === $other->name && $this->isEqualStructure($other); + } + + public function isEqualStructure(self $other) : bool + { + $aCols = $this->columns; + $bCols = $other->columns; + \sort($aCols); + \sort($bCols); + + return $aCols === $bCols; + } + + /** + * @return PrimaryKeyShape + */ + public function normalize() : array + { + return [ + 'columns' => $this->columns, + 'name' => $this->name, + ]; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Constraint/UniqueConstraint.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Constraint/UniqueConstraint.php new file mode 100644 index 0000000000..3fecd91714 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Constraint/UniqueConstraint.php @@ -0,0 +1,60 @@ +, name: ?string, nulls_not_distinct: bool} + */ +final readonly class UniqueConstraint +{ + /** + * @param non-empty-list $columns + */ + public function __construct( + public array $columns, + public ?string $name = null, + public bool $nullsNotDistinct = false, + ) { + } + + /** + * @param UniqueConstraintShape $data + */ + public static function fromArray(array $data) : self + { + return new self( + columns: $data['columns'], + name: $data['name'] ?? null, + nullsNotDistinct: $data['nulls_not_distinct'] ?? false, + ); + } + + public function isEqual(self $other) : bool + { + return $this->name === $other->name && $this->isEqualStructure($other); + } + + public function isEqualStructure(self $other) : bool + { + $aCols = $this->columns; + $bCols = $other->columns; + \sort($aCols); + \sort($bCols); + + return $aCols === $bCols && $this->nullsNotDistinct === $other->nullsNotDistinct; + } + + /** + * @return UniqueConstraintShape + */ + public function normalize() : array + { + return [ + 'columns' => $this->columns, + 'name' => $this->name, + 'nulls_not_distinct' => $this->nullsNotDistinct, + ]; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/AstViewDependencyResolver.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/AstViewDependencyResolver.php new file mode 100644 index 0000000000..585494669e --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/AstViewDependencyResolver.php @@ -0,0 +1,144 @@ + $allViews */ + $allViews = []; + /** @var array> $viewDependsOn */ + $viewDependsOn = []; + + foreach ($catalog->all() as $schema) { + foreach ($schema->views as $view) { + $qualifiedName = $schema->name . '.' . $view->name; + $allViews[$qualifiedName] = new DependentView($schema->name, $view); + $viewDependsOn[$qualifiedName] = $this->extractDependencies($view->definition, $schema->name); + } + + foreach ($schema->materializedViews as $materializedView) { + $qualifiedName = $schema->name . '.' . $materializedView->name; + $allViews[$qualifiedName] = new DependentView($schema->name, $materializedView); + $viewDependsOn[$qualifiedName] = $this->extractDependencies($materializedView->definition, $schema->name); + } + } + + $affected = $this->findAffectedViews($modifiedTableQualifiedNames, $viewDependsOn); + + if ($affected === []) { + return DependentViews::empty(); + } + + $depths = $this->computeDepths($affected, $viewDependsOn, $allViews); + + $dropOrder = $affected; + \usort($dropOrder, static fn (string $a, string $b) : int => $depths[$b] <=> $depths[$a]); + + $createOrder = $affected; + \usort($createOrder, static fn (string $a, string $b) : int => $depths[$a] <=> $depths[$b]); + + return new DependentViews( + \array_map(static fn (string $name) : DependentView => $allViews[$name], $dropOrder), + \array_map(static fn (string $name) : DependentView => $allViews[$name], $createOrder), + ); + } + + /** + * @param list $affected + * @param array> $viewDependsOn + * @param array $allViews + * + * @return array + */ + private function computeDepths(array $affected, array $viewDependsOn, array $allViews) : array + { + $depths = []; + $affectedSet = \array_flip($affected); + + $getDepth = static function (string $viewName) use (&$getDepth, &$depths, $viewDependsOn, $allViews, $affectedSet) : int { + if (\array_key_exists($viewName, $depths)) { + return $depths[$viewName]; + } + + $depths[$viewName] = 0; + $maxDep = -1; + + foreach ($viewDependsOn[$viewName] ?? [] as $dep) { + if (\array_key_exists($dep, $allViews) && \array_key_exists($dep, $affectedSet)) { + $maxDep = \max($maxDep, $getDepth($dep)); + } + } + + $depths[$viewName] = $maxDep + 1; + + return $depths[$viewName]; + }; + + foreach ($affected as $viewName) { + $getDepth($viewName); + } + + return $depths; + } + + /** + * @return list + */ + private function extractDependencies(string $definition, string $defaultSchema) : array + { + $parsedQuery = $this->parser->parse($definition); + $tables = (new Tables($parsedQuery))->all(); + $deps = []; + + foreach ($tables as $table) { + $deps[] = ($table->schema() ?? $defaultSchema) . '.' . $table->name(); + } + + return $deps; + } + + /** + * @param list $modifiedTableQualifiedNames + * @param array> $viewDependsOn + * + * @return list + */ + private function findAffectedViews(array $modifiedTableQualifiedNames, array $viewDependsOn) : array + { + $affected = []; + $queue = $modifiedTableQualifiedNames; + + while ($queue !== []) { + $current = \array_shift($queue); + + foreach ($viewDependsOn as $viewName => $deps) { + if (\in_array($viewName, $affected, true)) { + continue; + } + + if (\in_array($current, $deps, true)) { + $affected[] = $viewName; + $queue[] = $viewName; + } + } + } + + return $affected; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/CatalogComparator.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/CatalogComparator.php new file mode 100644 index 0000000000..60b0b34f85 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/CatalogComparator.php @@ -0,0 +1,93 @@ + $tableOrderStrategy + * @param ExecutionOrderStrategy $viewOrderStrategy + * @param ExecutionOrderStrategy $materializedViewOrderStrategy + */ + public function __construct( + private SchemaComparator $schemaComparator, + private ViewDependencyResolver $viewDependencyResolver = new AstViewDependencyResolver(new Parser()), + private ExecutionOrderStrategy $tableOrderStrategy = new ForeignKeyDependencyOrder(), + private ExecutionOrderStrategy $viewOrderStrategy = new ViewDependencyOrder(new Parser()), + private ExecutionOrderStrategy $materializedViewOrderStrategy = new MaterializedViewDependencyOrder(new Parser()), + ) { + } + + /** + * @param null|ExecutionOrderStrategy $tableOrderStrategy + * @param null|ExecutionOrderStrategy $viewOrderStrategy + * @param null|ExecutionOrderStrategy $materializedViewOrderStrategy + */ + public static function create( + ?RenameStrategy $renameStrategy = null, + ?ViewDependencyResolver $viewDependencyResolver = null, + ?ExecutionOrderStrategy $tableOrderStrategy = null, + ?ExecutionOrderStrategy $viewOrderStrategy = null, + ?ExecutionOrderStrategy $materializedViewOrderStrategy = null, + ) : self { + $renameStrategy ??= new GreedySimilarityRenameStrategy(new SimilarTextStrategy()); + $constraintComparator = new ConstraintComparator(); + $indexComparator = new IndexComparator($renameStrategy); + $tableComparator = new TableComparator($indexComparator, $constraintComparator, $renameStrategy); + $tableStructureComparator = new TableStructureComparator($renameStrategy); + + $tableOrderStrategy ??= new ForeignKeyDependencyOrder(); + $viewOrderStrategy ??= new ViewDependencyOrder(new Parser()); + $materializedViewOrderStrategy ??= new MaterializedViewDependencyOrder(new Parser()); + + return new self( + new SchemaComparator($tableComparator, $indexComparator, $constraintComparator, $tableStructureComparator, $tableOrderStrategy, $viewOrderStrategy, $materializedViewOrderStrategy), + $viewDependencyResolver ?? new AstViewDependencyResolver(new Parser()), + $tableOrderStrategy, + $viewOrderStrategy, + $materializedViewOrderStrategy, + ); + } + + public function compare(Catalog $source, Catalog $target) : CatalogDiff + { + $sourceNames = $source->names(); + $targetNames = $target->names(); + + $addedSchemas = []; + $removedSchemas = []; + $modifiedSchemas = []; + + foreach ($targetNames as $name) { + if (!\in_array($name, $sourceNames, true)) { + $addedSchemas[] = $target->get($name); + } + } + + foreach ($sourceNames as $name) { + if (!\in_array($name, $targetNames, true)) { + $removedSchemas[] = $source->get($name); + } + } + + foreach ($sourceNames as $name) { + if (!\in_array($name, $targetNames, true)) { + continue; + } + + $schemaDiff = $this->schemaComparator->compare($source->get($name), $target->get($name)); + + if (!$schemaDiff->isEmpty()) { + $modifiedSchemas[] = $schemaDiff; + } + } + + return new CatalogDiff($source, $target, $addedSchemas, $removedSchemas, $modifiedSchemas, $this->viewDependencyResolver, $this->tableOrderStrategy, $this->viewOrderStrategy, $this->materializedViewOrderStrategy); + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/CatalogDiff.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/CatalogDiff.php new file mode 100644 index 0000000000..320412bddd --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/CatalogDiff.php @@ -0,0 +1,169 @@ + $addedSchemas + * @param list $removedSchemas + * @param list $modifiedSchemas + * @param ExecutionOrderStrategy
$tableOrderStrategy + * @param ExecutionOrderStrategy $viewOrderStrategy + * @param ExecutionOrderStrategy $materializedViewOrderStrategy + */ + public function __construct( + public Catalog $source, + public Catalog $target, + public array $addedSchemas = [], + public array $removedSchemas = [], + public array $modifiedSchemas = [], + private ViewDependencyResolver $viewDependencyResolver = new NoopViewDependencyResolver(), + private ExecutionOrderStrategy $tableOrderStrategy = new ForeignKeyDependencyOrder(), + private ExecutionOrderStrategy $viewOrderStrategy = new ViewDependencyOrder(new Parser()), + private ExecutionOrderStrategy $materializedViewOrderStrategy = new MaterializedViewDependencyOrder(new Parser()), + ) { + } + + /** + * @return list + */ + public function generate() : array + { + $sqls = []; + + foreach ($this->addedSchemas as $schema) { + $sqls[] = create()->schema($schema->name)->ifNotExists(); + $sqls = [...$sqls, ...$schema->toSql($this->tableOrderStrategy, $this->viewOrderStrategy, $this->materializedViewOrderStrategy)]; + } + + $dependentViews = $this->resolveDependentViews(); + + foreach ($dependentViews->toDrop as $dv) { + $sqls[] = $dv->view instanceof MaterializedView + ? drop()->materializedView($dv->qualifiedName()) + : drop()->view($dv->qualifiedName()); + } + + foreach ($this->modifiedSchemas as $diff) { + $sqls = [...$sqls, ...$diff->generate()]; + } + + foreach ($dependentViews->toCreate as $dv) { + if ($dv->view instanceof MaterializedView) { + $sqls[] = create()->materializedView($dv->view->name, $dv->schema)->as(parsed_select($dv->view->definition)); + + foreach ($dv->view->indexes as $idx) { + $builder = create()->index($idx->name); + + if ($idx->unique) { + $builder = $builder->unique(); + } + + $onBuilder = $builder->on($dv->view->name, $dv->schema); + + if ($idx->method !== IndexMethod::BTREE) { + $onBuilder = $onBuilder->using(QbIndexMethod::from($idx->method->value)); + } + + $sqls[] = $onBuilder->columns(...$idx->columns); + } + } else { + $sqls[] = create()->view($dv->view->name, $dv->schema)->as(parsed_select($dv->view->definition)); + } + } + + foreach ($this->removedSchemas as $schema) { + $sqls[] = drop()->schema($schema->name)->cascade(); + } + + return $sqls; + } + + public function isEmpty() : bool + { + return $this->addedSchemas === [] + && $this->removedSchemas === [] + && $this->modifiedSchemas === []; + } + + /** + * @return list + */ + private function collectModifiedTableNames() : array + { + $names = []; + + foreach ($this->modifiedSchemas as $schemaDiff) { + foreach ($schemaDiff->modifiedTables as $tableDiff) { + if ($tableDiff->requiresViewRebuild()) { + $names[] = $tableDiff->target->qualifiedName(); + } + } + } + + return $names; + } + + private function resolveDependentViews() : DependentViews + { + $modifiedTableNames = $this->collectModifiedTableNames(); + + if ($modifiedTableNames === []) { + return DependentViews::empty(); + } + + $resolved = $this->viewDependencyResolver->resolve($this->source, $modifiedTableNames); + + $excludedNames = $this->viewNamesAlreadyHandledByDiff(); + + if ($excludedNames === []) { + return $resolved; + } + + $excludeSet = \array_flip($excludedNames); + + return new DependentViews( + \array_values(\array_filter($resolved->toDrop, static fn (DependentView $dv) : bool => !\array_key_exists($dv->qualifiedName(), $excludeSet))), + \array_values(\array_filter($resolved->toCreate, static fn (DependentView $dv) : bool => !\array_key_exists($dv->qualifiedName(), $excludeSet))), + ); + } + + /** + * @return list + */ + private function viewNamesAlreadyHandledByDiff() : array + { + $names = []; + + foreach ($this->modifiedSchemas as $schemaDiff) { + foreach ($schemaDiff->removedViews as $view) { + $names[] = $schemaDiff->source->name . '.' . $view->name; + } + + foreach ($schemaDiff->modifiedViews as $viewDiff) { + $names[] = $schemaDiff->source->name . '.' . $viewDiff->target->name; + } + + foreach ($schemaDiff->removedMaterializedViews as $mv) { + $names[] = $schemaDiff->source->name . '.' . $mv->name; + } + + foreach ($schemaDiff->modifiedMaterializedViews as $mvDiff) { + $names[] = $schemaDiff->source->name . '.' . $mvDiff->target->name; + } + } + + return $names; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/ChangeSet.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/ChangeSet.php new file mode 100644 index 0000000000..e108585ac6 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/ChangeSet.php @@ -0,0 +1,84 @@ + $added + * @param list $removed + * @param null|list $modified + * @param null|array $renamed + */ + public function __construct( + public array $added, + public array $removed, + public ?array $modified = null, + public ?array $renamed = null, + ) { + } + + /** + * @template TObj + * @template TObjDiff + * + * @param list $source + * @param list $target + * @param callable(TObj): string $identityFn + * @param null|(callable(TObj, TObj): ?TObjDiff) $modifiedFn + * + * @return self + */ + public static function fromNamedObjects(array $source, array $target, callable $identityFn, ?callable $modifiedFn = null) : self + { + $sourceMap = []; + + foreach ($source as $item) { + $sourceMap[$identityFn($item)] = $item; + } + + $targetMap = []; + + foreach ($target as $item) { + $targetMap[$identityFn($item)] = $item; + } + + $added = []; + $removed = []; + $modified = []; + + foreach ($targetMap as $identity => $item) { + if (!array_key_exists($identity, $sourceMap)) { + $added[] = $item; + } + } + + foreach ($sourceMap as $identity => $item) { + if (!array_key_exists($identity, $targetMap)) { + $removed[] = $item; + } + } + + if ($modifiedFn !== null) { + foreach ($sourceMap as $identity => $sourceItem) { + if (!array_key_exists($identity, $targetMap)) { + continue; + } + + $diff = $modifiedFn($sourceItem, $targetMap[$identity]); + + if ($diff !== null) { + $modified[] = $diff; + } + } + } + + return new self($added, $removed, $modified !== [] ? $modified : null); + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/ColumnDiff.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/ColumnDiff.php new file mode 100644 index 0000000000..08ca5039ff --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/ColumnDiff.php @@ -0,0 +1,115 @@ + + */ + public function generate() : array + { + $sqls = []; + $columnName = $this->source->name; + + if ($this->source->name !== $this->target->name) { + $sqls[] = alter()->table($this->qualifiedTableName)->renameColumn($this->source->name, $this->target->name); + $columnName = $this->target->name; + } + + // PostgreSQL cannot ALTER generated columns or identity — must drop and re-add + if ($this->target->isGenerated !== $this->source->isGenerated || $this->target->generationExpression !== $this->source->generationExpression + || $this->target->isIdentity !== $this->source->isIdentity || $this->target->identityGeneration !== $this->source->identityGeneration) { + $sqls[] = alter()->table($this->qualifiedTableName)->dropColumn($columnName); + + $colDef = column($this->target->name, $this->target->type); + + if (!$this->target->nullable) { + $colDef = $colDef->notNull(); + } + + if ($this->target->default !== null) { + $colDef = $colDef->defaultRaw(ExpressionFactory::fromAst((new ExpressionParser(new Parser()))->parse($this->target->default))); + } + + if ($this->target->isGenerated && $this->target->generationExpression !== null) { + $colDef = $colDef->generatedAs(ExpressionFactory::fromAst((new ExpressionParser(new Parser()))->parse($this->target->generationExpression))); + } + + if ($this->target->isIdentity) { + $colDef = $colDef->identity($this->target->identityGeneration ?? IdentityGeneration::ALWAYS); + } + + $sqls[] = alter()->table($this->qualifiedTableName)->addColumn($colDef); + + return $sqls; + } + + if (!$this->target->type->isEqual($this->source->type)) { + $sqls[] = alter()->table($this->qualifiedTableName)->alterColumnType($columnName, $this->target->type); + } + + if ($this->target->nullable !== $this->source->nullable) { + $sqls[] = $this->target->nullable + ? alter()->table($this->qualifiedTableName)->alterColumnDropNotNull($columnName) + : alter()->table($this->qualifiedTableName)->alterColumnSetNotNull($columnName); + } + + if ($this->target->default !== $this->source->default) { + $sqls[] = $this->target->default === null + ? alter()->table($this->qualifiedTableName)->alterColumnDropDefault($columnName) + : alter()->table($this->qualifiedTableName)->alterColumnSetDefault($columnName, ExpressionFactory::fromAst((new ExpressionParser(new Parser()))->parse($this->target->default))); + } + + return $sqls; + } + + public function hasDefaultChanged() : bool + { + return $this->source->default !== $this->target->default; + } + + public function hasGenerationChanged() : bool + { + return $this->source->isGenerated !== $this->target->isGenerated + || $this->source->generationExpression !== $this->target->generationExpression; + } + + public function hasIdentityChanged() : bool + { + return $this->source->isIdentity !== $this->target->isIdentity + || $this->source->identityGeneration !== $this->target->identityGeneration; + } + + public function hasNameChanged() : bool + { + return $this->source->name !== $this->target->name; + } + + public function hasNullableChanged() : bool + { + return $this->source->nullable !== $this->target->nullable; + } + + public function hasTypeChanged() : bool + { + return !$this->source->type->isEqual($this->target->type); + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/ConstraintComparator.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/ConstraintComparator.php new file mode 100644 index 0000000000..5714a73f5b --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/ConstraintComparator.php @@ -0,0 +1,128 @@ + $sourceCcs + * @param list $targetCcs + * + * @return ChangeSet + */ + public function diffCheckConstraints(array $sourceCcs, array $targetCcs) : ChangeSet + { + return $this->diffConstraints( + $sourceCcs, + $targetCcs, + static fn (CheckConstraint $cc) : string => $cc->name ?? $cc->expression, + static fn (CheckConstraint $a, CheckConstraint $b) : bool => $a->isEqualStructure($b), + ); + } + + /** + * @param list $sourceEcs + * @param list $targetEcs + * + * @return ChangeSet + */ + public function diffExcludeConstraints(array $sourceEcs, array $targetEcs) : ChangeSet + { + return $this->diffConstraints( + $sourceEcs, + $targetEcs, + static fn (ExcludeConstraint $ec) : string => $ec->name ?? $ec->definition, + static fn (ExcludeConstraint $a, ExcludeConstraint $b) : bool => $a->isEqualStructure($b), + ); + } + + /** + * @param list $sourceFks + * @param list $targetFks + * + * @return ChangeSet + */ + public function diffForeignKeys(array $sourceFks, array $targetFks) : ChangeSet + { + return $this->diffConstraints( + $sourceFks, + $targetFks, + static fn (ForeignKey $fk) : string => $fk->name ?? \implode(',', $fk->columns) . '=>' . $fk->referenceSchema . '.' . $fk->referenceTable . '(' . \implode(',', $fk->referenceColumns) . ')', + static fn (ForeignKey $a, ForeignKey $b) : bool => $a->isEqualStructure($b), + ); + } + + /** + * @param list $sourceUcs + * @param list $targetUcs + * + * @return ChangeSet + */ + public function diffUniqueConstraints(array $sourceUcs, array $targetUcs) : ChangeSet + { + return $this->diffConstraints( + $sourceUcs, + $targetUcs, + static function (UniqueConstraint $uc) : string { + if ($uc->name !== null) { + return $uc->name; + } + + $cols = $uc->columns; + \sort($cols); + + return \implode(',', $cols); + }, + static fn (UniqueConstraint $a, UniqueConstraint $b) : bool => $a->isEqualStructure($b), + ); + } + + /** + * @template T + * + * @param list $sourceList + * @param list $targetList + * @param callable(T): string $identityFn + * @param callable(T, T): bool $equalsFn + * + * @return ChangeSet + */ + private function diffConstraints(array $sourceList, array $targetList, callable $identityFn, callable $equalsFn) : ChangeSet + { + $sourceMap = []; + + foreach ($sourceList as $item) { + $sourceMap[$identityFn($item)] = $item; + } + + $targetMap = []; + + foreach ($targetList as $item) { + $targetMap[$identityFn($item)] = $item; + } + + $added = []; + $removed = []; + + foreach ($targetMap as $identity => $item) { + if (!array_key_exists($identity, $sourceMap)) { + $added[] = $item; + } elseif (!$equalsFn($sourceMap[$identity], $item)) { + $removed[] = $sourceMap[$identity]; + $added[] = $item; + } + } + + foreach ($sourceMap as $identity => $item) { + if (!array_key_exists($identity, $targetMap)) { + $removed[] = $item; + } + } + + return new ChangeSet($added, $removed); + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/DependentView.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/DependentView.php new file mode 100644 index 0000000000..03989fdfbc --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/DependentView.php @@ -0,0 +1,21 @@ +schema . '.' . $this->view->name; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/DependentViews.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/DependentViews.php new file mode 100644 index 0000000000..8564631660 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/DependentViews.php @@ -0,0 +1,28 @@ + $toDrop views to drop before table modifications, ordered most-dependent first + * @param list $toCreate views to recreate after table modifications, ordered least-dependent first + */ + public function __construct( + public array $toDrop, + public array $toCreate, + ) { + } + + public static function empty() : self + { + return new self([], []); + } + + public function isEmpty() : bool + { + return $this->toDrop === [] && $this->toCreate === []; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/Diff.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/Diff.php new file mode 100644 index 0000000000..e93c7d636b --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/Diff.php @@ -0,0 +1,15 @@ + + */ + public function generate() : array; +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/DomainDiff.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/DomainDiff.php new file mode 100644 index 0000000000..d6a1c49285 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/DomainDiff.php @@ -0,0 +1,87 @@ + $addedCheckConstraints + * @param list $removedCheckConstraints + */ + public function __construct( + public Domain $source, + public Domain $target, + public array $addedCheckConstraints = [], + public array $removedCheckConstraints = [], + ) { + } + + /** + * @return list + */ + public function generate() : array + { + if ($this->hasBaseTypeChanged()) { + return [drop()->domain($this->target->name)->cascade(), $this->target->toSql()]; + } + + $sqls = []; + + if ($this->target->nullable !== $this->source->nullable) { + $sqls[] = $this->target->nullable + ? alter()->domain($this->target->name)->dropNotNull() + : alter()->domain($this->target->name)->setNotNull(); + } + + if ($this->target->default !== $this->source->default) { + $sqls[] = $this->target->default === null + ? alter()->domain($this->target->name)->dropDefault() + : alter()->domain($this->target->name)->setDefault(ExpressionFactory::fromAst((new ExpressionParser(new Parser()))->parse($this->target->default))); + } + + foreach ($this->removedCheckConstraints as $cc) { + if ($cc->name === null) { + throw new \RuntimeException(\sprintf('Cannot drop unnamed check constraint on domain "%s". Constraint names are required for reversible migrations.', $this->target->name)); + } + + $sqls[] = alter()->domain($this->target->name)->dropConstraint($cc->name); + } + + foreach ($this->addedCheckConstraints as $cc) { + if ($cc->name === null) { + throw new \RuntimeException(\sprintf('Cannot add unnamed check constraint on domain "%s". Constraint names are required for reversible migrations.', $this->target->name)); + } + + $sqls[] = alter()->domain($this->target->name)->addConstraint($cc->name, ConditionFactory::fromAst((new ExpressionParser(new Parser()))->parse($cc->expression))); + } + + return $sqls; + } + + public function hasBaseTypeChanged() : bool + { + return !$this->source->baseType->isEqual($this->target->baseType); + } + + public function hasDefaultChanged() : bool + { + return $this->source->default !== $this->target->default; + } + + public function hasNullableChanged() : bool + { + return $this->source->nullable !== $this->target->nullable; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/ExtensionDiff.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/ExtensionDiff.php new file mode 100644 index 0000000000..36c92159f3 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/ExtensionDiff.php @@ -0,0 +1,40 @@ + + */ + public function generate() : array + { + if (!$this->hasVersionChanged()) { + return []; + } + + if ($this->target->version === null) { + return [alter()->extension($this->target->name)->update()]; + } + + return [alter()->extension($this->target->name)->updateTo($this->target->version)]; + } + + public function hasVersionChanged() : bool + { + return $this->source->version !== $this->target->version; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/FuncDiff.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/FuncDiff.php new file mode 100644 index 0000000000..8fedac41ec --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/FuncDiff.php @@ -0,0 +1,31 @@ + + */ + public function generate() : array + { + $sql = $this->target->toSql(); + + if ($sql === null) { + return []; + } + + return [$sql]; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/GreedySimilarityRenameStrategy.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/GreedySimilarityRenameStrategy.php new file mode 100644 index 0000000000..4977222418 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/GreedySimilarityRenameStrategy.php @@ -0,0 +1,70 @@ +addedName][] = $candidate->removedName; + } + + $matched = []; + $matchedAdded = []; + $matchedRemoved = []; + + foreach ($candidatesByAdded as $addedName => $removedCandidates) { + if (\count($removedCandidates) !== 1) { + continue; + } + + $removedName = $removedCandidates[0]; + + if (array_key_exists($removedName, $matchedRemoved)) { + continue; + } + + $matched[] = new RenameMatch($addedName, $removedName); + $matchedAdded[$addedName] = true; + $matchedRemoved[$removedName] = true; + } + + $pairs = []; + + foreach ($candidates as $candidate) { + if (array_key_exists($candidate->addedName, $matchedAdded) || array_key_exists($candidate->removedName, $matchedRemoved)) { + continue; + } + + $score = $this->similarity->similarity($candidate->addedName, $candidate->removedName); + + if ($score >= $this->similarity->threshold()) { + $pairs[] = ['added' => $candidate->addedName, 'removed' => $candidate->removedName, 'score' => $score]; + } + } + + \usort($pairs, static fn (array $a, array $b) : int => $b['score'] <=> $a['score']); + + foreach ($pairs as $pair) { + if (array_key_exists($pair['added'], $matchedAdded) || array_key_exists($pair['removed'], $matchedRemoved)) { + continue; + } + + $matched[] = new RenameMatch($pair['added'], $pair['removed']); + $matchedAdded[$pair['added']] = true; + $matchedRemoved[$pair['removed']] = true; + } + + return $matched; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/IndexComparator.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/IndexComparator.php new file mode 100644 index 0000000000..19441c00f8 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/IndexComparator.php @@ -0,0 +1,98 @@ + $sourceIndexes + * @param list $targetIndexes + * + * @return ChangeSet + */ + public function compare(array $sourceIndexes, array $targetIndexes) : ChangeSet + { + $sourceMap = []; + + foreach ($sourceIndexes as $idx) { + $sourceMap[$idx->name] = $idx; + } + + $targetMap = []; + + foreach ($targetIndexes as $idx) { + $targetMap[$idx->name] = $idx; + } + + $added = []; + $removed = []; + + foreach ($targetMap as $name => $idx) { + if (!array_key_exists($name, $sourceMap)) { + $added[] = $idx; + } elseif (!$sourceMap[$name]->isEqualStructure($idx)) { + $removed[] = $sourceMap[$name]; + $added[] = $idx; + } + } + + foreach ($sourceMap as $name => $idx) { + if (!array_key_exists($name, $targetMap)) { + $removed[] = $idx; + } + } + + $renameResult = $this->detectIndexRenames($added, $removed); + + return new ChangeSet($renameResult->added, $renameResult->removed, renamed: $renameResult->renamed ?? []); + } + + /** + * @param list $added + * @param list $removed + * + * @return ChangeSet + */ + private function detectIndexRenames(array $added, array $removed) : ChangeSet + { + $addedMap = []; + + foreach ($added as $idx) { + $addedMap[$idx->name] = $idx; + } + + $removedMap = []; + + foreach ($removed as $idx) { + $removedMap[$idx->name] = $idx; + } + + $candidates = []; + + foreach ($addedMap as $addedName => $addedIdx) { + foreach ($removedMap as $removedName => $removedIdx) { + if ($addedIdx->isEqualStructure($removedIdx)) { + $candidates[] = new RenameCandidate($addedName, $removedName); + } + } + } + + $renamed = []; + + foreach ($this->renameStrategy->resolve($candidates) as $match) { + $renamed[$match->removedName] = $addedMap[$match->addedName]; + unset($addedMap[$match->addedName], $removedMap[$match->removedName]); + } + + return new ChangeSet(\array_values($addedMap), \array_values($removedMap), renamed: $renamed !== [] ? $renamed : null); + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/LevenshteinStrategy.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/LevenshteinStrategy.php new file mode 100644 index 0000000000..759a988369 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/LevenshteinStrategy.php @@ -0,0 +1,29 @@ +threshold; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/LongestCommonSubstringStrategy.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/LongestCommonSubstringStrategy.php new file mode 100644 index 0000000000..4e28690653 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/LongestCommonSubstringStrategy.php @@ -0,0 +1,51 @@ + $longest) { + $longest = $curr[$j]; + } + } + } + + $prev = $curr; + } + + return ($longest / $maxLen) * 100.0; + } + + public function threshold() : float + { + return $this->threshold; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/MaterializedViewDiff.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/MaterializedViewDiff.php new file mode 100644 index 0000000000..f6d9c37aa8 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/MaterializedViewDiff.php @@ -0,0 +1,72 @@ + $addedIndexes + * @param list $removedIndexes + */ + public function __construct( + public MaterializedView $source, + public MaterializedView $target, + public array $addedIndexes = [], + public array $removedIndexes = [], + ) { + } + + /** + * @return list + */ + public function generate() : array + { + $sqls = []; + + if ($this->hasDefinitionChanged()) { + foreach ($this->source->indexes as $idx) { + $sqls[] = drop()->index($idx->name); + } + + $sqls[] = drop()->materializedView($this->source->name); + $sqls = [...$sqls, ...$this->target->toSql()]; + + return $sqls; + } + + foreach ($this->removedIndexes as $idx) { + $sqls[] = drop()->index($idx->name); + } + + foreach ($this->addedIndexes as $idx) { + $builder = create()->index($idx->name); + + if ($idx->unique) { + $builder = $builder->unique(); + } + + $onBuilder = $builder->on($this->target->name); + + if ($idx->method !== IndexMethod::BTREE) { + $onBuilder = $onBuilder->using(QbIndexMethod::from($idx->method->value)); + } + + $sqls[] = $onBuilder->columns(...$idx->columns); + } + + return $sqls; + } + + public function hasDefinitionChanged() : bool + { + return $this->source->definition !== $this->target->definition; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/NoRenameStrategy.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/NoRenameStrategy.php new file mode 100644 index 0000000000..45b92481e6 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/NoRenameStrategy.php @@ -0,0 +1,13 @@ + + */ + public function generate() : array + { + $sql = $this->target->toSql(); + + if ($sql === null) { + return []; + } + + return [$sql]; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/RenameCandidate.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/RenameCandidate.php new file mode 100644 index 0000000000..c35cd34c43 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/RenameCandidate.php @@ -0,0 +1,14 @@ + $candidates + * + * @return list + */ + public function resolve(array $candidates) : array; +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/SchemaComparator.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/SchemaComparator.php new file mode 100644 index 0000000000..e46aec5564 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/SchemaComparator.php @@ -0,0 +1,215 @@ + $tableOrderStrategy + * @param ExecutionOrderStrategy $viewOrderStrategy + * @param ExecutionOrderStrategy $materializedViewOrderStrategy + */ + public function __construct( + private TableComparator $tableComparator, + private IndexComparator $indexComparator, + private ConstraintComparator $constraintComparator, + private TableStructureComparator $tableStructureComparator, + private ExecutionOrderStrategy $tableOrderStrategy = new ForeignKeyDependencyOrder(), + private ExecutionOrderStrategy $viewOrderStrategy = new ViewDependencyOrder(new Parser()), + private ExecutionOrderStrategy $materializedViewOrderStrategy = new MaterializedViewDependencyOrder(new Parser()), + ) { + } + + public function compare(Schema $source, Schema $target) : SchemaDiff + { + $tables = $this->diffTables($source->tables, $target->tables); + $materializedViews = $this->diffMaterializedViews($source->materializedViews, $target->materializedViews); + $domains = $this->diffDomains($source->domains, $target->domains); + + /** @var ChangeSet $sequences */ + $sequences = ChangeSet::fromNamedObjects( + $source->sequences, + $target->sequences, + static fn (Sequence $s) : string => $s->name, + static fn (Sequence $a, Sequence $b) : ?SequenceDiff => $a->dataType === $b->dataType + && $a->startValue === $b->startValue + && $a->minValue === $b->minValue + && $a->maxValue === $b->maxValue + && $a->incrementBy === $b->incrementBy + && $a->cycle === $b->cycle + && $a->cacheValue === $b->cacheValue + && $a->ownedByTable === $b->ownedByTable + && $a->ownedByColumn === $b->ownedByColumn + ? null + : new SequenceDiff($a, $b), + ); + + /** @var ChangeSet $views */ + $views = ChangeSet::fromNamedObjects( + $source->views, + $target->views, + static fn (View $v) : string => $v->name, + static fn (View $a, View $b) : ?ViewDiff => $a->definition === $b->definition + && $a->isUpdatable === $b->isUpdatable + ? null + : new ViewDiff($a, $b), + ); + + /** @var ChangeSet $functions */ + $functions = ChangeSet::fromNamedObjects( + $source->functions, + $target->functions, + static fn (Func $f) : string => $f->name, + static fn (Func $a, Func $b) : ?FuncDiff => $a->returnType === $b->returnType + && $a->argumentTypes === $b->argumentTypes + && $a->language === $b->language + && $a->definition === $b->definition + && $a->isStrict === $b->isStrict + && $a->volatility === $b->volatility + ? null + : new FuncDiff($a, $b), + ); + + /** @var ChangeSet $procedures */ + $procedures = ChangeSet::fromNamedObjects( + $source->procedures, + $target->procedures, + static fn (Procedure $p) : string => $p->name, + static fn (Procedure $a, Procedure $b) : ?ProcedureDiff => $a->argumentTypes === $b->argumentTypes + && $a->language === $b->language + && $a->definition === $b->definition + ? null + : new ProcedureDiff($a, $b), + ); + + /** @var ChangeSet $extensions */ + $extensions = ChangeSet::fromNamedObjects( + $source->extensions, + $target->extensions, + static fn (Extension $e) : string => $e->name, + static fn (Extension $a, Extension $b) : ?ExtensionDiff => $a->version === $b->version + ? null + : new ExtensionDiff($a, $b), + ); + + return new SchemaDiff( + $source, + $target, + $tables->added, + $tables->removed, + $tables->modified ?? [], + $tables->renamed ?? [], + $sequences->added, + $sequences->removed, + $sequences->modified ?? [], + $views->added, + $views->removed, + $views->modified ?? [], + $materializedViews->added, + $materializedViews->removed, + $materializedViews->modified ?? [], + $functions->added, + $functions->removed, + $functions->modified ?? [], + $procedures->added, + $procedures->removed, + $procedures->modified ?? [], + $domains->added, + $domains->removed, + $domains->modified ?? [], + $extensions->added, + $extensions->removed, + $extensions->modified ?? [], + $this->tableOrderStrategy, + $this->viewOrderStrategy, + $this->materializedViewOrderStrategy, + ); + } + + /** + * @param list $sourceDomains + * @param list $targetDomains + * + * @return ChangeSet + */ + private function diffDomains(array $sourceDomains, array $targetDomains) : ChangeSet + { + /** @var ChangeSet */ + return ChangeSet::fromNamedObjects( + $sourceDomains, + $targetDomains, + static fn (Domain $d) : string => $d->name, + function (Domain $a, Domain $b) : ?DomainDiff { + $checkDiff = $this->constraintComparator->diffCheckConstraints($a->checkConstraints, $b->checkConstraints); + + $hasPropertyChange = !$a->baseType->isEqual($b->baseType) + || $a->nullable !== $b->nullable + || $a->default !== $b->default; + + if (!$hasPropertyChange && $checkDiff->added === [] && $checkDiff->removed === []) { + return null; + } + + return new DomainDiff($a, $b, $checkDiff->added, $checkDiff->removed); + }, + ); + } + + /** + * @param list $sourceMViews + * @param list $targetMViews + * + * @return ChangeSet + */ + private function diffMaterializedViews(array $sourceMViews, array $targetMViews) : ChangeSet + { + /** @var ChangeSet */ + return ChangeSet::fromNamedObjects( + $sourceMViews, + $targetMViews, + static fn (MaterializedView $mv) : string => $mv->name, + function (MaterializedView $a, MaterializedView $b) : ?MaterializedViewDiff { + $indexChanges = $this->indexComparator->compare($a->indexes, $b->indexes); + + if ($a->definition === $b->definition && $indexChanges->added === [] && $indexChanges->removed === [] && ($indexChanges->renamed === null || $indexChanges->renamed === [])) { + return null; + } + + return new MaterializedViewDiff($a, $b, $indexChanges->added, $indexChanges->removed); + }, + ); + } + + /** + * @param list
$sourceTables + * @param list
$targetTables + * + * @return ChangeSet + */ + private function diffTables(array $sourceTables, array $targetTables) : ChangeSet + { + /** @var ChangeSet $initial */ + $initial = ChangeSet::fromNamedObjects( + $sourceTables, + $targetTables, + static fn (Table $t) : string => $t->name, + fn (Table $a, Table $b) : ?TableDiff => ($diff = $this->tableComparator->compare($a, $b))->isEmpty() + ? null + : $diff, + ); + + $renameResult = $this->tableStructureComparator->detectTableRenames($initial->added, $initial->removed); + + return new ChangeSet( + $renameResult->added, + $renameResult->removed, + $initial->modified, + $renameResult->renamed, + ); + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/SchemaDiff.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/SchemaDiff.php new file mode 100644 index 0000000000..f078162a36 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/SchemaDiff.php @@ -0,0 +1,212 @@ + $addedTables + * @param list
$removedTables + * @param list $modifiedTables + * @param array $renamedTables old qualified name => new Table + * @param list $addedSequences + * @param list $removedSequences + * @param list $modifiedSequences + * @param list $addedViews + * @param list $removedViews + * @param list $modifiedViews + * @param list $addedMaterializedViews + * @param list $removedMaterializedViews + * @param list $modifiedMaterializedViews + * @param list $addedFunctions + * @param list $removedFunctions + * @param list $modifiedFunctions + * @param list $addedProcedures + * @param list $removedProcedures + * @param list $modifiedProcedures + * @param list $addedDomains + * @param list $removedDomains + * @param list $modifiedDomains + * @param list $addedExtensions + * @param list $removedExtensions + * @param list $modifiedExtensions + * @param ExecutionOrderStrategy
$tableOrderStrategy + * @param ExecutionOrderStrategy $viewOrderStrategy + * @param ExecutionOrderStrategy $materializedViewOrderStrategy + */ + public function __construct( + public Schema $source, + public Schema $target, + public array $addedTables = [], + public array $removedTables = [], + public array $modifiedTables = [], + public array $renamedTables = [], + public array $addedSequences = [], + public array $removedSequences = [], + public array $modifiedSequences = [], + public array $addedViews = [], + public array $removedViews = [], + public array $modifiedViews = [], + public array $addedMaterializedViews = [], + public array $removedMaterializedViews = [], + public array $modifiedMaterializedViews = [], + public array $addedFunctions = [], + public array $removedFunctions = [], + public array $modifiedFunctions = [], + public array $addedProcedures = [], + public array $removedProcedures = [], + public array $modifiedProcedures = [], + public array $addedDomains = [], + public array $removedDomains = [], + public array $modifiedDomains = [], + public array $addedExtensions = [], + public array $removedExtensions = [], + public array $modifiedExtensions = [], + private ExecutionOrderStrategy $tableOrderStrategy = new ForeignKeyDependencyOrder(), + private ExecutionOrderStrategy $viewOrderStrategy = new ViewDependencyOrder(new Parser()), + private ExecutionOrderStrategy $materializedViewOrderStrategy = new MaterializedViewDependencyOrder(new Parser()), + ) { + } + + /** + * @return list + */ + public function generate() : array + { + return [ + ...(new Schema($this->target->name, $this->addedTables, $this->addedSequences, $this->addedViews, $this->addedMaterializedViews, $this->addedFunctions, $this->addedProcedures, $this->addedDomains, $this->addedExtensions))->toSql($this->tableOrderStrategy, $this->viewOrderStrategy, $this->materializedViewOrderStrategy), + ...$this->modifiedSqls(), + ...$this->renamedTableSqls(), + ...$this->dropObjectSqls($this->removedMaterializedViews, $this->removedViews, $this->removedTables, $this->removedProcedures, $this->removedFunctions, $this->removedSequences, $this->removedDomains, $this->removedExtensions), + ]; + } + + public function isEmpty() : bool + { + return $this->addedTables === [] + && $this->removedTables === [] + && $this->modifiedTables === [] + && $this->renamedTables === [] + && $this->addedSequences === [] + && $this->removedSequences === [] + && $this->modifiedSequences === [] + && $this->addedViews === [] + && $this->removedViews === [] + && $this->modifiedViews === [] + && $this->addedMaterializedViews === [] + && $this->removedMaterializedViews === [] + && $this->modifiedMaterializedViews === [] + && $this->addedFunctions === [] + && $this->removedFunctions === [] + && $this->modifiedFunctions === [] + && $this->addedProcedures === [] + && $this->removedProcedures === [] + && $this->modifiedProcedures === [] + && $this->addedDomains === [] + && $this->removedDomains === [] + && $this->modifiedDomains === [] + && $this->addedExtensions === [] + && $this->removedExtensions === [] + && $this->modifiedExtensions === []; + } + + /** + * @param list $materializedViews + * @param list $views + * @param list
$tables + * @param list $procedures + * @param list $functions + * @param list $sequences + * @param list $domains + * @param list $extensions + * + * @return list + */ + private function dropObjectSqls(array $materializedViews, array $views, array $tables, array $procedures, array $functions, array $sequences, array $domains, array $extensions) : array + { + $sqls = []; + + foreach ($materializedViews as $mv) { + $sqls[] = drop()->materializedView($mv->name); + } + + foreach ($views as $view) { + $sqls[] = drop()->view($view->name); + } + + foreach ($tables as $table) { + $sqls[] = drop()->table($table->qualifiedName())->cascade(); + } + + foreach ($procedures as $proc) { + $sqls[] = drop()->procedure($proc->name); + } + + foreach ($functions as $func) { + $sqls[] = drop()->function($func->name); + } + + foreach ($sequences as $seq) { + $sqls[] = drop()->sequence($seq->name); + } + + foreach ($domains as $domain) { + $sqls[] = drop()->domain($domain->name)->cascade(); + } + + foreach ($extensions as $ext) { + $sqls[] = drop()->extension($ext->name); + } + + return $sqls; + } + + /** + * @return list + */ + private function modifiedSqls() : array + { + $sqls = []; + + $diffs = [ + $this->modifiedExtensions, + $this->modifiedDomains, + $this->modifiedSequences, + $this->modifiedFunctions, + $this->modifiedProcedures, + $this->modifiedTables, + $this->modifiedViews, + $this->modifiedMaterializedViews, + ]; + + foreach ($diffs as $diffGroup) { + foreach ($diffGroup as $diff) { + $sqls = [...$sqls, ...$diff->generate()]; + } + } + + return $sqls; + } + + /** + * @return list + */ + private function renamedTableSqls() : array + { + $sqls = []; + + foreach ($this->renamedTables as $oldQualifiedName => $newTable) { + $sqls[] = alter()->table($oldQualifiedName)->renameTo($newTable->name); + } + + return $sqls; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/SequenceDiff.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/SequenceDiff.php new file mode 100644 index 0000000000..2ab6a94de8 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/SequenceDiff.php @@ -0,0 +1,82 @@ + + */ + public function generate() : array + { + $builder = alter()->sequence($this->target->name); + $hasChanges = false; + + if ($this->target->dataType !== $this->source->dataType) { + $builder = $builder->asType($this->target->dataType); + $hasChanges = true; + } + + if ($this->target->incrementBy !== $this->source->incrementBy) { + $builder = $builder->incrementBy((int) $this->target->incrementBy); + $hasChanges = true; + } + + if ($this->target->startValue !== $this->source->startValue) { + $builder = $builder->startWith((int) $this->target->startValue); + $hasChanges = true; + } + + if ($this->target->minValue !== $this->source->minValue) { + $builder = $builder->minValue((int) $this->target->minValue); + $hasChanges = true; + } + + if ($this->target->maxValue !== $this->source->maxValue) { + if ($this->target->maxValue === null) { + $builder = $builder->noMaxValue(); + } else { + $builder = $builder->maxValue((int) $this->target->maxValue); + } + $hasChanges = true; + } + + if ($this->target->cacheValue !== $this->source->cacheValue) { + $builder = $builder->cache((int) $this->target->cacheValue); + $hasChanges = true; + } + + if ($this->target->cycle !== $this->source->cycle) { + $builder = $this->target->cycle ? $builder->cycle() : $builder->noCycle(); + $hasChanges = true; + } + + if ($this->target->ownedByTable !== $this->source->ownedByTable || $this->target->ownedByColumn !== $this->source->ownedByColumn) { + if ($this->target->ownedByTable !== null && $this->target->ownedByColumn !== null) { + $builder = $builder->ownedBy($this->target->ownedByTable, $this->target->ownedByColumn); + } else { + $builder = $builder->ownedByNone(); + } + $hasChanges = true; + } + + if (!$hasChanges) { + return []; + } + + return [$builder]; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/SimilarTextStrategy.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/SimilarTextStrategy.php new file mode 100644 index 0000000000..6e2b96ae6d --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/SimilarTextStrategy.php @@ -0,0 +1,25 @@ +threshold; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/SimilarityStrategy.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/SimilarityStrategy.php new file mode 100644 index 0000000000..b2bb0e9a51 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/SimilarityStrategy.php @@ -0,0 +1,18 @@ +addedName][] = $candidate->removedName; + } + + $matched = []; + $matchedRemoved = []; + + foreach ($candidatesByAdded as $addedName => $removedCandidates) { + if (\count($removedCandidates) !== 1) { + continue; + } + + $removedName = $removedCandidates[0]; + + if (array_key_exists($removedName, $matchedRemoved)) { + continue; + } + + $matched[] = new RenameMatch($addedName, $removedName); + $matchedRemoved[$removedName] = true; + } + + return $matched; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/TableComparator.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/TableComparator.php new file mode 100644 index 0000000000..0418529a9d --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/TableComparator.php @@ -0,0 +1,206 @@ +columns as $col) { + $sourceColumnMap[$col->name] = $col; + } + + $targetColumnMap = []; + + foreach ($target->columns as $col) { + $targetColumnMap[$col->name] = $col; + } + + $addedColumns = []; + $removedColumns = []; + $modifiedColumns = []; + + foreach ($targetColumnMap as $name => $col) { + if (!array_key_exists($name, $sourceColumnMap)) { + $addedColumns[$name] = $col; + } + } + + foreach ($sourceColumnMap as $name => $col) { + if (!array_key_exists($name, $targetColumnMap)) { + $removedColumns[$name] = $col; + } + } + + $this->detectColumnRenames($source->qualifiedName(), $addedColumns, $removedColumns, $modifiedColumns); + + foreach ($sourceColumnMap as $name => $sourceCol) { + if (!array_key_exists($name, $targetColumnMap)) { + continue; + } + + if (!$sourceCol->isEqual($targetColumnMap[$name])) { + $modifiedColumns[] = new ColumnDiff($source->qualifiedName(), $sourceCol, $targetColumnMap[$name]); + } + } + + $indexes = $this->indexComparator->compare($source->indexes, $target->indexes); + $foreignKeys = $this->constraintComparator->diffForeignKeys($source->foreignKeys, $target->foreignKeys); + $uniqueConstraints = $this->constraintComparator->diffUniqueConstraints($source->uniqueConstraints, $target->uniqueConstraints); + $checkConstraints = $this->constraintComparator->diffCheckConstraints($source->checkConstraints, $target->checkConstraints); + $excludeConstraints = $this->constraintComparator->diffExcludeConstraints($source->excludeConstraints, $target->excludeConstraints); + $triggers = $this->diffTriggers($source->triggers, $target->triggers); + + $partitionChanged = $source->partitionStrategy !== $target->partitionStrategy + || $source->partitionColumns !== $target->partitionColumns; + + $sourceInherits = $source->inherits; + $targetInherits = $target->inherits; + \sort($sourceInherits); + \sort($targetInherits); + $addedInherits = \array_values(\array_diff($targetInherits, $sourceInherits)); + $removedInherits = \array_values(\array_diff($sourceInherits, $targetInherits)); + + $tablespaceChanged = $source->tablespace !== $target->tablespace; + + return new TableDiff( + $source, + $target, + \array_values($addedColumns), + \array_values($removedColumns), + $modifiedColumns, + $this->diffPrimaryKeyAdded($source->primaryKey, $target->primaryKey), + $this->diffPrimaryKeyRemoved($source->primaryKey, $target->primaryKey), + $indexes->added, + $indexes->removed, + $indexes->renamed ?? [], + $foreignKeys->added, + $foreignKeys->removed, + $uniqueConstraints->added, + $uniqueConstraints->removed, + $checkConstraints->added, + $checkConstraints->removed, + $excludeConstraints->added, + $excludeConstraints->removed, + $triggers->added, + $triggers->removed, + $source->unlogged !== $target->unlogged, + $partitionChanged, + $addedInherits, + $removedInherits, + $tablespaceChanged, + ); + } + + /** + * @param array $addedColumns + * @param array $removedColumns + * @param list $modifiedColumns + */ + private function detectColumnRenames(string $qualifiedTableName, array &$addedColumns, array &$removedColumns, array &$modifiedColumns) : void + { + $candidates = []; + + foreach ($addedColumns as $addedName => $addedCol) { + foreach ($removedColumns as $removedName => $removedCol) { + if ($addedCol->isEqualStructure($removedCol)) { + $candidates[] = new RenameCandidate($addedName, $removedName); + } + } + } + + foreach ($this->renameStrategy->resolve($candidates) as $match) { + $modifiedColumns[] = new ColumnDiff($qualifiedTableName, $removedColumns[$match->removedName], $addedColumns[$match->addedName]); + unset($addedColumns[$match->addedName], $removedColumns[$match->removedName]); + } + } + + private function diffPrimaryKeyAdded(?PrimaryKey $source, ?PrimaryKey $target) : ?PrimaryKey + { + if ($target === null) { + return null; + } + + if ($source === null) { + return $target; + } + + if ($source->isEqualStructure($target)) { + return null; + } + + return $target; + } + + private function diffPrimaryKeyRemoved(?PrimaryKey $source, ?PrimaryKey $target) : ?PrimaryKey + { + if ($source === null) { + return null; + } + + if ($target === null) { + return $source; + } + + if ($source->isEqualStructure($target)) { + return null; + } + + return $source; + } + + /** + * @param list $sourceTriggers + * @param list $targetTriggers + * + * @return ChangeSet + */ + private function diffTriggers(array $sourceTriggers, array $targetTriggers) : ChangeSet + { + $sourceMap = []; + + foreach ($sourceTriggers as $trigger) { + $sourceMap[$trigger->name] = $trigger; + } + + $targetMap = []; + + foreach ($targetTriggers as $trigger) { + $targetMap[$trigger->name] = $trigger; + } + + $added = []; + $removed = []; + + foreach ($targetMap as $name => $trigger) { + if (!array_key_exists($name, $sourceMap)) { + $added[] = $trigger; + } elseif (!$sourceMap[$name]->isEqual($trigger)) { + $removed[] = $sourceMap[$name]; + $added[] = $trigger; + } + } + + foreach ($sourceMap as $name => $trigger) { + if (!array_key_exists($name, $targetMap)) { + $removed[] = $trigger; + } + } + + return new ChangeSet($added, $removed); + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/TableDiff.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/TableDiff.php new file mode 100644 index 0000000000..c02a5b0c98 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/TableDiff.php @@ -0,0 +1,326 @@ + $addedColumns + * @param list $removedColumns + * @param list $modifiedColumns + * @param list $addedIndexes + * @param list $removedIndexes + * @param array $renamedIndexes + * @param list $addedForeignKeys + * @param list $removedForeignKeys + * @param list $addedUniqueConstraints + * @param list $removedUniqueConstraints + * @param list $addedCheckConstraints + * @param list $removedCheckConstraints + * @param list $addedExcludeConstraints + * @param list $removedExcludeConstraints + * @param list $addedTriggers + * @param list $removedTriggers + * @param list $addedInherits + * @param list $removedInherits + */ + public function __construct( + public Table $source, + public Table $target, + public array $addedColumns = [], + public array $removedColumns = [], + public array $modifiedColumns = [], + public ?PrimaryKey $addedPrimaryKey = null, + public ?PrimaryKey $removedPrimaryKey = null, + public array $addedIndexes = [], + public array $removedIndexes = [], + public array $renamedIndexes = [], + public array $addedForeignKeys = [], + public array $removedForeignKeys = [], + public array $addedUniqueConstraints = [], + public array $removedUniqueConstraints = [], + public array $addedCheckConstraints = [], + public array $removedCheckConstraints = [], + public array $addedExcludeConstraints = [], + public array $removedExcludeConstraints = [], + public array $addedTriggers = [], + public array $removedTriggers = [], + public bool $unloggedChanged = false, + public bool $partitionChanged = false, + public array $addedInherits = [], + public array $removedInherits = [], + public bool $tablespaceChanged = false, + ) { + } + + /** + * @return list + */ + public function generate() : array + { + $sqls = []; + $qualifiedName = $this->target->qualifiedName(); + + if ($this->partitionChanged) { + throw new \RuntimeException(\sprintf( + 'Partition strategy change on table "%s" cannot be applied via ALTER TABLE. The table must be recreated.', + $qualifiedName, + )); + } + + if ($this->unloggedChanged) { + $sqls[] = $this->target->unlogged + ? alter()->table($qualifiedName)->setUnlogged() + : alter()->table($qualifiedName)->setLogged(); + } + + foreach ($this->removedInherits as $parent) { + $sqls[] = alter()->table($qualifiedName)->dropInherit($parent); + } + + foreach ($this->removedForeignKeys as $fk) { + if ($fk->name === null) { + throw new \RuntimeException(\sprintf('Cannot drop unnamed foreign key on table "%s". Constraint names are required for reversible migrations.', $qualifiedName)); + } + $sqls[] = alter()->table($qualifiedName)->dropConstraint($fk->name); + } + + foreach ($this->removedIndexes as $idx) { + $sqls[] = drop()->index($idx->name); + } + + foreach ($this->removedUniqueConstraints as $uc) { + if ($uc->name === null) { + throw new \RuntimeException(\sprintf('Cannot drop unnamed unique constraint on table "%s". Constraint names are required for reversible migrations.', $qualifiedName)); + } + $sqls[] = alter()->table($qualifiedName)->dropConstraint($uc->name); + } + + foreach ($this->removedCheckConstraints as $cc) { + if ($cc->name === null) { + throw new \RuntimeException(\sprintf('Cannot drop unnamed check constraint on table "%s". Constraint names are required for reversible migrations.', $qualifiedName)); + } + $sqls[] = alter()->table($qualifiedName)->dropConstraint($cc->name); + } + + foreach ($this->removedExcludeConstraints as $ec) { + if ($ec->name === null) { + throw new \RuntimeException(\sprintf('Cannot drop unnamed exclude constraint on table "%s". Constraint names are required for reversible migrations.', $qualifiedName)); + } + $sqls[] = alter()->table($qualifiedName)->dropConstraint($ec->name); + } + + if ($this->removedPrimaryKey !== null) { + if ($this->removedPrimaryKey->name === null) { + throw new \RuntimeException(\sprintf('Cannot drop unnamed primary key on table "%s". Constraint names are required for reversible migrations.', $qualifiedName)); + } + $sqls[] = alter()->table($qualifiedName)->dropConstraint($this->removedPrimaryKey->name); + } + + foreach ($this->removedTriggers as $trigger) { + $sqls[] = drop()->trigger($trigger->name)->on($this->target->name, $this->target->schema); + } + + foreach ($this->removedColumns as $col) { + $sqls[] = alter()->table($qualifiedName)->dropColumn($col->name); + } + + foreach ($this->addedColumns as $col) { + $colDef = column($col->name, $col->type); + + if (!$col->nullable) { + $colDef = $colDef->notNull(); + } + + if ($col->default !== null) { + $colDef = $colDef->defaultRaw(ExpressionFactory::fromAst((new ExpressionParser(new Parser()))->parse($col->default))); + } + + if ($col->isIdentity) { + $colDef = $colDef->identity($col->identityGeneration ?? IdentityGeneration::ALWAYS); + } + + if ($col->isGenerated && $col->generationExpression !== null) { + $colDef = $colDef->generatedAs(ExpressionFactory::fromAst((new ExpressionParser(new Parser()))->parse($col->generationExpression))); + } + + $sqls[] = alter()->table($qualifiedName)->addColumn($colDef); + } + + foreach ($this->modifiedColumns as $colDiff) { + $sqls = [...$sqls, ...$colDiff->generate()]; + } + + if ($this->addedPrimaryKey !== null) { + $constraint = PrimaryKeyConstraint::create(...$this->addedPrimaryKey->columns); + + if ($this->addedPrimaryKey->name !== null) { + $constraint = $constraint->name($this->addedPrimaryKey->name); + } + $sqls[] = alter()->table($qualifiedName)->addConstraint($constraint); + } + + foreach ($this->addedIndexes as $idx) { + $builder = create()->index($idx->name); + + if ($idx->unique) { + $builder = $builder->unique(); + } + + $onBuilder = $builder->on($this->target->name, $this->target->schema); + + if ($idx->method !== IndexMethod::BTREE) { + $onBuilder = $onBuilder->using(QbIndexMethod::from($idx->method->value)); + } + + $sqls[] = $onBuilder->columns(...$idx->columns); + } + + foreach ($this->renamedIndexes as $oldName => $newIndex) { + $sqls[] = alter()->index($oldName, $this->target->schema)->renameTo($newIndex->name); + } + + foreach ($this->addedUniqueConstraints as $uc) { + $constraint = UniqueConstraintBuilder::create(...$uc->columns); + + if ($uc->name !== null) { + $constraint = $constraint->name($uc->name); + } + + if ($uc->nullsNotDistinct) { + $constraint = $constraint->nullsNotDistinct(); + } + $sqls[] = alter()->table($qualifiedName)->addConstraint($constraint); + } + + foreach ($this->addedCheckConstraints as $cc) { + $constraint = CheckConstraintBuilder::create(ConditionFactory::fromAst((new ExpressionParser(new Parser()))->parse($cc->expression))); + + if ($cc->name !== null) { + $constraint = $constraint->name($cc->name); + } + + if ($cc->noInherit) { + $constraint = $constraint->noInherit(); + } + $sqls[] = alter()->table($qualifiedName)->addConstraint($constraint); + } + + foreach ($this->addedExcludeConstraints as $ec) { + if ($ec->name === null) { + throw new \RuntimeException(\sprintf('Cannot add unnamed exclude constraint on table "%s". Constraint names are required for reversible migrations.', $qualifiedName)); + } + + $sqls[] = alter()->table($qualifiedName)->addConstraint( + \Flow\PostgreSql\QueryBuilder\Schema\Constraint\ExcludeConstraint::create()->name($ec->name), + ); + } + + foreach ($this->addedForeignKeys as $fk) { + $refTable = $fk->referenceSchema . '.' . $fk->referenceTable; + $constraint = ForeignKeyConstraint::create($fk->columns, $refTable, $fk->referenceColumns) + ->onUpdate($fk->onUpdate) + ->onDelete($fk->onDelete); + + if ($fk->name !== null) { + $constraint = $constraint->name($fk->name); + } + + if ($fk->deferrable) { + $constraint = $constraint->deferrable($fk->initiallyDeferred); + } + + $sqls[] = alter()->table($qualifiedName)->addConstraint($constraint); + } + + foreach ($this->addedTriggers as $trigger) { + $qbEvents = \array_map( + static fn (TriggerEvent $e) : QbTriggerEvent => QbTriggerEvent::{$e->name}, + $trigger->events, + ); + + $triggerBuilder = create()->trigger($trigger->name); + + $onStep = match ($trigger->timing) { + TriggerTiming::BEFORE => $triggerBuilder->before(...$qbEvents), + TriggerTiming::AFTER => $triggerBuilder->after(...$qbEvents), + TriggerTiming::INSTEAD_OF => $triggerBuilder->insteadOf(...$qbEvents), + }; + + $optionsStep = $onStep->on($this->target->name, $this->target->schema); + + if ($trigger->forEachRow) { + $optionsStep = $optionsStep->forEachRow(); + } + + $sqls[] = $optionsStep->execute($trigger->functionName); + } + + foreach ($this->addedInherits as $parent) { + $sqls[] = alter()->table($qualifiedName)->addInherit($parent); + } + + if ($this->tablespaceChanged && $this->target->tablespace !== null) { + $sqls[] = alter()->table($qualifiedName)->setTablespace($this->target->tablespace); + } + + return $sqls; + } + + public function isEmpty() : bool + { + return $this->addedColumns === [] + && $this->removedColumns === [] + && $this->modifiedColumns === [] + && $this->addedPrimaryKey === null + && $this->removedPrimaryKey === null + && $this->addedIndexes === [] + && $this->removedIndexes === [] + && $this->renamedIndexes === [] + && $this->addedForeignKeys === [] + && $this->removedForeignKeys === [] + && $this->addedUniqueConstraints === [] + && $this->removedUniqueConstraints === [] + && $this->addedCheckConstraints === [] + && $this->removedCheckConstraints === [] + && $this->addedExcludeConstraints === [] + && $this->removedExcludeConstraints === [] + && $this->addedTriggers === [] + && $this->removedTriggers === [] + && !$this->unloggedChanged + && !$this->partitionChanged + && $this->addedInherits === [] + && $this->removedInherits === [] + && !$this->tablespaceChanged; + } + + public function requiresViewRebuild() : bool + { + if ($this->removedColumns !== []) { + return true; + } + + foreach ($this->modifiedColumns as $colDiff) { + if ($colDiff->hasTypeChanged() || $colDiff->hasNameChanged()) { + return true; + } + } + + return false; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/TableStructureComparator.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/TableStructureComparator.php new file mode 100644 index 0000000000..058f205119 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/TableStructureComparator.php @@ -0,0 +1,188 @@ + $added + * @param list
$removed + * + * @return ChangeSet + */ + public function detectTableRenames(array $added, array $removed) : ChangeSet + { + $addedMap = []; + + foreach ($added as $table) { + $addedMap[$table->name] = $table; + } + + $removedMap = []; + + foreach ($removed as $table) { + $removedMap[$table->name] = $table; + } + + $candidates = []; + + foreach ($addedMap as $addedName => $addedTable) { + foreach ($removedMap as $removedName => $removedTable) { + if ($this->haveEqualStructure($addedTable, $removedTable)) { + $candidates[] = new RenameCandidate($addedName, $removedName); + } + } + } + + $renamed = []; + + foreach ($this->renameStrategy->resolve($candidates) as $match) { + $renamed[$removedMap[$match->removedName]->qualifiedName()] = $addedMap[$match->addedName]; + unset($addedMap[$match->addedName], $removedMap[$match->removedName]); + } + + return new ChangeSet( + \array_values($addedMap), + \array_values($removedMap), + renamed: $renamed !== [] ? $renamed : null, + ); + } + + public function haveEqualStructure(Table $a, Table $b) : bool + { + if ($a->schema !== $b->schema) { + return false; + } + + if ($a->unlogged !== $b->unlogged + || $a->partitionStrategy !== $b->partitionStrategy + || $a->tablespace !== $b->tablespace) { + return false; + } + + $aPartCols = $a->partitionColumns; + $bPartCols = $b->partitionColumns; + \sort($aPartCols); + \sort($bPartCols); + + if ($aPartCols !== $bPartCols) { + return false; + } + + $aInherits = $a->inherits; + $bInherits = $b->inherits; + \sort($aInherits); + \sort($bInherits); + + if ($aInherits !== $bInherits) { + return false; + } + + if (!$this->columnListsEqual($a->columns, $b->columns)) { + return false; + } + + if (!$this->primaryKeysStructurallyEqual($a->primaryKey, $b->primaryKey)) { + return false; + } + + return $this->listsStructurallyEqual($a->indexes, $b->indexes, static fn ($x, $y) => $x->isEqualStructure($y)) + && $this->listsStructurallyEqual($a->foreignKeys, $b->foreignKeys, static fn ($x, $y) => $x->isEqualStructure($y)) + && $this->listsStructurallyEqual($a->uniqueConstraints, $b->uniqueConstraints, static fn ($x, $y) => $x->isEqualStructure($y)) + && $this->listsStructurallyEqual($a->checkConstraints, $b->checkConstraints, static fn ($x, $y) => $x->isEqualStructure($y)) + && $this->listsStructurallyEqual($a->excludeConstraints, $b->excludeConstraints, static fn ($x, $y) => $x->isEqualStructure($y)) + && $this->listsStructurallyEqual($a->triggers, $b->triggers, static fn ($x, $y) => $x->isEqualStructure($y)); + } + + /** + * @param list $a + * @param list $b + */ + private function columnListsEqual(array $a, array $b) : bool + { + if (\count($a) !== \count($b)) { + return false; + } + + $mapA = []; + + foreach ($a as $col) { + $mapA[$col->name] = $col; + } + + $mapB = []; + + foreach ($b as $col) { + $mapB[$col->name] = $col; + } + + if (\count($mapA) !== \count($mapB)) { + return false; + } + + foreach ($mapA as $name => $colA) { + if (!array_key_exists($name, $mapB)) { + return false; + } + + if (!$colA->isEqualStructure($mapB[$name])) { + return false; + } + } + + return true; + } + + /** + * @template T + * + * @param list $a + * @param list $b + * @param callable(T, T): bool $equalsFn + */ + private function listsStructurallyEqual(array $a, array $b, callable $equalsFn) : bool + { + if (\count($a) !== \count($b)) { + return false; + } + + $matched = []; + + foreach ($a as $itemA) { + foreach ($b as $j => $itemB) { + if (!array_key_exists($j, $matched) && $equalsFn($itemA, $itemB)) { + $matched[$j] = true; + + continue 2; + } + } + + return false; + } + + return true; + } + + private function primaryKeysStructurallyEqual(?PrimaryKey $a, ?PrimaryKey $b) : bool + { + if ($a === null && $b === null) { + return true; + } + + if ($a === null || $b === null) { + return false; + } + + return $a->isEqualStructure($b); + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/ViewDependencyResolver.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/ViewDependencyResolver.php new file mode 100644 index 0000000000..b4071685f5 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/ViewDependencyResolver.php @@ -0,0 +1,15 @@ + $modifiedTableQualifiedNames + */ + public function resolve(Catalog $catalog, array $modifiedTableQualifiedNames) : DependentViews; +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/ViewDiff.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/ViewDiff.php new file mode 100644 index 0000000000..768fe10e5a --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Diff/ViewDiff.php @@ -0,0 +1,27 @@ + + */ + public function generate() : array + { + return [create()->view($this->target->name)->orReplace()->as(parsed_select($this->target->definition))]; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Domain.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Domain.php new file mode 100644 index 0000000000..6a09716be4 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Domain.php @@ -0,0 +1,92 @@ +} + */ +final readonly class Domain +{ + /** + * @param list $checkConstraints + */ + public function __construct( + public string $name, + public ColumnType $baseType, + public bool $nullable = true, + public ?string $default = null, + public array $checkConstraints = [], + ) { + } + + /** + * @param DomainShape $data + */ + public static function fromArray(array $data) : self + { + return new self( + name: $data['name'], + baseType: ColumnType::fromArray($data['base_type']), + nullable: $data['nullable'] ?? true, + default: $data['default'] ?? null, + checkConstraints: \array_map( + static fn (array $cc) : CheckConstraint => CheckConstraint::fromArray($cc), + $data['check_constraints'] ?? [], + ), + ); + } + + /** + * @return DomainShape + */ + public function normalize() : array + { + return [ + 'name' => $this->name, + 'base_type' => $this->baseType->normalize(), + 'nullable' => $this->nullable, + 'default' => $this->default, + 'check_constraints' => \array_map( + static fn (CheckConstraint $cc) : array => $cc->normalize(), + $this->checkConstraints, + ), + ]; + } + + public function toSql() : Sql + { + $builder = create()->domain($this->name)->as($this->baseType); + + if (!$this->nullable) { + $builder = $builder->notNull(); + } + + if ($this->default !== null) { + $builder = $builder->default(ExpressionFactory::fromAst((new ExpressionParser(new Parser()))->parse($this->default))); + } + + foreach ($this->checkConstraints as $cc) { + if ($cc->name !== null) { + $builder = $builder->constraint($cc->name); + } + $builder = $builder->check(ConditionFactory::fromAst((new ExpressionParser(new Parser()))->parse($cc->expression))); + } + + return $builder; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Exception/ColumnNotFoundException.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Exception/ColumnNotFoundException.php new file mode 100644 index 0000000000..59029d2099 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Exception/ColumnNotFoundException.php @@ -0,0 +1,13 @@ + $items + * + * @return list + */ + public function order(array $items) : array; +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Extension.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Extension.php new file mode 100644 index 0000000000..53469f8cdc --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Extension.php @@ -0,0 +1,54 @@ + $this->name, + 'version' => $this->version, + ]; + } + + public function toSql() : Sql + { + $builder = create()->extension($this->name); + + if ($this->version !== null) { + $builder = $builder->version($this->version); + } + + return $builder; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/ForeignKeyDependencyOrder.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/ForeignKeyDependencyOrder.php new file mode 100644 index 0000000000..911c53f4e0 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/ForeignKeyDependencyOrder.php @@ -0,0 +1,105 @@ + + */ +final readonly class ForeignKeyDependencyOrder implements ExecutionOrderStrategy +{ + /** + * Orders tables so that referenced tables come before tables that reference them. + * Uses Kahn's algorithm for topological sorting. + * + * @param list
$items + * + * @throws SchemaException when circular foreign key dependencies are detected + * + * @return list
+ */ + public function order(array $items) : array + { + if (\count($items) <= 1) { + return $items; + } + + $tablesByQualifiedName = []; + + foreach ($items as $table) { + $tablesByQualifiedName[$table->qualifiedName()] = $table; + } + + /** @var array> $dependsOn qualified name → list of qualified names it depends on */ + $dependsOn = []; + /** @var array $inDegree */ + $inDegree = []; + + foreach ($tablesByQualifiedName as $qualifiedName => $table) { + $inDegree[$qualifiedName] ??= 0; + $dependsOn[$qualifiedName] = []; + + foreach ($table->foreignKeys as $fk) { + $refQualified = $fk->referenceSchema . '.' . $fk->referenceTable; + + if ($refQualified === $qualifiedName) { + continue; + } + + if (!array_key_exists($refQualified, $tablesByQualifiedName)) { + continue; + } + + $dependsOn[$qualifiedName][] = $refQualified; + $inDegree[$refQualified] ??= 0; + $inDegree[$qualifiedName]++; + } + } + + $queue = []; + + foreach ($inDegree as $name => $degree) { + if ($degree === 0) { + $queue[] = $name; + } + } + + $sorted = []; + + while ($queue !== []) { + $current = \array_shift($queue); + $sorted[] = $tablesByQualifiedName[$current]; + + foreach ($tablesByQualifiedName as $name => $table) { + if (\in_array($current, $dependsOn[$name], true)) { + $dependsOn[$name] = \array_values(\array_filter( + $dependsOn[$name], + static fn (string $dep) : bool => $dep !== $current, + )); + $inDegree[$name]--; + + if ($inDegree[$name] === 0) { + $queue[] = $name; + } + } + } + } + + if (\count($sorted) !== \count($tablesByQualifiedName)) { + $unsorted = \array_diff(\array_keys($tablesByQualifiedName), \array_map( + static fn (Table $t) : string => $t->qualifiedName(), + $sorted, + )); + + throw new SchemaException(\sprintf( + 'Circular foreign key dependency detected between tables: %s. Use deferred constraints to handle circular references.', + \implode(', ', $unsorted), + )); + } + + return $sorted; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Func.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Func.php new file mode 100644 index 0000000000..27ff7f8e54 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Func.php @@ -0,0 +1,96 @@ +, language: string, definition: ?string, is_strict: bool, volatility: ?string} + */ +final readonly class Func +{ + /** + * @param list $argumentTypes + */ + public function __construct( + public string $name, + public string $returnType, + public array $argumentTypes = [], + public string $language = 'sql', + public ?string $definition = null, + public bool $isStrict = false, + public ?FunctionVolatility $volatility = null, + ) { + } + + /** + * @param FuncShape $data + */ + public static function fromArray(array $data) : self + { + return new self( + name: $data['name'], + returnType: $data['return_type'], + argumentTypes: $data['argument_types'] ?? [], + language: $data['language'] ?? 'sql', + definition: $data['definition'] ?? null, + isStrict: $data['is_strict'] ?? false, + volatility: array_key_exists('volatility', $data) && $data['volatility'] !== null ? FunctionVolatility::from($data['volatility']) : null, + ); + } + + /** + * @return FuncShape + */ + public function normalize() : array + { + return [ + 'name' => $this->name, + 'return_type' => $this->returnType, + 'argument_types' => $this->argumentTypes, + 'language' => $this->language, + 'definition' => $this->definition, + 'is_strict' => $this->isStrict, + 'volatility' => $this->volatility?->value, + ]; + } + + public function toSql() : ?Sql + { + if ($this->definition === null) { + return null; + } + + $builder = create()->function($this->name)->orReplace(); + + if ($this->argumentTypes !== []) { + $args = \array_map( + static fn (string $type) : FunctionArgument => FunctionArgument::of(column_type_from_string($type)), + $this->argumentTypes, + ); + $builder = $builder->arguments(...$args); + } + + $builder = $builder->returns(column_type_from_string($this->returnType)) + ->language($this->language); + + if ($this->isStrict) { + $builder = $builder->strict(); + } + + if ($this->volatility !== null) { + $builder = match ($this->volatility) { + FunctionVolatility::IMMUTABLE => $builder->immutable(), + FunctionVolatility::STABLE => $builder->stable(), + FunctionVolatility::VOLATILE => $builder->volatile(), + }; + } + + return $builder->as($this->definition); + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/FunctionVolatility.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/FunctionVolatility.php new file mode 100644 index 0000000000..f177e994ca --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/FunctionVolatility.php @@ -0,0 +1,12 @@ +, unique: bool, method: string, primary: bool, predicate: ?string} + */ +final readonly class Index +{ + /** + * @param non-empty-list $columns + */ + public function __construct( + public string $name, + public array $columns, + public bool $unique = false, + public IndexMethod $method = IndexMethod::BTREE, + public bool $primary = false, + public ?string $predicate = null, + ) { + } + + /** + * @param IndexShape $data + */ + public static function fromArray(array $data) : self + { + return new self( + name: $data['name'], + columns: $data['columns'], + unique: $data['unique'] ?? false, + method: array_key_exists('method', $data) ? IndexMethod::from($data['method']) : IndexMethod::BTREE, + primary: $data['primary'] ?? false, + predicate: $data['predicate'] ?? null, + ); + } + + public function isEqual(self $other) : bool + { + return $this->name === $other->name && $this->isEqualStructure($other); + } + + public function isEqualStructure(self $other) : bool + { + return $this->columns === $other->columns + && $this->unique === $other->unique + && $this->method === $other->method + && $this->primary === $other->primary + && $this->predicate === $other->predicate; + } + + /** + * @return IndexShape + */ + public function normalize() : array + { + return [ + 'name' => $this->name, + 'columns' => $this->columns, + 'unique' => $this->unique, + 'method' => $this->method->value, + 'primary' => $this->primary, + 'predicate' => $this->predicate, + ]; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/IndexMethod.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/IndexMethod.php new file mode 100644 index 0000000000..aef2e6f028 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/IndexMethod.php @@ -0,0 +1,15 @@ +catalog; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/MaterializedView.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/MaterializedView.php new file mode 100644 index 0000000000..c54f2ef2fa --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/MaterializedView.php @@ -0,0 +1,86 @@ +} + */ +final readonly class MaterializedView +{ + /** + * @param list $indexes + */ + public function __construct( + public string $name, + public string $definition, + public array $indexes = [], + ) { + } + + /** + * @param MaterializedViewShape $data + */ + public static function fromArray(array $data) : self + { + return new self( + name: $data['name'], + definition: $data['definition'], + indexes: \array_map( + static fn (array $index) : Index => Index::fromArray($index), + $data['indexes'] ?? [], + ), + ); + } + + /** + * @return MaterializedViewShape + */ + public function normalize() : array + { + return [ + 'name' => $this->name, + 'definition' => $this->definition, + 'indexes' => \array_map( + static fn (Index $index) : array => $index->normalize(), + $this->indexes, + ), + ]; + } + + /** + * @return list + */ + public function toSql() : array + { + $sqls = []; + + $sqls[] = create()->materializedView($this->name)->as(parsed_select($this->definition)); + + foreach ($this->indexes as $idx) { + $builder = create()->index($idx->name); + + if ($idx->unique) { + $builder = $builder->unique(); + } + + $onBuilder = $builder->on($this->name); + + if ($idx->method !== IndexMethod::BTREE) { + $onBuilder = $onBuilder->using(QbIndexMethod::from($idx->method->value)); + } + + $sqls[] = $onBuilder->columns(...$idx->columns); + } + + return $sqls; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/MaterializedViewDependencyOrder.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/MaterializedViewDependencyOrder.php new file mode 100644 index 0000000000..4ee0daa1a2 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/MaterializedViewDependencyOrder.php @@ -0,0 +1,121 @@ + + */ +final readonly class MaterializedViewDependencyOrder implements ExecutionOrderStrategy +{ + public function __construct(private Parser $parser) + { + } + + /** + * @param list $items + * + * @throws SchemaException when circular materialized view dependencies are detected + * + * @return list + */ + public function order(array $items) : array + { + if (\count($items) <= 1) { + return $items; + } + + $viewsByName = []; + + foreach ($items as $view) { + $viewsByName[$view->name] = $view; + } + + /** @var array> $dependsOn */ + $dependsOn = []; + /** @var array $inDegree */ + $inDegree = []; + + foreach ($viewsByName as $name => $view) { + $inDegree[$name] ??= 0; + $dependsOn[$name] = []; + + foreach ($this->extractReferencedNames($view->definition) as $refName) { + if ($refName === $name) { + continue; + } + + if (!array_key_exists($refName, $viewsByName)) { + continue; + } + + $dependsOn[$name][] = $refName; + $inDegree[$refName] ??= 0; + $inDegree[$name]++; + } + } + + $queue = []; + + foreach ($inDegree as $name => $degree) { + if ($degree === 0) { + $queue[] = $name; + } + } + + $sorted = []; + + while ($queue !== []) { + $current = \array_shift($queue); + $sorted[] = $viewsByName[$current]; + + foreach ($viewsByName as $name => $view) { + if (\in_array($current, $dependsOn[$name], true)) { + $dependsOn[$name] = \array_values(\array_filter( + $dependsOn[$name], + static fn (string $dep) : bool => $dep !== $current, + )); + $inDegree[$name]--; + + if ($inDegree[$name] === 0) { + $queue[] = $name; + } + } + } + } + + if (\count($sorted) !== \count($viewsByName)) { + $unsorted = \array_diff(\array_keys($viewsByName), \array_map( + static fn (MaterializedView $v) : string => $v->name, + $sorted, + )); + + throw new SchemaException(\sprintf( + 'Circular dependency detected between materialized views: %s.', + \implode(', ', $unsorted), + )); + } + + return $sorted; + } + + /** + * @return list + */ + private function extractReferencedNames(string $definition) : array + { + $tables = (new Tables($this->parser->parse($definition)))->all(); + $names = []; + + foreach ($tables as $table) { + $names[] = $table->name(); + } + + return $names; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/NoExecutionOrder.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/NoExecutionOrder.php new file mode 100644 index 0000000000..4539b90be1 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/NoExecutionOrder.php @@ -0,0 +1,18 @@ + + */ +final readonly class NoExecutionOrder implements ExecutionOrderStrategy +{ + public function order(array $items) : array + { + return $items; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/PartitionStrategy.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/PartitionStrategy.php new file mode 100644 index 0000000000..914f03bba4 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/PartitionStrategy.php @@ -0,0 +1,12 @@ +, language: string, definition: ?string} + */ +final readonly class Procedure +{ + /** + * @param list $argumentTypes + */ + public function __construct( + public string $name, + public array $argumentTypes = [], + public string $language = 'sql', + public ?string $definition = null, + ) { + } + + /** + * @param ProcedureShape $data + */ + public static function fromArray(array $data) : self + { + return new self( + name: $data['name'], + argumentTypes: $data['argument_types'] ?? [], + language: $data['language'] ?? 'sql', + definition: $data['definition'] ?? null, + ); + } + + /** + * @return ProcedureShape + */ + public function normalize() : array + { + return [ + 'name' => $this->name, + 'argument_types' => $this->argumentTypes, + 'language' => $this->language, + 'definition' => $this->definition, + ]; + } + + public function toSql() : ?Sql + { + if ($this->definition === null) { + return null; + } + + $builder = create()->procedure($this->name)->orReplace(); + + if ($this->argumentTypes !== []) { + $args = \array_map( + static fn (string $type) : FunctionArgument => FunctionArgument::of(column_type_from_string($type)), + $this->argumentTypes, + ); + $builder = $builder->arguments(...$args); + } + + return $builder->language($this->language)->as($this->definition); + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Schema.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Schema.php new file mode 100644 index 0000000000..96bee3f014 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Schema.php @@ -0,0 +1,287 @@ +, sequences: list, views: list, materialized_views: list, functions: list, procedures: list, domains: list, extensions: list} + */ +final readonly class Schema +{ + /** + * @param list
$tables + * @param list $sequences + * @param list $views + * @param list $materializedViews + * @param list $functions + * @param list $procedures + * @param list $domains + * @param list $extensions + */ + public function __construct( + public string $name, + public array $tables = [], + public array $sequences = [], + public array $views = [], + public array $materializedViews = [], + public array $functions = [], + public array $procedures = [], + public array $domains = [], + public array $extensions = [], + ) { + } + + /** + * @param SchemaShape $data + */ + public static function fromArray(array $data) : self + { + return new self( + name: $data['name'], + tables: \array_map( + static function (array $t) use ($data) : Table { + if (!\array_key_exists('schema', $t)) { + $t['schema'] = $data['name']; + } + + return Table::fromArray($t); + }, + $data['tables'] ?? [], + ), + sequences: \array_map( + static fn (array $s) : Sequence => Sequence::fromArray($s), + $data['sequences'] ?? [], + ), + views: \array_map( + static fn (array $v) : View => View::fromArray($v), + $data['views'] ?? [], + ), + materializedViews: \array_map( + static fn (array $mv) : MaterializedView => MaterializedView::fromArray($mv), + $data['materialized_views'] ?? [], + ), + functions: \array_map( + static fn (array $f) : Func => Func::fromArray($f), + $data['functions'] ?? [], + ), + procedures: \array_map( + static fn (array $p) : Procedure => Procedure::fromArray($p), + $data['procedures'] ?? [], + ), + domains: \array_map( + static fn (array $d) : Domain => Domain::fromArray($d), + $data['domains'] ?? [], + ), + extensions: \array_map( + static fn (array $e) : Extension => Extension::fromArray($e), + $data['extensions'] ?? [], + ), + ); + } + + public function hasSequence(string $name) : bool + { + foreach ($this->sequences as $sequence) { + if ($sequence->name === $name) { + return true; + } + } + + return false; + } + + public function hasTable(string $name) : bool + { + foreach ($this->tables as $table) { + if ($table->name === $name) { + return true; + } + } + + return false; + } + + public function merge(self $other) : self + { + return new self( + name: $this->name, + tables: self::mergeByName($this->tables, $other->tables), + sequences: self::mergeByName($this->sequences, $other->sequences), + views: self::mergeByName($this->views, $other->views), + materializedViews: self::mergeByName($this->materializedViews, $other->materializedViews), + functions: self::mergeByName($this->functions, $other->functions), + procedures: self::mergeByName($this->procedures, $other->procedures), + domains: self::mergeByName($this->domains, $other->domains), + extensions: self::mergeByName($this->extensions, $other->extensions), + ); + } + + /** + * @return SchemaShape + */ + public function normalize() : array + { + return [ + 'name' => $this->name, + 'tables' => \array_map( + static fn (Table $t) : array => $t->normalize(), + $this->tables, + ), + 'sequences' => \array_map( + static fn (Sequence $s) : array => $s->normalize(), + $this->sequences, + ), + 'views' => \array_map( + static fn (View $v) : array => $v->normalize(), + $this->views, + ), + 'materialized_views' => \array_map( + static fn (MaterializedView $mv) : array => $mv->normalize(), + $this->materializedViews, + ), + 'functions' => \array_map( + static fn (Func $f) : array => $f->normalize(), + $this->functions, + ), + 'procedures' => \array_map( + static fn (Procedure $p) : array => $p->normalize(), + $this->procedures, + ), + 'domains' => \array_map( + static fn (Domain $d) : array => $d->normalize(), + $this->domains, + ), + 'extensions' => \array_map( + static fn (Extension $e) : array => $e->normalize(), + $this->extensions, + ), + ]; + } + + public function sequence(string $name) : Sequence + { + foreach ($this->sequences as $sequence) { + if ($sequence->name === $name) { + return $sequence; + } + } + + throw new SchemaException(\sprintf('Sequence "%s" not found in schema "%s".', $name, $this->name)); + } + + public function table(string $name) : Table + { + foreach ($this->tables as $table) { + if ($table->name === $name) { + return $table; + } + } + + throw TableNotFoundException::inSchema($name, $this->name); + } + + /** + * @return list + */ + public function tableNames() : array + { + return \array_map( + static fn (Table $t) : string => $t->name, + $this->tables, + ); + } + + /** + * @param ExecutionOrderStrategy
$tableOrderStrategy + * @param ExecutionOrderStrategy $viewOrderStrategy + * @param ExecutionOrderStrategy $materializedViewOrderStrategy + * + * @return list + */ + public function toSql( + ExecutionOrderStrategy $tableOrderStrategy = new ForeignKeyDependencyOrder(), + ExecutionOrderStrategy $viewOrderStrategy = new ViewDependencyOrder(new Parser()), + ExecutionOrderStrategy $materializedViewOrderStrategy = new MaterializedViewDependencyOrder(new Parser()), + ) : array { + $sqls = []; + + foreach ($this->extensions as $ext) { + $sqls[] = $ext->toSql(); + } + + foreach ($this->domains as $domain) { + $sqls[] = $domain->toSql(); + } + + foreach ($this->sequences as $seq) { + $sqls[] = $seq->toSql(); + } + + foreach ($this->functions as $func) { + $sql = $func->toSql(); + + if ($sql !== null) { + $sqls[] = $sql; + } + } + + foreach ($this->procedures as $proc) { + $sql = $proc->toSql(); + + if ($sql !== null) { + $sqls[] = $sql; + } + } + + foreach ($tableOrderStrategy->order($this->tables) as $table) { + $sqls = [...$sqls, ...$table->toSql()]; + } + + foreach ($viewOrderStrategy->order($this->views) as $view) { + $sqls[] = $view->toSql(); + } + + foreach ($materializedViewOrderStrategy->order($this->materializedViews) as $mv) { + $sqls = [...$sqls, ...$mv->toSql()]; + } + + return $sqls; + } + + /** + * @template T of object{name: string} + * + * @param list $base + * @param list $override + * + * @return list + */ + private static function mergeByName(array $base, array $override) : array + { + $indexed = []; + + foreach ($base as $item) { + $indexed[$item->name] = $item; + } + + foreach ($override as $item) { + $indexed[$item->name] = $item; + } + + return \array_values($indexed); + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Sequence.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Sequence.php new file mode 100644 index 0000000000..3a3b339922 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Sequence.php @@ -0,0 +1,93 @@ + $this->name, + 'data_type' => $this->dataType, + 'start_value' => $this->startValue, + 'min_value' => $this->minValue, + 'max_value' => $this->maxValue, + 'increment_by' => $this->incrementBy, + 'cycle' => $this->cycle, + 'cache_value' => $this->cacheValue, + 'owned_by_table' => $this->ownedByTable, + 'owned_by_column' => $this->ownedByColumn, + ]; + } + + public function toSql() : Sql + { + $builder = create()->sequence($this->name) + ->asType($this->dataType) + ->startWith((int) $this->startValue) + ->incrementBy((int) $this->incrementBy) + ->minValue((int) $this->minValue) + ->cache((int) $this->cacheValue); + + if ($this->maxValue !== null) { + $builder = $builder->maxValue((int) $this->maxValue); + } else { + $builder = $builder->noMaxValue(); + } + + if ($this->cycle) { + $builder = $builder->cycle(); + } + + if ($this->ownedByTable !== null && $this->ownedByColumn !== null) { + $builder = $builder->ownedBy($this->ownedByTable, $this->ownedByColumn); + } + + return $builder; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Table.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Table.php new file mode 100644 index 0000000000..bab6726797 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Table.php @@ -0,0 +1,339 @@ +, primary_key: ?PrimaryKeyShape, indexes: list, foreign_keys: list, unique_constraints: list, check_constraints: list, exclude_constraints: list, triggers: list, unlogged: bool, partition_strategy: ?string, partition_columns: list, inherits: list, tablespace: ?string} + */ +final readonly class Table +{ + /** + * @param non-empty-list $columns + * @param list $indexes + * @param list $foreignKeys + * @param list $uniqueConstraints + * @param list $checkConstraints + * @param list $excludeConstraints + * @param list $triggers + * @param list $partitionColumns + * @param list $inherits + */ + public function __construct( + public string $schema, + public string $name, + public array $columns, + public ?PrimaryKey $primaryKey = null, + public array $indexes = [], + public array $foreignKeys = [], + public array $uniqueConstraints = [], + public array $checkConstraints = [], + public array $excludeConstraints = [], + public array $triggers = [], + public bool $unlogged = false, + public ?PartitionStrategy $partitionStrategy = null, + public array $partitionColumns = [], + public array $inherits = [], + public ?string $tablespace = null, + ) { + } + + /** + * @param TableShape $data + */ + public static function fromArray(array $data) : self + { + return new self( + schema: $data['schema'] ?? 'public', + name: $data['name'], + columns: \array_map( + static fn (array $col) : Column => Column::fromArray($col), + $data['columns'], + ), + primaryKey: array_key_exists('primary_key', $data) && $data['primary_key'] !== null + ? PrimaryKey::fromArray($data['primary_key']) + : null, + indexes: \array_map( + static fn (array $idx) : Index => Index::fromArray($idx), + $data['indexes'] ?? [], + ), + foreignKeys: \array_map( + static fn (array $fk) : ForeignKey => ForeignKey::fromArray($fk), + $data['foreign_keys'] ?? [], + ), + uniqueConstraints: \array_map( + static fn (array $uc) : UniqueConstraint => UniqueConstraint::fromArray($uc), + $data['unique_constraints'] ?? [], + ), + checkConstraints: \array_map( + static fn (array $cc) : CheckConstraint => CheckConstraint::fromArray($cc), + $data['check_constraints'] ?? [], + ), + excludeConstraints: \array_map( + static fn (array $ec) : ExcludeConstraint => ExcludeConstraint::fromArray($ec), + $data['exclude_constraints'] ?? [], + ), + triggers: \array_map( + static fn (array $t) : Trigger => Trigger::fromArray($t), + $data['triggers'] ?? [], + ), + unlogged: $data['unlogged'] ?? false, + partitionStrategy: array_key_exists('partition_strategy', $data) && $data['partition_strategy'] !== null ? PartitionStrategy::from($data['partition_strategy']) : null, + partitionColumns: $data['partition_columns'] ?? [], + inherits: $data['inherits'] ?? [], + tablespace: $data['tablespace'] ?? null, + ); + } + + public function column(string $name) : Column + { + foreach ($this->columns as $column) { + if ($column->name === $name) { + return $column; + } + } + + throw ColumnNotFoundException::inTable($name, $this->name); + } + + /** + * @return list + */ + public function columnNames() : array + { + return \array_map( + static fn (Column $c) : string => $c->name, + $this->columns, + ); + } + + public function hasColumn(string $name) : bool + { + foreach ($this->columns as $column) { + if ($column->name === $name) { + return true; + } + } + + return false; + } + + /** + * @return TableShape + */ + public function normalize() : array + { + return [ + 'schema' => $this->schema, + 'name' => $this->name, + 'columns' => \array_map( + static fn (Column $col) : array => $col->normalize(), + $this->columns, + ), + 'primary_key' => $this->primaryKey?->normalize(), + 'indexes' => \array_map( + static fn (Index $idx) : array => $idx->normalize(), + $this->indexes, + ), + 'foreign_keys' => \array_map( + static fn (ForeignKey $fk) : array => $fk->normalize(), + $this->foreignKeys, + ), + 'unique_constraints' => \array_map( + static fn (UniqueConstraint $uc) : array => $uc->normalize(), + $this->uniqueConstraints, + ), + 'check_constraints' => \array_map( + static fn (CheckConstraint $cc) : array => $cc->normalize(), + $this->checkConstraints, + ), + 'exclude_constraints' => \array_map( + static fn (ExcludeConstraint $ec) : array => $ec->normalize(), + $this->excludeConstraints, + ), + 'triggers' => \array_map( + static fn (Trigger $t) : array => $t->normalize(), + $this->triggers, + ), + 'unlogged' => $this->unlogged, + 'partition_strategy' => $this->partitionStrategy?->value, + 'partition_columns' => $this->partitionColumns, + 'inherits' => $this->inherits, + 'tablespace' => $this->tablespace, + ]; + } + + public function qualifiedName() : string + { + return $this->schema . '.' . $this->name; + } + + /** + * @return list + */ + public function toSql() : array + { + $sqls = []; + + $tableBuilder = create()->table($this->name, $this->schema); + + foreach ($this->columns as $col) { + $colDef = column($col->name, $col->type); + + if (!$col->nullable) { + $colDef = $colDef->notNull(); + } + + if ($col->default !== null) { + $colDef = $colDef->defaultRaw(ExpressionFactory::fromAst((new ExpressionParser(new Parser()))->parse($col->default))); + } + + if ($col->isIdentity) { + $colDef = $colDef->identity($col->identityGeneration ?? IdentityGeneration::ALWAYS); + } + + if ($col->isGenerated && $col->generationExpression !== null) { + $colDef = $colDef->generatedAs(ExpressionFactory::fromAst((new ExpressionParser(new Parser()))->parse($col->generationExpression))); + } + + $tableBuilder = $tableBuilder->column($colDef); + } + + if ($this->primaryKey !== null) { + $pk = PrimaryKeyConstraint::create(...$this->primaryKey->columns); + + if ($this->primaryKey->name !== null) { + $pk = $pk->name($this->primaryKey->name); + } + $tableBuilder = $tableBuilder->constraint($pk); + } + + foreach ($this->uniqueConstraints as $uc) { + $constraint = UniqueConstraintBuilder::create(...$uc->columns); + + if ($uc->name !== null) { + $constraint = $constraint->name($uc->name); + } + + if ($uc->nullsNotDistinct) { + $constraint = $constraint->nullsNotDistinct(); + } + $tableBuilder = $tableBuilder->constraint($constraint); + } + + foreach ($this->checkConstraints as $cc) { + $constraint = CheckConstraintBuilder::create(ConditionFactory::fromAst((new ExpressionParser(new Parser()))->parse($cc->expression))); + + if ($cc->name !== null) { + $constraint = $constraint->name($cc->name); + } + + if ($cc->noInherit) { + $constraint = $constraint->noInherit(); + } + $tableBuilder = $tableBuilder->constraint($constraint); + } + + foreach ($this->foreignKeys as $fk) { + $refTable = $fk->referenceSchema . '.' . $fk->referenceTable; + $constraint = ForeignKeyConstraint::create($fk->columns, $refTable, $fk->referenceColumns) + ->onUpdate($fk->onUpdate) + ->onDelete($fk->onDelete); + + if ($fk->name !== null) { + $constraint = $constraint->name($fk->name); + } + + if ($fk->deferrable) { + $constraint = $constraint->deferrable($fk->initiallyDeferred); + } + $tableBuilder = $tableBuilder->constraint($constraint); + } + + if ($this->unlogged) { + $tableBuilder = $tableBuilder->unlogged(); + } + + if ($this->partitionStrategy !== null && $this->partitionColumns !== []) { + $tableBuilder = match ($this->partitionStrategy) { + PartitionStrategy::HASH => $tableBuilder->partitionByHash(...$this->partitionColumns), + PartitionStrategy::LIST => $tableBuilder->partitionByList(...$this->partitionColumns), + PartitionStrategy::RANGE => $tableBuilder->partitionByRange(...$this->partitionColumns), + }; + } + + if ($this->inherits !== []) { + $tableBuilder = $tableBuilder->inherits(...$this->inherits); + } + + if ($this->tablespace !== null) { + $tableBuilder = $tableBuilder->tablespace($this->tablespace); + } + + $sqls[] = $tableBuilder; + + foreach ($this->indexes as $idx) { + $builder = create()->index($idx->name); + + if ($idx->unique) { + $builder = $builder->unique(); + } + + $onBuilder = $builder->on($this->name, $this->schema); + + if ($idx->method !== IndexMethod::BTREE) { + $onBuilder = $onBuilder->using(QbIndexMethod::from($idx->method->value)); + } + + $sqls[] = $onBuilder->columns(...$idx->columns); + } + + foreach ($this->triggers as $trigger) { + $qbEvents = \array_map( + static fn (TriggerEvent $e) : QbTriggerEvent => QbTriggerEvent::{$e->name}, + $trigger->events, + ); + + $triggerBuilder = create()->trigger($trigger->name); + + $onStep = match ($trigger->timing) { + TriggerTiming::BEFORE => $triggerBuilder->before(...$qbEvents), + TriggerTiming::AFTER => $triggerBuilder->after(...$qbEvents), + TriggerTiming::INSTEAD_OF => $triggerBuilder->insteadOf(...$qbEvents), + }; + + $optionsStep = $onStep->on($this->name, $this->schema); + + if ($trigger->forEachRow) { + $optionsStep = $optionsStep->forEachRow(); + } + + $sqls[] = $optionsStep->execute($trigger->functionName); + } + + return $sqls; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/Trigger.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Trigger.php new file mode 100644 index 0000000000..1ac4b8781a --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/Trigger.php @@ -0,0 +1,79 @@ +, function_name: string, for_each_row: bool, when_condition: ?string} + */ +final readonly class Trigger +{ + /** + * @param non-empty-list $events + */ + public function __construct( + public string $name, + public string $tableName, + public TriggerTiming $timing, + public array $events, + public string $functionName, + public bool $forEachRow = false, + public ?string $whenCondition = null, + ) { + } + + /** + * @param TriggerShape $data + */ + public static function fromArray(array $data) : self + { + return new self( + name: $data['name'], + tableName: $data['table_name'], + timing: TriggerTiming::from($data['timing']), + events: \array_map( + static fn (string $event) : TriggerEvent => TriggerEvent::from($event), + $data['events'], + ), + functionName: $data['function_name'], + forEachRow: $data['for_each_row'] ?? false, + whenCondition: $data['when_condition'] ?? null, + ); + } + + public function isEqual(self $other) : bool + { + return $this->name === $other->name + && $this->tableName === $other->tableName + && $this->isEqualStructure($other); + } + + public function isEqualStructure(self $other) : bool + { + return $this->timing === $other->timing + && $this->events === $other->events + && $this->functionName === $other->functionName + && $this->forEachRow === $other->forEachRow + && $this->whenCondition === $other->whenCondition; + } + + /** + * @return TriggerShape + */ + public function normalize() : array + { + return [ + 'name' => $this->name, + 'table_name' => $this->tableName, + 'timing' => $this->timing->value, + 'events' => \array_map( + static fn (TriggerEvent $event) : string => $event->value, + $this->events, + ), + 'function_name' => $this->functionName, + 'for_each_row' => $this->forEachRow, + 'when_condition' => $this->whenCondition, + ]; + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/TriggerEvent.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/TriggerEvent.php new file mode 100644 index 0000000000..14ec90c2de --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/TriggerEvent.php @@ -0,0 +1,13 @@ + $this->name, + 'definition' => $this->definition, + 'is_updatable' => $this->isUpdatable, + ]; + } + + public function toSql() : Sql + { + return create()->view($this->name)->as(parsed_select($this->definition)); + } +} diff --git a/src/lib/postgresql/src/Flow/PostgreSql/Schema/ViewDependencyOrder.php b/src/lib/postgresql/src/Flow/PostgreSql/Schema/ViewDependencyOrder.php new file mode 100644 index 0000000000..a360ca8e49 --- /dev/null +++ b/src/lib/postgresql/src/Flow/PostgreSql/Schema/ViewDependencyOrder.php @@ -0,0 +1,121 @@ + + */ +final readonly class ViewDependencyOrder implements ExecutionOrderStrategy +{ + public function __construct(private Parser $parser) + { + } + + /** + * @param list $items + * + * @throws SchemaException when circular view dependencies are detected + * + * @return list + */ + public function order(array $items) : array + { + if (\count($items) <= 1) { + return $items; + } + + $viewsByName = []; + + foreach ($items as $view) { + $viewsByName[$view->name] = $view; + } + + /** @var array> $dependsOn */ + $dependsOn = []; + /** @var array $inDegree */ + $inDegree = []; + + foreach ($viewsByName as $name => $view) { + $inDegree[$name] ??= 0; + $dependsOn[$name] = []; + + foreach ($this->extractReferencedNames($view->definition) as $refName) { + if ($refName === $name) { + continue; + } + + if (!array_key_exists($refName, $viewsByName)) { + continue; + } + + $dependsOn[$name][] = $refName; + $inDegree[$refName] ??= 0; + $inDegree[$name]++; + } + } + + $queue = []; + + foreach ($inDegree as $name => $degree) { + if ($degree === 0) { + $queue[] = $name; + } + } + + $sorted = []; + + while ($queue !== []) { + $current = \array_shift($queue); + $sorted[] = $viewsByName[$current]; + + foreach ($viewsByName as $name => $view) { + if (\in_array($current, $dependsOn[$name], true)) { + $dependsOn[$name] = \array_values(\array_filter( + $dependsOn[$name], + static fn (string $dep) : bool => $dep !== $current, + )); + $inDegree[$name]--; + + if ($inDegree[$name] === 0) { + $queue[] = $name; + } + } + } + } + + if (\count($sorted) !== \count($viewsByName)) { + $unsorted = \array_diff(\array_keys($viewsByName), \array_map( + static fn (View $v) : string => $v->name, + $sorted, + )); + + throw new SchemaException(\sprintf( + 'Circular view dependency detected between views: %s.', + \implode(', ', $unsorted), + )); + } + + return $sorted; + } + + /** + * @return list + */ + private function extractReferencedNames(string $definition) : array + { + $tables = (new Tables($this->parser->parse($definition)))->all(); + $names = []; + + foreach ($tables as $table) { + $names[] = $table->name(); + } + + return $names; + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Double/FailingMigration.php b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Double/FailingMigration.php new file mode 100644 index 0000000000..0f6013a7be --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Double/FailingMigration.php @@ -0,0 +1,20 @@ +catalog; + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Double/FakeMigrationRepository.php b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Double/FakeMigrationRepository.php new file mode 100644 index 0000000000..899b3b3515 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Double/FakeMigrationRepository.php @@ -0,0 +1,33 @@ +migrations = new AvailableMigrations(...$migrations); + } + + public function all() : AvailableMigrations + { + return $this->migrations; + } + + public function get(Version $version) : AvailableMigration + { + return $this->migrations->get($version); + } + + public function has(Version $version) : bool + { + return $this->migrations->has($version); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Double/FakeMigrationStore.php b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Double/FakeMigrationStore.php new file mode 100644 index 0000000000..04bd90b275 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Double/FakeMigrationStore.php @@ -0,0 +1,52 @@ + + */ + private array $migrations = []; + + public function complete(Version $version, int $executionTimeMs) : void + { + $this->migrations[(string) $version] = new ExecutedMigration( + $version, + new \DateTimeImmutable(), + $executionTimeMs, + ); + } + + public function executedMigrations() : ExecutedMigrations + { + return new ExecutedMigrations(...\array_values($this->migrations)); + } + + public function initialize() : void + { + $this->initialized = true; + } + + public function isInitialized() : bool + { + return $this->initialized; + } + + public function remove(Version $version) : void + { + unset($this->migrations[(string) $version]); + } + + public function reset() : void + { + $this->migrations = []; + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Double/FixedVersionGenerator.php b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Double/FixedVersionGenerator.php new file mode 100644 index 0000000000..21948415e2 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Double/FixedVersionGenerator.php @@ -0,0 +1,20 @@ +version; + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Double/NonTransactionalMigration.php b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Double/NonTransactionalMigration.php new file mode 100644 index 0000000000..c043b40b4a --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Double/NonTransactionalMigration.php @@ -0,0 +1,22 @@ +migrateCalled = true; + } + + public function transactional() : bool + { + return false; + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Double/NonTransactionalRollback.php b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Double/NonTransactionalRollback.php new file mode 100644 index 0000000000..c59592aa4e --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Double/NonTransactionalRollback.php @@ -0,0 +1,22 @@ +rollbackCalled = true; + } + + public function transactional() : bool + { + return false; + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Double/SpyClient.php b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Double/SpyClient.php new file mode 100644 index 0000000000..4a453a02ff --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Double/SpyClient.php @@ -0,0 +1,167 @@ +}> + */ + public array $executedQueries = []; + + public int $transactionCallCount = 0; + + public int $transactionLevel = 0; + + public function beginTransaction() : void + { + $this->transactionLevel++; + } + + public function close() : void + { + throw new \RuntimeException('Not implemented'); + } + + public function commit() : void + { + $this->transactionLevel--; + } + + public function converters() : ValueConverters + { + throw new \RuntimeException('Not implemented'); + } + + public function cursor(Sql|string $sql, array $parameters = []) : Cursor + { + throw new \RuntimeException('Not implemented'); + } + + public function execute(Sql|string $sql, array $parameters = []) : int + { + $this->executedQueries[] = ['sql' => $sql instanceof Sql ? $sql->toSql() : $sql, 'parameters' => $parameters]; + + return 0; + } + + public function explain(Sql|string $sql, array $parameters = [], ?ExplainConfig $config = null) : Plan + { + throw new \RuntimeException('Not implemented'); + } + + public function fetch(Sql|string $sql, array $parameters = []) : ?array + { + throw new \RuntimeException('Not implemented'); + } + + public function fetchAll(Sql|string $sql, array $parameters = []) : array + { + throw new \RuntimeException('Not implemented'); + } + + public function fetchAllInto(RowMapper $mapper, Sql|string $sql, array $parameters = []) : array + { + throw new \RuntimeException('Not implemented'); + } + + public function fetchInto(RowMapper $mapper, Sql|string $sql, array $parameters = []) : mixed + { + throw new \RuntimeException('Not implemented'); + } + + public function fetchOne(Sql|string $sql, array $parameters = []) : array + { + throw new \RuntimeException('Not implemented'); + } + + public function fetchOneInto(RowMapper $mapper, Sql|string $sql, array $parameters = []) : mixed + { + throw new \RuntimeException('Not implemented'); + } + + public function fetchScalar(Sql|string $sql, array $parameters = []) : mixed + { + throw new \RuntimeException('Not implemented'); + } + + public function fetchScalarBool(Sql|string $sql, array $parameters = []) : bool + { + throw new \RuntimeException('Not implemented'); + } + + public function fetchScalarFloat(Sql|string $sql, array $parameters = []) : float + { + throw new \RuntimeException('Not implemented'); + } + + public function fetchScalarInt(Sql|string $sql, array $parameters = []) : int + { + throw new \RuntimeException('Not implemented'); + } + + public function fetchScalarString(Sql|string $sql, array $parameters = []) : string + { + throw new \RuntimeException('Not implemented'); + } + + public function getTransactionNestingLevel() : int + { + return $this->transactionLevel; + } + + public function isAutoCommit() : bool + { + throw new \RuntimeException('Not implemented'); + } + + public function isConnected() : bool + { + throw new \RuntimeException('Not implemented'); + } + + public function lastInsertId(string $sequenceName) : int|string + { + throw new \RuntimeException('Not implemented'); + } + + public function parameters() : ConnectionParameters + { + throw new \RuntimeException('Not implemented'); + } + + public function rollBack() : void + { + $this->transactionLevel--; + } + + public function setAutoCommit(bool $autoCommit) : void + { + throw new \RuntimeException('Not implemented'); + } + + public function transaction(callable $callback) : mixed + { + $this->transactionCallCount++; + $this->beginTransaction(); + + try { + $result = $callback($this); + $this->commit(); + + return $result; + } catch (\Throwable $e) { + $this->rollBack(); + + throw $e; + } + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Double/SpyMigration.php b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Double/SpyMigration.php new file mode 100644 index 0000000000..9739dcc178 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Double/SpyMigration.php @@ -0,0 +1,22 @@ +migrateCalled = true; + } + + public function transactional() : bool + { + return true; + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Double/SpyMigrationExecutor.php b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Double/SpyMigrationExecutor.php new file mode 100644 index 0000000000..6ae4feec9e --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Double/SpyMigrationExecutor.php @@ -0,0 +1,23 @@ + + */ + public array $executedPlans = []; + + public function execute(MigrationPlan $plan, MigrationContext $context) : ExecutionResult + { + $this->executedPlans[] = $plan; + + return new ExecutionResult($plan->version, $plan->direction, 0, false, null); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Double/SpyMigrationGenerator.php b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Double/SpyMigrationGenerator.php new file mode 100644 index 0000000000..96be79b638 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Double/SpyMigrationGenerator.php @@ -0,0 +1,46 @@ + + */ + public ?array $lastDownSql = null; + + public ?string $lastSchemaName = null; + + /** + * @var ?list + */ + public ?array $lastUpSql = null; + + public function __construct( + public Version $returnVersion, + ) { + } + + public function generateDataMigration(?string $name = null) : Version + { + $this->lastDataName = $name; + + return $this->returnVersion; + } + + public function generateSchemaMigration(?string $name, array $upSql, ?array $downSql = null) : Version + { + $this->lastSchemaName = $name; + $this->lastUpSql = $upSql; + $this->lastDownSql = $downSql; + + return $this->returnVersion; + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Double/SpyRollback.php b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Double/SpyRollback.php new file mode 100644 index 0000000000..09e4de22e3 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Double/SpyRollback.php @@ -0,0 +1,22 @@ +rollbackCalled = true; + } + + public function transactional() : bool + { + return true; + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Double/TemporaryDirectory.php b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Double/TemporaryDirectory.php new file mode 100644 index 0000000000..af42fba616 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Double/TemporaryDirectory.php @@ -0,0 +1,39 @@ +path = \sys_get_temp_dir() . '/flow_migrations_test_' . \uniqid(); + \mkdir($this->path, 0755, true); + } + + public function cleanUp() : void + { + if (!\is_dir($this->path)) { + return; + } + + $iterator = new \RecursiveIteratorIterator( + new \RecursiveDirectoryIterator($this->path, \RecursiveDirectoryIterator::SKIP_DOTS), + \RecursiveIteratorIterator::CHILD_FIRST, + ); + + /** @var \SplFileInfo $file */ + foreach ($iterator as $file) { + if ($file->isDir()) { + \rmdir($file->getPathname()); + } else { + \unlink($file->getPathname()); + } + } + + \rmdir($this->path); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Fixture/migrations/20260401120000_create_users/migration.php b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Fixture/migrations/20260401120000_create_users/migration.php new file mode 100644 index 0000000000..c3b783e29b --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Fixture/migrations/20260401120000_create_users/migration.php @@ -0,0 +1,17 @@ +client->execute('CREATE TABLE users (id SERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL)'); + } + + public function transactional() : bool + { + return true; + } +}; diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Fixture/migrations/20260401120000_create_users/rollback.php b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Fixture/migrations/20260401120000_create_users/rollback.php new file mode 100644 index 0000000000..91742b3bf1 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Fixture/migrations/20260401120000_create_users/rollback.php @@ -0,0 +1,17 @@ +client->execute('DROP TABLE users'); + } + + public function transactional() : bool + { + return true; + } +}; diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Fixture/migrations/20260402100000_seed_data/migration.php b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Fixture/migrations/20260402100000_seed_data/migration.php new file mode 100644 index 0000000000..6f4d905717 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Fixture/migrations/20260402100000_seed_data/migration.php @@ -0,0 +1,17 @@ +client->execute("INSERT INTO users (name) VALUES ('seed')"); + } + + public function transactional() : bool + { + return true; + } +}; diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Fixture/migrations/20260402100000_seed_data/rollback.php b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Fixture/migrations/20260402100000_seed_data/rollback.php new file mode 100644 index 0000000000..2973a2e909 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Fixture/migrations/20260402100000_seed_data/rollback.php @@ -0,0 +1,17 @@ +client->execute("DELETE FROM users WHERE name = 'seed'"); + } + + public function transactional() : bool + { + return true; + } +}; diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Fixture/migrations/20260403090000_add_column/migration.php b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Fixture/migrations/20260403090000_add_column/migration.php new file mode 100644 index 0000000000..e450697b6b --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Fixture/migrations/20260403090000_add_column/migration.php @@ -0,0 +1,17 @@ +client->execute('ALTER TABLE users ADD COLUMN email VARCHAR(255)'); + } + + public function transactional() : bool + { + return true; + } +}; diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Integration/MigratorTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Integration/MigratorTest.php new file mode 100644 index 0000000000..f4338afcc4 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Integration/MigratorTest.php @@ -0,0 +1,209 @@ +context = new PostgreSqlMigrationsContext(); + $this->configuration = new Configuration( + client: $this->context->client, + targetCatalogProvider: new FakeCatalogProvider(new Catalog([])), + migrationsDirectory: __DIR__ . '/../Fixture/migrations', + migrationsNamespace: 'Flow\\PostgreSql\\Migrations\\Tests\\Fixture', + tableName: 'flow_migrations_test', + tableSchema: 'public', + ); + $this->store = new PostgreSqlMigrationStore($this->context->client, $this->configuration); + + $this->context->dropTableIfExists('public.flow_migrations_test'); + $this->context->dropTableIfExists('public.users'); + } + + protected function tearDown() : void + { + $this->context->dropTableIfExists('public.flow_migrations_test'); + $this->context->dropTableIfExists('public.users'); + $this->context->close(); + } + + public function test_all_or_nothing_rolls_back_on_failure() : void + { + $repository = new FakeMigrationRepository( + new AvailableMigration(Version::fromString('20260501120000'), 'good', new SpyMigration(), null), + new AvailableMigration(Version::fromString('20260502120000'), 'bad', new FailingMigration(), null), + ); + + $migrator = new Migrator( + $repository, + $this->store, + new DefaultMigrationExecutor(), + $this->context->client, + $this->configuration, + ); + + try { + $migrator->migrate(allOrNothing: true); + } catch (\Throwable) { + } + + self::assertCount(0, $this->store->executedMigrations()); + } + + public function test_dry_run_does_not_persist() : void + { + $migrator = new Migrator( + $this->fixtureRepository(), + $this->store, + new DefaultMigrationExecutor(), + $this->context->client, + $this->configuration, + ); + + $results = $migrator->migrate( + Version::fromString('20260401120000'), + dryRun: true, + ); + + self::assertCount(1, $results); + self::assertTrue($results[0]->isSuccessful()); + self::assertCount(0, $this->store->executedMigrations()); + } + + public function test_execute_version_runs_single_migration() : void + { + $migrator = new Migrator( + $this->fixtureRepository(), + $this->store, + new DefaultMigrationExecutor(), + $this->context->client, + $this->configuration, + ); + + $result = $migrator->executeVersion(Version::fromString('20260401120000'), Direction::UP); + + self::assertTrue($result->isSuccessful()); + self::assertCount(1, $this->store->executedMigrations()); + } + + public function test_migrate_down_to_specific_version() : void + { + $migrator = new Migrator( + $this->fixtureRepository(), + $this->store, + new DefaultMigrationExecutor(), + $this->context->client, + $this->configuration, + ); + + $migrator->migrate(Version::fromString('20260402100000')); + + self::assertCount(2, $this->store->executedMigrations()); + + $results = $migrator->migrate(Version::fromString('20260401120000')); + + self::assertCount(1, $results); + self::assertSame(Direction::DOWN, $results[0]->direction); + self::assertCount(1, $this->store->executedMigrations()); + } + + public function test_migrate_up_from_empty_state() : void + { + $migrator = new Migrator( + $this->fixtureRepository(), + $this->store, + new DefaultMigrationExecutor(), + $this->context->client, + $this->configuration, + ); + + $results = $migrator->migrate(); + + self::assertCount(3, $results); + + foreach ($results as $result) { + self::assertTrue($result->isSuccessful()); + self::assertSame(Direction::UP, $result->direction); + } + + self::assertCount(3, $this->store->executedMigrations()); + } + + public function test_migrate_up_to_specific_version() : void + { + $migrator = new Migrator( + $this->fixtureRepository(), + $this->store, + new DefaultMigrationExecutor(), + $this->context->client, + $this->configuration, + ); + + $results = $migrator->migrate(Version::fromString('20260402100000')); + + self::assertCount(2, $results); + self::assertCount(2, $this->store->executedMigrations()); + } + + public function test_status_returns_correct_states() : void + { + $migrator = new Migrator( + $this->fixtureRepository(), + $this->store, + new DefaultMigrationExecutor(), + $this->context->client, + $this->configuration, + ); + + $migrator->migrate(Version::fromString('20260401120000')); + + $status = $migrator->status(); + + self::assertCount(3, $status); + self::assertCount(1, $status->executed()); + self::assertCount(2, $status->pending()); + } + + private function fixtureRepository() : FakeMigrationRepository + { + $fixturesPath = __DIR__ . '/../Fixture/migrations'; + + return new FakeMigrationRepository( + new AvailableMigration( + Version::fromString('20260401120000'), + 'create_users', + require $fixturesPath . '/20260401120000_create_users/migration.php', + require $fixturesPath . '/20260401120000_create_users/rollback.php', + ), + new AvailableMigration( + Version::fromString('20260402100000'), + 'seed_data', + require $fixturesPath . '/20260402100000_seed_data/migration.php', + require $fixturesPath . '/20260402100000_seed_data/rollback.php', + ), + new AvailableMigration( + Version::fromString('20260403090000'), + 'add_column', + require $fixturesPath . '/20260403090000_add_column/migration.php', + null, + ), + ); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Integration/PostgreSqlMigrationsContext.php b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Integration/PostgreSqlMigrationsContext.php new file mode 100644 index 0000000000..b1fb13ff92 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Integration/PostgreSqlMigrationsContext.php @@ -0,0 +1,35 @@ +client = pgsql_client(pgsql_connection_dsn($dsn)); + } + + public function close() : void + { + $this->client->close(); + } + + public function dropTableIfExists(string $table) : void + { + $this->client->execute(drop()->table($table)->ifExists()->cascade()->toSql()); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Integration/Store/PostgreSqlMigrationStoreTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Integration/Store/PostgreSqlMigrationStoreTest.php new file mode 100644 index 0000000000..83d97cd66f --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Integration/Store/PostgreSqlMigrationStoreTest.php @@ -0,0 +1,126 @@ +context = new PostgreSqlMigrationsContext(); + $this->configuration = new Configuration( + client: $this->context->client, + targetCatalogProvider: new FakeCatalogProvider(new Catalog([])), + migrationsDirectory: __DIR__, + migrationsNamespace: 'Flow\\PostgreSql\\Migrations\\Tests\\Integration\\Store', + tableName: 'flow_migrations_test', + tableSchema: 'public', + ); + $this->store = new PostgreSqlMigrationStore($this->context->client, $this->configuration); + + $this->context->dropTableIfExists('public.flow_migrations_test'); + } + + protected function tearDown() : void + { + $this->context->dropTableIfExists('public.flow_migrations_test'); + $this->context->close(); + } + + public function test_complete_inserts_record() : void + { + $this->store->initialize(); + + $version = Version::fromString('20260403120000'); + $this->store->complete($version, 150); + + $executed = $this->store->executedMigrations(); + + self::assertCount(1, $executed); + self::assertTrue($executed->has($version)); + self::assertSame(150, $executed->get($version)->executionTimeMs); + } + + public function test_executed_migrations_returns_sorted_results() : void + { + $this->store->initialize(); + + $this->store->complete(Version::fromString('20260403140000'), 300); + $this->store->complete(Version::fromString('20260403120000'), 100); + $this->store->complete(Version::fromString('20260403130000'), 200); + + $executed = $this->store->executedMigrations(); + + $versions = []; + + foreach ($executed as $migration) { + $versions[] = (string) $migration->version; + } + + self::assertSame(['20260403120000', '20260403130000', '20260403140000'], $versions); + } + + public function test_initialize_creates_table() : void + { + $this->store->initialize(); + + self::assertTrue($this->store->isInitialized()); + } + + public function test_is_initialized_returns_false_before_init() : void + { + self::assertFalse($this->store->isInitialized()); + } + + public function test_is_initialized_returns_true_after_init() : void + { + self::assertFalse($this->store->isInitialized()); + + $this->store->initialize(); + + self::assertTrue($this->store->isInitialized()); + } + + public function test_remove_deletes_record() : void + { + $this->store->initialize(); + + $version = Version::fromString('20260403120000'); + $this->store->complete($version, 150); + + self::assertCount(1, $this->store->executedMigrations()); + + $this->store->remove($version); + + self::assertCount(0, $this->store->executedMigrations()); + } + + public function test_reset_clears_all_records() : void + { + $this->store->initialize(); + + $this->store->complete(Version::fromString('20260403120000'), 100); + $this->store->complete(Version::fromString('20260403130000'), 200); + + self::assertCount(2, $this->store->executedMigrations()); + + $this->store->reset(); + + self::assertCount(0, $this->store->executedMigrations()); + self::assertTrue($this->store->executedMigrations()->isEmpty()); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/ConfigurationTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/ConfigurationTest.php new file mode 100644 index 0000000000..451086b18e --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/ConfigurationTest.php @@ -0,0 +1,54 @@ +client); + self::assertSame($catalog, $config->targetCatalogProvider); + self::assertSame('/app/migrations', $config->migrationsDirectory); + self::assertSame('App\\Migrations', $config->migrationsNamespace); + self::assertSame('custom_migrations', $config->tableName); + self::assertSame('app', $config->tableSchema); + self::assertFalse($config->allOrNothing); + self::assertFalse($config->generateRollback); + } + + public function test_default_values() : void + { + $config = new Configuration( + client: new SpyClient(), + targetCatalogProvider: new FakeCatalogProvider(new Catalog([])), + migrationsDirectory: '/app/migrations', + migrationsNamespace: 'App\\Migrations', + ); + + self::assertSame('flow_migrations', $config->tableName); + self::assertSame('public', $config->tableSchema); + self::assertFalse($config->allOrNothing); + self::assertTrue($config->generateRollback); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/Exception/MigrationExceptionTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/Exception/MigrationExceptionTest.php new file mode 100644 index 0000000000..976ef807be --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/Exception/MigrationExceptionTest.php @@ -0,0 +1,86 @@ +getMessage()); + self::assertStringContainsString('not found', $exception->getMessage()); + } + + public function test_invalid_configuration_file() : void + { + $exception = MigrationException::invalidConfigurationFile('/path/to/config.php'); + + self::assertStringContainsString('/path/to/config.php', $exception->getMessage()); + self::assertStringContainsString('Configuration', $exception->getMessage()); + } + + public function test_invalid_data_migration() : void + { + $exception = MigrationException::invalidDataMigration('/path/to/file.php'); + + self::assertSame('Data migration file "/path/to/file.php" must return an instance of Migration.', $exception->getMessage()); + } + + public function test_invalid_rollback() : void + { + $exception = MigrationException::invalidRollback('/path/to/file.php'); + + self::assertSame('Rollback file "/path/to/file.php" must return an instance of Rollback.', $exception->getMessage()); + } + + public function test_invalid_version_format() : void + { + $exception = MigrationException::invalidVersionFormat('abc'); + + self::assertSame('Invalid migration version format: "abc". Expected non-empty alphanumeric string (max 255 chars).', $exception->getMessage()); + } + + public function test_irreversible_migration() : void + { + $exception = MigrationException::irreversibleMigration(Version::fromString('20260403120000')); + + self::assertSame('Migration "20260403120000" is irreversible and cannot be rolled back.', $exception->getMessage()); + } + + public function test_migration_failed() : void + { + $previous = new \RuntimeException('Connection lost'); + $exception = MigrationException::migrationFailed(Version::fromString('20260403120000'), $previous); + + self::assertSame('Migration "20260403120000" failed: Connection lost', $exception->getMessage()); + self::assertSame($previous, $exception->getPrevious()); + } + + public function test_missing_migration_file() : void + { + $exception = MigrationException::missingMigrationFile('/path/to/dir'); + + self::assertSame('Migration directory "/path/to/dir" must contain migration.php.', $exception->getMessage()); + } + + public function test_no_changes_detected() : void + { + $exception = MigrationException::noChangesDetected(); + + self::assertSame('No changes detected between source and target catalog.', $exception->getMessage()); + } + + public function test_version_not_found() : void + { + $exception = MigrationException::versionNotFound(Version::fromString('20260403120000')); + + self::assertSame('Migration version "20260403120000" not found.', $exception->getMessage()); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/ExecutedMigrationTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/ExecutedMigrationTest.php new file mode 100644 index 0000000000..1bcc07f572 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/ExecutedMigrationTest.php @@ -0,0 +1,34 @@ +equals($executed->version)); + self::assertSame($executedAt, $executed->executedAt); + self::assertSame(150, $executed->executionTimeMs); + } + + public function test_construction_with_null_execution_time() : void + { + $executed = new ExecutedMigration( + Version::fromString('20260403120000'), + new \DateTimeImmutable('2026-04-03 12:00:00'), + null, + ); + + self::assertNull($executed->executionTimeMs); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/Executor/DefaultMigrationExecutorTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/Executor/DefaultMigrationExecutorTest.php new file mode 100644 index 0000000000..4ad24f4fc1 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/Executor/DefaultMigrationExecutorTest.php @@ -0,0 +1,213 @@ +execute($plan, new MigrationContext(new SpyClient())); + + self::assertFalse($result->isSuccessful()); + self::assertInstanceOf(\RuntimeException::class, $result->error); + self::assertSame('Migration failed', $result->error->getMessage()); + } + + public function test_execute_down_calls_rollback() : void + { + $executor = new DefaultMigrationExecutor(); + $rollback = new SpyRollback(); + $plan = new MigrationPlan( + Version::fromString('20260401120000'), + new SpyMigration(), + $rollback, + Direction::DOWN, + ); + + $result = $executor->execute($plan, new MigrationContext(new SpyClient())); + + self::assertTrue($rollback->rollbackCalled); + self::assertTrue($result->isSuccessful()); + self::assertSame(Direction::DOWN, $result->direction); + } + + public function test_execute_down_calls_rollback_in_transaction_when_transactional() : void + { + $executor = new DefaultMigrationExecutor(); + $rollback = new SpyRollback(); + $client = new SpyClient(); + $plan = new MigrationPlan( + Version::fromString('20260401120000'), + new SpyMigration(), + $rollback, + Direction::DOWN, + ); + + $result = $executor->execute($plan, new MigrationContext($client)); + + self::assertTrue($rollback->rollbackCalled); + self::assertTrue($result->isSuccessful()); + self::assertSame(1, $client->transactionCallCount); + } + + public function test_execute_down_calls_rollback_without_transaction_when_not_transactional() : void + { + $executor = new DefaultMigrationExecutor(); + $rollback = new NonTransactionalRollback(); + $client = new SpyClient(); + $plan = new MigrationPlan( + Version::fromString('20260401120000'), + new SpyMigration(), + $rollback, + Direction::DOWN, + ); + + $result = $executor->execute($plan, new MigrationContext($client)); + + self::assertTrue($rollback->rollbackCalled); + self::assertTrue($result->isSuccessful()); + self::assertSame(0, $client->transactionCallCount); + } + + public function test_execute_down_without_rollback_returns_error() : void + { + $executor = new DefaultMigrationExecutor(); + $plan = new MigrationPlan( + Version::fromString('20260401120000'), + new SpyMigration(), + null, + Direction::DOWN, + ); + + $result = $executor->execute($plan, new MigrationContext(new SpyClient())); + + self::assertFalse($result->isSuccessful()); + self::assertInstanceOf(MigrationException::class, $result->error); + } + + public function test_execute_up_calls_migrate() : void + { + $executor = new DefaultMigrationExecutor(); + $migration = new SpyMigration(); + $plan = new MigrationPlan( + Version::fromString('20260401120000'), + $migration, + null, + Direction::UP, + ); + + $result = $executor->execute($plan, new MigrationContext(new SpyClient())); + + self::assertTrue($migration->migrateCalled); + self::assertTrue($result->isSuccessful()); + self::assertSame(Direction::UP, $result->direction); + } + + public function test_execute_up_calls_migrate_in_transaction_when_transactional() : void + { + $executor = new DefaultMigrationExecutor(); + $migration = new SpyMigration(); + $client = new SpyClient(); + $plan = new MigrationPlan( + Version::fromString('20260401120000'), + $migration, + null, + Direction::UP, + ); + + $result = $executor->execute($plan, new MigrationContext($client)); + + self::assertTrue($migration->migrateCalled); + self::assertTrue($result->isSuccessful()); + self::assertSame(1, $client->transactionCallCount); + } + + public function test_execute_up_calls_migrate_without_transaction_when_not_transactional() : void + { + $executor = new DefaultMigrationExecutor(); + $migration = new NonTransactionalMigration(); + $client = new SpyClient(); + $plan = new MigrationPlan( + Version::fromString('20260401120000'), + $migration, + null, + Direction::UP, + ); + + $result = $executor->execute($plan, new MigrationContext($client)); + + self::assertTrue($migration->migrateCalled); + self::assertTrue($result->isSuccessful()); + self::assertSame(0, $client->transactionCallCount); + } + + public function test_execution_time_is_recorded() : void + { + $executor = new DefaultMigrationExecutor(); + $plan = new MigrationPlan( + Version::fromString('20260401120000'), + new SpyMigration(), + null, + Direction::UP, + ); + + $result = $executor->execute($plan, new MigrationContext(new SpyClient())); + + self::assertGreaterThanOrEqual(0, $result->executionTimeMs); + } + + public function test_failed_result_is_not_successful() : void + { + $result = new ExecutionResult( + Version::fromString('20260401120000'), + Direction::UP, + 0, + false, + new \RuntimeException('error'), + ); + + self::assertFalse($result->isSuccessful()); + } + + public function test_skipped_result_is_not_successful() : void + { + $result = new ExecutionResult( + Version::fromString('20260401120000'), + Direction::UP, + 0, + true, + null, + ); + + self::assertFalse($result->isSuccessful()); + } + + public function test_successful_result_is_successful() : void + { + $result = new ExecutionResult( + Version::fromString('20260401120000'), + Direction::UP, + 0, + false, + null, + ); + + self::assertTrue($result->isSuccessful()); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/Generator/DiffMigrationGeneratorTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/Generator/DiffMigrationGeneratorTest.php new file mode 100644 index 0000000000..fa76ae4e5b --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/Generator/DiffMigrationGeneratorTest.php @@ -0,0 +1,179 @@ +generate('create_users'); + + self::assertNotEmpty($spy->lastUpSql); + self::assertNull($spy->lastDownSql); + } + + public function test_does_not_throw_when_no_changes_and_allow_empty_is_true() : void + { + $catalog = new Catalog([]); + $spy = new SpyMigrationGenerator(Version::fromString('20260403120000')); + + $diffGenerator = new DiffMigrationGenerator( + new FakeCatalogProvider($catalog), + new FakeCatalogProvider($catalog), + CatalogComparator::create(), + $spy, + ); + + $result = $diffGenerator->generate('empty_migration', allowEmpty: true); + + self::assertTrue($result->equals(Version::fromString('20260403120000'))); + self::assertSame([], $spy->lastUpSql); + self::assertSame([], $spy->lastDownSql); + } + + public function test_from_empty_schema_uses_empty_catalog_as_source() : void + { + $sourceCatalogWithData = new Catalog([ + new Schema('public', [ + new Table('public', 'existing_table', [ + new Column('id', ColumnType::integer(), false), + ]), + ]), + ]); + + $target = new Catalog([ + new Schema('public', [ + new Table('public', 'existing_table', [ + new Column('id', ColumnType::integer(), false), + ]), + new Table('public', 'new_table', [ + new Column('id', ColumnType::integer(), false), + ]), + ]), + ]); + + $version = Version::fromString('20260403120000'); + $spy = new SpyMigrationGenerator($version); + + $diffGenerator = new DiffMigrationGenerator( + new FakeCatalogProvider($sourceCatalogWithData), + new FakeCatalogProvider($target), + CatalogComparator::create(), + $spy, + ); + + $diffGenerator->generate('initial_schema', fromEmptySchema: true); + + $upSqlJoined = \implode(' ', $spy->lastUpSql ?? []); + self::assertStringContainsString('new_table', $upSqlJoined); + self::assertStringContainsString('existing_table', $upSqlJoined); + } + + public function test_generated_sql_content_comes_from_catalog_diff() : void + { + $source = new Catalog([]); + $target = new Catalog([ + new Schema('public', [ + new Table('public', 'users', [ + new Column('id', ColumnType::integer(), false), + new Column('name', ColumnType::text(), true), + ]), + ]), + ]); + + $version = Version::fromString('20260403120000'); + $spy = new SpyMigrationGenerator($version); + + $diffGenerator = new DiffMigrationGenerator( + new FakeCatalogProvider($source), + new FakeCatalogProvider($target), + CatalogComparator::create(), + $spy, + ); + + $diffGenerator->generate('create_users'); + + $upSqlJoined = \implode(' ', $spy->lastUpSql ?? []); + $downSqlJoined = \implode(' ', $spy->lastDownSql ?? []); + self::assertStringContainsString('CREATE', $upSqlJoined); + self::assertStringContainsString('users', $upSqlJoined); + self::assertStringContainsString('DROP', $downSqlJoined); + } + + public function test_generates_migration_when_diff_has_changes() : void + { + $source = new Catalog([]); + $target = new Catalog([ + new Schema('public', [ + new Table('public', 'users', [ + new Column('id', ColumnType::integer(), false), + ]), + ]), + ]); + + $version = Version::fromString('20260403120000'); + $spy = new SpyMigrationGenerator($version); + + $diffGenerator = new DiffMigrationGenerator( + new FakeCatalogProvider($source), + new FakeCatalogProvider($target), + CatalogComparator::create(), + $spy, + ); + + $result = $diffGenerator->generate('create_users'); + + self::assertTrue($result->equals($version)); + self::assertSame('create_users', $spy->lastSchemaName); + self::assertNotEmpty($spy->lastUpSql); + self::assertNotEmpty($spy->lastDownSql); + } + + public function test_throws_when_no_changes_detected_and_allow_empty_is_false() : void + { + $catalog = new Catalog([]); + + $diffGenerator = new DiffMigrationGenerator( + new FakeCatalogProvider($catalog), + new FakeCatalogProvider($catalog), + CatalogComparator::create(), + new SpyMigrationGenerator(Version::fromString('20260403120000')), + ); + + $this->expectException(MigrationException::class); + $this->expectExceptionMessage('No changes detected'); + + $diffGenerator->generate('empty_migration'); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/MigrateWithVersionAliasTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/MigrateWithVersionAliasTest.php new file mode 100644 index 0000000000..e787e25410 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/MigrateWithVersionAliasTest.php @@ -0,0 +1,268 @@ +migrate($resolver->resolve('first')); + + self::assertCount(1, $results); + self::assertSame(Direction::UP, $results[0]->direction); + self::assertTrue($results[0]->version->equals(Version::fromString('20260401120000'))); + self::assertCount(1, $store->executedMigrations()); + } + + public function test_first_rolls_back_to_first_when_all_executed() : void + { + $store = new FakeMigrationStore(); + $store->complete(Version::fromString('20260401120000'), 10); + $store->complete(Version::fromString('20260402120000'), 10); + $store->complete(Version::fromString('20260403120000'), 10); + + $repository = new FakeMigrationRepository( + new AvailableMigration(Version::fromString('20260401120000'), 'create_users', new SpyMigration(), new SpyRollback()), + new AvailableMigration(Version::fromString('20260402120000'), 'create_posts', new SpyMigration(), new SpyRollback()), + new AvailableMigration(Version::fromString('20260403120000'), 'create_comments', new SpyMigration(), new SpyRollback()), + ); + $client = new SpyClient(); + $migrator = new Migrator($repository, $store, new SpyMigrationExecutor(), $client, new Configuration($client, new FakeCatalogProvider(new Catalog([])), '/tmp', 'App\\Migrations')); + $resolver = new VersionResolver($repository, $store); + + $results = $migrator->migrate($resolver->resolve('first')); + + self::assertCount(2, $results); + self::assertSame(Direction::DOWN, $results[0]->direction); + self::assertTrue($results[0]->version->equals(Version::fromString('20260403120000'))); + self::assertSame(Direction::DOWN, $results[1]->direction); + self::assertTrue($results[1]->version->equals(Version::fromString('20260402120000'))); + self::assertCount(1, $store->executedMigrations()); + self::assertTrue($store->executedMigrations()->has(Version::fromString('20260401120000'))); + } + + public function test_full_lifecycle_latest_then_prev_then_next_then_first() : void + { + $store = new FakeMigrationStore(); + $repository = new FakeMigrationRepository( + new AvailableMigration(Version::fromString('20260401120000'), 'create_users', new SpyMigration(), new SpyRollback()), + new AvailableMigration(Version::fromString('20260402120000'), 'create_posts', new SpyMigration(), new SpyRollback()), + new AvailableMigration(Version::fromString('20260403120000'), 'create_comments', new SpyMigration(), new SpyRollback()), + ); + $client = new SpyClient(); + $migrator = new Migrator($repository, $store, new SpyMigrationExecutor(), $client, new Configuration($client, new FakeCatalogProvider(new Catalog([])), '/tmp', 'App\\Migrations')); + $resolver = new VersionResolver($repository, $store); + + $results = $migrator->migrate($resolver->resolve('latest')); + self::assertCount(3, $results); + self::assertCount(3, $store->executedMigrations()); + + $results = $migrator->migrate($resolver->resolve('prev')); + self::assertCount(1, $results); + self::assertSame(Direction::DOWN, $results[0]->direction); + self::assertCount(2, $store->executedMigrations()); + + $results = $migrator->migrate($resolver->resolve('next')); + self::assertCount(1, $results); + self::assertSame(Direction::UP, $results[0]->direction); + self::assertCount(3, $store->executedMigrations()); + + $results = $migrator->migrate($resolver->resolve('first')); + self::assertCount(2, $results); + self::assertSame(Direction::DOWN, $results[0]->direction); + self::assertSame(Direction::DOWN, $results[1]->direction); + self::assertCount(1, $store->executedMigrations()); + self::assertTrue($store->executedMigrations()->has(Version::fromString('20260401120000'))); + } + + public function test_latest_migrates_all_from_scratch() : void + { + $store = new FakeMigrationStore(); + $repository = new FakeMigrationRepository( + new AvailableMigration(Version::fromString('20260401120000'), 'create_users', new SpyMigration(), new SpyRollback()), + new AvailableMigration(Version::fromString('20260402120000'), 'create_posts', new SpyMigration(), new SpyRollback()), + ); + $client = new SpyClient(); + $migrator = new Migrator($repository, $store, new SpyMigrationExecutor(), $client, new Configuration($client, new FakeCatalogProvider(new Catalog([])), '/tmp', 'App\\Migrations')); + $resolver = new VersionResolver($repository, $store); + + $results = $migrator->migrate($resolver->resolve('latest')); + + self::assertCount(2, $results); + self::assertCount(2, $store->executedMigrations()); + } + + public function test_latest_migrates_all_pending() : void + { + $store = new FakeMigrationStore(); + $store->complete(Version::fromString('20260401120000'), 10); + + $repository = new FakeMigrationRepository( + new AvailableMigration(Version::fromString('20260401120000'), 'create_users', new SpyMigration(), new SpyRollback()), + new AvailableMigration(Version::fromString('20260402120000'), 'create_posts', new SpyMigration(), new SpyRollback()), + new AvailableMigration(Version::fromString('20260403120000'), 'create_comments', new SpyMigration(), new SpyRollback()), + ); + $client = new SpyClient(); + $migrator = new Migrator($repository, $store, new SpyMigrationExecutor(), $client, new Configuration($client, new FakeCatalogProvider(new Catalog([])), '/tmp', 'App\\Migrations')); + $resolver = new VersionResolver($repository, $store); + + $results = $migrator->migrate($resolver->resolve('latest')); + + self::assertCount(2, $results); + self::assertSame(Direction::UP, $results[0]->direction); + self::assertTrue($results[0]->version->equals(Version::fromString('20260402120000'))); + self::assertSame(Direction::UP, $results[1]->direction); + self::assertTrue($results[1]->version->equals(Version::fromString('20260403120000'))); + self::assertCount(3, $store->executedMigrations()); + } + + public function test_latest_returns_empty_when_already_up_to_date() : void + { + $store = new FakeMigrationStore(); + $store->complete(Version::fromString('20260401120000'), 10); + $store->complete(Version::fromString('20260402120000'), 10); + + $repository = new FakeMigrationRepository( + new AvailableMigration(Version::fromString('20260401120000'), 'create_users', new SpyMigration(), new SpyRollback()), + new AvailableMigration(Version::fromString('20260402120000'), 'create_posts', new SpyMigration(), new SpyRollback()), + ); + $client = new SpyClient(); + $migrator = new Migrator($repository, $store, new SpyMigrationExecutor(), $client, new Configuration($client, new FakeCatalogProvider(new Catalog([])), '/tmp', 'App\\Migrations')); + $resolver = new VersionResolver($repository, $store); + + $results = $migrator->migrate($resolver->resolve('latest')); + + self::assertCount(0, $results); + } + + public function test_next_migrates_first_when_nothing_executed() : void + { + $store = new FakeMigrationStore(); + $repository = new FakeMigrationRepository( + new AvailableMigration(Version::fromString('20260401120000'), 'create_users', new SpyMigration(), new SpyRollback()), + new AvailableMigration(Version::fromString('20260402120000'), 'create_posts', new SpyMigration(), new SpyRollback()), + ); + $client = new SpyClient(); + $migrator = new Migrator($repository, $store, new SpyMigrationExecutor(), $client, new Configuration($client, new FakeCatalogProvider(new Catalog([])), '/tmp', 'App\\Migrations')); + $resolver = new VersionResolver($repository, $store); + + $results = $migrator->migrate($resolver->resolve('next')); + + self::assertCount(1, $results); + self::assertTrue($results[0]->version->equals(Version::fromString('20260401120000'))); + } + + public function test_next_migrates_one_step_forward() : void + { + $store = new FakeMigrationStore(); + $store->complete(Version::fromString('20260401120000'), 10); + + $repository = new FakeMigrationRepository( + new AvailableMigration(Version::fromString('20260401120000'), 'create_users', new SpyMigration(), new SpyRollback()), + new AvailableMigration(Version::fromString('20260402120000'), 'create_posts', new SpyMigration(), new SpyRollback()), + new AvailableMigration(Version::fromString('20260403120000'), 'create_comments', new SpyMigration(), new SpyRollback()), + ); + $client = new SpyClient(); + $migrator = new Migrator($repository, $store, new SpyMigrationExecutor(), $client, new Configuration($client, new FakeCatalogProvider(new Catalog([])), '/tmp', 'App\\Migrations')); + $resolver = new VersionResolver($repository, $store); + + $results = $migrator->migrate($resolver->resolve('next')); + + self::assertCount(1, $results); + self::assertSame(Direction::UP, $results[0]->direction); + self::assertTrue($results[0]->version->equals(Version::fromString('20260402120000'))); + self::assertCount(2, $store->executedMigrations()); + } + + public function test_prev_rolls_back_everything_when_only_one_executed() : void + { + $store = new FakeMigrationStore(); + $store->complete(Version::fromString('20260401120000'), 10); + + $repository = new FakeMigrationRepository( + new AvailableMigration(Version::fromString('20260401120000'), 'create_users', new SpyMigration(), new SpyRollback()), + new AvailableMigration(Version::fromString('20260402120000'), 'create_posts', new SpyMigration(), new SpyRollback()), + ); + $client = new SpyClient(); + $migrator = new Migrator($repository, $store, new SpyMigrationExecutor(), $client, new Configuration($client, new FakeCatalogProvider(new Catalog([])), '/tmp', 'App\\Migrations')); + $resolver = new VersionResolver($repository, $store); + + $results = $migrator->migrate($resolver->resolve('prev')); + + self::assertCount(1, $results); + self::assertSame(Direction::DOWN, $results[0]->direction); + self::assertTrue($results[0]->version->equals(Version::fromString('20260401120000'))); + self::assertCount(0, $store->executedMigrations()); + } + + public function test_prev_rolls_back_one_step() : void + { + $store = new FakeMigrationStore(); + $store->complete(Version::fromString('20260401120000'), 10); + $store->complete(Version::fromString('20260402120000'), 10); + $store->complete(Version::fromString('20260403120000'), 10); + + $repository = new FakeMigrationRepository( + new AvailableMigration(Version::fromString('20260401120000'), 'create_users', new SpyMigration(), new SpyRollback()), + new AvailableMigration(Version::fromString('20260402120000'), 'create_posts', new SpyMigration(), new SpyRollback()), + new AvailableMigration(Version::fromString('20260403120000'), 'create_comments', new SpyMigration(), new SpyRollback()), + ); + $client = new SpyClient(); + $migrator = new Migrator($repository, $store, new SpyMigrationExecutor(), $client, new Configuration($client, new FakeCatalogProvider(new Catalog([])), '/tmp', 'App\\Migrations')); + $resolver = new VersionResolver($repository, $store); + + $results = $migrator->migrate($resolver->resolve('prev')); + + self::assertCount(1, $results); + self::assertSame(Direction::DOWN, $results[0]->direction); + self::assertTrue($results[0]->version->equals(Version::fromString('20260403120000'))); + self::assertCount(2, $store->executedMigrations()); + self::assertTrue($store->executedMigrations()->has(Version::fromString('20260401120000'))); + self::assertTrue($store->executedMigrations()->has(Version::fromString('20260402120000'))); + self::assertFalse($store->executedMigrations()->has(Version::fromString('20260403120000'))); + } + + public function test_prev_then_next_is_round_trip() : void + { + $store = new FakeMigrationStore(); + $store->complete(Version::fromString('20260401120000'), 10); + $store->complete(Version::fromString('20260402120000'), 10); + + $repository = new FakeMigrationRepository( + new AvailableMigration(Version::fromString('20260401120000'), 'create_users', new SpyMigration(), new SpyRollback()), + new AvailableMigration(Version::fromString('20260402120000'), 'create_posts', new SpyMigration(), new SpyRollback()), + new AvailableMigration(Version::fromString('20260403120000'), 'create_comments', new SpyMigration(), new SpyRollback()), + ); + $client = new SpyClient(); + $migrator = new Migrator($repository, $store, new SpyMigrationExecutor(), $client, new Configuration($client, new FakeCatalogProvider(new Catalog([])), '/tmp', 'App\\Migrations')); + $resolver = new VersionResolver($repository, $store); + + $migrator->migrate($resolver->resolve('prev')); + self::assertCount(1, $store->executedMigrations()); + self::assertTrue($store->executedMigrations()->has(Version::fromString('20260401120000'))); + + $results = $migrator->migrate($resolver->resolve('next')); + self::assertCount(1, $results); + self::assertSame(Direction::UP, $results[0]->direction); + self::assertTrue($results[0]->version->equals(Version::fromString('20260402120000'))); + self::assertCount(2, $store->executedMigrations()); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/MigrationPlanListTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/MigrationPlanListTest.php new file mode 100644 index 0000000000..9dac8c5296 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/MigrationPlanListTest.php @@ -0,0 +1,68 @@ +stubMigration(), null, Direction::UP), + new MigrationPlan(Version::fromString('20260402120000'), $this->stubMigration(), null, Direction::UP), + ); + + self::assertCount(2, $list); + } + + public function test_empty_list() : void + { + $list = new MigrationPlanList(); + + self::assertCount(0, $list); + self::assertTrue($list->isEmpty()); + } + + public function test_is_not_empty() : void + { + $list = new MigrationPlanList( + new MigrationPlan(Version::fromString('20260401120000'), $this->stubMigration(), null, Direction::UP), + ); + + self::assertFalse($list->isEmpty()); + } + + public function test_iteration() : void + { + $plan1 = new MigrationPlan(Version::fromString('20260401120000'), $this->stubMigration(), null, Direction::UP); + $plan2 = new MigrationPlan(Version::fromString('20260402120000'), $this->stubMigration(), null, Direction::DOWN); + + $list = new MigrationPlanList($plan1, $plan2); + + $items = []; + + foreach ($list as $plan) { + $items[] = $plan; + } + + self::assertSame([$plan1, $plan2], $items); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/MigrationStatusListTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/MigrationStatusListTest.php new file mode 100644 index 0000000000..9ae8932ea8 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/MigrationStatusListTest.php @@ -0,0 +1,75 @@ +isEmpty()); + } + + public function test_executed_filter() : void + { + $list = new MigrationStatusList( + new MigrationStatus(Version::fromString('20260401120000'), 'first', MigrationState::EXECUTED, new \DateTimeImmutable()), + new MigrationStatus(Version::fromString('20260402120000'), 'second', MigrationState::PENDING, null), + new MigrationStatus(Version::fromString('20260403120000'), 'third', MigrationState::EXECUTED, new \DateTimeImmutable()), + ); + + $executed = $list->executed(); + + self::assertCount(2, $executed); + + foreach ($executed as $status) { + self::assertSame(MigrationState::EXECUTED, $status->state); + } + } + + public function test_iteration() : void + { + $s1 = new MigrationStatus(Version::fromString('20260401120000'), 'first', MigrationState::PENDING, null); + $s2 = new MigrationStatus(Version::fromString('20260402120000'), 'second', MigrationState::EXECUTED, new \DateTimeImmutable()); + + $list = new MigrationStatusList($s1, $s2); + $items = \iterator_to_array($list); + + self::assertSame([$s1, $s2], $items); + } + + public function test_pending_filter() : void + { + $list = new MigrationStatusList( + new MigrationStatus(Version::fromString('20260401120000'), 'first', MigrationState::EXECUTED, new \DateTimeImmutable()), + new MigrationStatus(Version::fromString('20260402120000'), 'second', MigrationState::PENDING, null), + new MigrationStatus(Version::fromString('20260403120000'), 'third', MigrationState::PENDING, null), + ); + + $pending = $list->pending(); + + self::assertCount(2, $pending); + + foreach ($pending as $status) { + self::assertSame(MigrationState::PENDING, $status->state); + } + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/MigrationsFactoryTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/MigrationsFactoryTest.php new file mode 100644 index 0000000000..12decce57b --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/MigrationsFactoryTest.php @@ -0,0 +1,51 @@ +createDiffGenerator(new SpyMigrationGenerator(Version::fromString('20260401120000')))); + } + + public function test_create_executor() : void + { + $factory = new MigrationsFactory(new Configuration(new SpyClient(), new FakeCatalogProvider(new Catalog([])), \sys_get_temp_dir() . '/flow_migrations_test', 'App\\Migrations'), new FakeMigrationRepository()); + + self::assertInstanceOf(MigrationExecutor::class, $factory->createExecutor()); + } + + public function test_create_migrator() : void + { + $factory = new MigrationsFactory(new Configuration(new SpyClient(), new FakeCatalogProvider(new Catalog([])), \sys_get_temp_dir() . '/flow_migrations_test', 'App\\Migrations'), new FakeMigrationRepository()); + + self::assertInstanceOf(Migrator::class, $factory->createMigrator()); + } + + public function test_create_store() : void + { + $factory = new MigrationsFactory(new Configuration(new SpyClient(), new FakeCatalogProvider(new Catalog([])), \sys_get_temp_dir() . '/flow_migrations_test', 'App\\Migrations'), new FakeMigrationRepository()); + + self::assertInstanceOf(MigrationStore::class, $factory->createStore()); + } + + public function test_create_version_resolver() : void + { + $factory = new MigrationsFactory(new Configuration(new SpyClient(), new FakeCatalogProvider(new Catalog([])), \sys_get_temp_dir() . '/flow_migrations_test', 'App\\Migrations'), new FakeMigrationRepository()); + + self::assertInstanceOf(VersionResolver::class, $factory->createVersionResolver()); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/MigratorTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/MigratorTest.php new file mode 100644 index 0000000000..da78fbb3e5 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/MigratorTest.php @@ -0,0 +1,345 @@ +complete(Version::fromString('20260401120000'), 100); + $client = new SpyClient(); + + $migrator = new Migrator( + new FakeMigrationRepository( + new AvailableMigration(Version::fromString('20260401120000'), 'first', new SpyMigration(), new SpyRollback()), + ), + $store, + new SpyMigrationExecutor(), + $client, + new Configuration($client, new FakeCatalogProvider(new Catalog([])), '/tmp', 'App\\Migrations'), + ); + + $result = $migrator->executeVersion(Version::fromString('20260401120000'), Direction::DOWN); + + self::assertTrue($result->isSuccessful()); + self::assertSame(Direction::DOWN, $result->direction); + self::assertFalse($store->executedMigrations()->has(Version::fromString('20260401120000'))); + } + + public function test_execute_version_up() : void + { + $store = new FakeMigrationStore(); + $executor = new SpyMigrationExecutor(); + $client = new SpyClient(); + + $migrator = new Migrator( + new FakeMigrationRepository( + new AvailableMigration(Version::fromString('20260401120000'), 'first', new SpyMigration(), null), + ), + $store, + $executor, + $client, + new Configuration($client, new FakeCatalogProvider(new Catalog([])), '/tmp', 'App\\Migrations'), + ); + + $result = $migrator->executeVersion(Version::fromString('20260401120000'), Direction::UP); + + self::assertTrue($result->isSuccessful()); + self::assertCount(1, $executor->executedPlans); + self::assertTrue($store->executedMigrations()->has(Version::fromString('20260401120000'))); + } + + public function test_migrate_dry_run_does_not_store() : void + { + $store = new FakeMigrationStore(); + $client = new SpyClient(); + + $migrator = new Migrator( + new FakeMigrationRepository( + new AvailableMigration(Version::fromString('20260401120000'), 'first', new SpyMigration(), null), + ), + $store, + new SpyMigrationExecutor(), + $client, + new Configuration($client, new FakeCatalogProvider(new Catalog([])), '/tmp', 'App\\Migrations'), + ); + + $results = $migrator->migrate(dryRun: true); + + self::assertCount(1, $results); + self::assertTrue($results[0]->isSuccessful()); + self::assertCount(0, $store->executedMigrations()); + } + + public function test_migrate_executes_pending_migrations() : void + { + $executor = new SpyMigrationExecutor(); + $client = new SpyClient(); + + $migrator = new Migrator( + new FakeMigrationRepository( + new AvailableMigration(Version::fromString('20260401120000'), 'first', new SpyMigration(), null), + new AvailableMigration(Version::fromString('20260402120000'), 'second', new SpyMigration(), null), + new AvailableMigration(Version::fromString('20260403120000'), 'third', new SpyMigration(), null), + ), + new FakeMigrationStore(), + $executor, + $client, + new Configuration($client, new FakeCatalogProvider(new Catalog([])), '/tmp', 'App\\Migrations'), + ); + + $results = $migrator->migrate(); + + self::assertCount(3, $results); + self::assertCount(3, $executor->executedPlans); + + foreach ($results as $result) { + self::assertTrue($result->isSuccessful()); + self::assertSame(Direction::UP, $result->direction); + } + } + + public function test_migrate_initializes_store() : void + { + $store = new FakeMigrationStore(); + $client = new SpyClient(); + + $migrator = new Migrator( + new FakeMigrationRepository(), + $store, + new SpyMigrationExecutor(), + $client, + new Configuration($client, new FakeCatalogProvider(new Catalog([])), '/tmp', 'App\\Migrations'), + ); + + $migrator->migrate(); + + self::assertTrue($store->isInitialized()); + } + + public function test_migrate_overrides_configuration_all_or_nothing() : void + { + $client = new SpyClient(); + + $migrator = new Migrator( + new FakeMigrationRepository( + new AvailableMigration(Version::fromString('20260401120000'), 'first', new SpyMigration(), null), + ), + new FakeMigrationStore(), + new SpyMigrationExecutor(), + $client, + new Configuration($client, new FakeCatalogProvider(new Catalog([])), '/tmp', 'App\\Migrations', allOrNothing: true), + ); + + $migrator->migrate(allOrNothing: false); + + self::assertSame(0, $client->transactionCallCount); + } + + public function test_migrate_removes_on_down() : void + { + $store = new FakeMigrationStore(); + $store->complete(Version::fromString('20260401120000'), 100); + $store->complete(Version::fromString('20260402120000'), 100); + $store->complete(Version::fromString('20260403120000'), 100); + $client = new SpyClient(); + + $migrator = new Migrator( + new FakeMigrationRepository( + new AvailableMigration(Version::fromString('20260401120000'), 'first', new SpyMigration(), new SpyRollback()), + new AvailableMigration(Version::fromString('20260402120000'), 'second', new SpyMigration(), new SpyRollback()), + new AvailableMigration(Version::fromString('20260403120000'), 'third', new SpyMigration(), new SpyRollback()), + ), + $store, + new SpyMigrationExecutor(), + $client, + new Configuration($client, new FakeCatalogProvider(new Catalog([])), '/tmp', 'App\\Migrations'), + ); + + $results = $migrator->migrate(Version::fromString('20260401120000')); + + self::assertCount(2, $results); + self::assertCount(1, $store->executedMigrations()); + self::assertTrue($store->executedMigrations()->has(Version::fromString('20260401120000'))); + } + + public function test_migrate_returns_empty_when_already_at_target() : void + { + $store = new FakeMigrationStore(); + $store->complete(Version::fromString('20260401120000'), 100); + $client = new SpyClient(); + + $migrator = new Migrator( + new FakeMigrationRepository( + new AvailableMigration(Version::fromString('20260401120000'), 'first', new SpyMigration(), null), + ), + $store, + new SpyMigrationExecutor(), + $client, + new Configuration($client, new FakeCatalogProvider(new Catalog([])), '/tmp', 'App\\Migrations'), + ); + + self::assertSame([], $migrator->migrate(Version::fromString('20260401120000'))); + } + + public function test_migrate_returns_empty_when_no_available() : void + { + $client = new SpyClient(); + + $migrator = new Migrator( + new FakeMigrationRepository(), + new FakeMigrationStore(), + new SpyMigrationExecutor(), + $client, + new Configuration($client, new FakeCatalogProvider(new Catalog([])), '/tmp', 'App\\Migrations'), + ); + + self::assertSame([], $migrator->migrate()); + } + + public function test_migrate_stores_completed_on_success() : void + { + $store = new FakeMigrationStore(); + $client = new SpyClient(); + + $migrator = new Migrator( + new FakeMigrationRepository( + new AvailableMigration(Version::fromString('20260401120000'), 'first', new SpyMigration(), null), + new AvailableMigration(Version::fromString('20260402120000'), 'second', new SpyMigration(), null), + ), + $store, + new SpyMigrationExecutor(), + $client, + new Configuration($client, new FakeCatalogProvider(new Catalog([])), '/tmp', 'App\\Migrations'), + ); + + $migrator->migrate(); + + self::assertCount(2, $store->executedMigrations()); + self::assertTrue($store->executedMigrations()->has(Version::fromString('20260401120000'))); + self::assertTrue($store->executedMigrations()->has(Version::fromString('20260402120000'))); + } + + public function test_migrate_up_to_specific_version() : void + { + $executor = new SpyMigrationExecutor(); + $client = new SpyClient(); + + $migrator = new Migrator( + new FakeMigrationRepository( + new AvailableMigration(Version::fromString('20260401120000'), 'first', new SpyMigration(), null), + new AvailableMigration(Version::fromString('20260402120000'), 'second', new SpyMigration(), null), + new AvailableMigration(Version::fromString('20260403120000'), 'third', new SpyMigration(), null), + ), + new FakeMigrationStore(), + $executor, + $client, + new Configuration($client, new FakeCatalogProvider(new Catalog([])), '/tmp', 'App\\Migrations'), + ); + + $results = $migrator->migrate(Version::fromString('20260402120000')); + + self::assertCount(2, $results); + self::assertCount(2, $executor->executedPlans); + } + + public function test_migrate_uses_all_or_nothing_from_configuration() : void + { + $client = new SpyClient(); + + $migrator = new Migrator( + new FakeMigrationRepository( + new AvailableMigration(Version::fromString('20260401120000'), 'first', new SpyMigration(), null), + new AvailableMigration(Version::fromString('20260402120000'), 'second', new SpyMigration(), null), + ), + new FakeMigrationStore(), + new SpyMigrationExecutor(), + $client, + new Configuration($client, new FakeCatalogProvider(new Catalog([])), '/tmp', 'App\\Migrations', allOrNothing: true), + ); + + $migrator->migrate(); + + self::assertSame(1, $client->transactionCallCount); + } + + public function test_migrate_without_transaction_when_all_or_nothing_disabled() : void + { + $client = new SpyClient(); + + $migrator = new Migrator( + new FakeMigrationRepository( + new AvailableMigration(Version::fromString('20260401120000'), 'first', new SpyMigration(), null), + ), + new FakeMigrationStore(), + new SpyMigrationExecutor(), + $client, + new Configuration($client, new FakeCatalogProvider(new Catalog([])), '/tmp', 'App\\Migrations', allOrNothing: false), + ); + + $migrator->migrate(); + + self::assertSame(0, $client->transactionCallCount); + } + + public function test_status_shows_pending_and_executed() : void + { + $store = new FakeMigrationStore(); + $store->complete(Version::fromString('20260401120000'), 100); + $client = new SpyClient(); + + $migrator = new Migrator( + new FakeMigrationRepository( + new AvailableMigration(Version::fromString('20260401120000'), 'first', new SpyMigration(), null), + new AvailableMigration(Version::fromString('20260402120000'), 'second', new SpyMigration(), null), + ), + $store, + new SpyMigrationExecutor(), + $client, + new Configuration($client, new FakeCatalogProvider(new Catalog([])), '/tmp', 'App\\Migrations'), + ); + + $status = $migrator->status(); + + self::assertCount(2, $status); + self::assertCount(1, $status->executed()); + self::assertCount(1, $status->pending()); + } + + public function test_status_shows_unavailable() : void + { + $store = new FakeMigrationStore(); + $store->complete(Version::fromString('20260401120000'), 100); + $store->complete(Version::fromString('20260499120000'), 100); + $client = new SpyClient(); + + $migrator = new Migrator( + new FakeMigrationRepository( + new AvailableMigration(Version::fromString('20260401120000'), 'first', new SpyMigration(), null), + ), + $store, + new SpyMigrationExecutor(), + $client, + new Configuration($client, new FakeCatalogProvider(new Catalog([])), '/tmp', 'App\\Migrations'), + ); + + $status = $migrator->status(); + + self::assertCount(2, $status); + self::assertCount(1, $status->executed()); + + $items = \iterator_to_array($status); + $unavailable = \array_filter($items, static fn ($s) => $s->state === MigrationState::UNAVAILABLE); + + self::assertCount(1, $unavailable); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/Repository/AvailableMigrationsTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/Repository/AvailableMigrationsTest.php new file mode 100644 index 0000000000..1d814f68e7 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/Repository/AvailableMigrationsTest.php @@ -0,0 +1,201 @@ +stubMigration(), null), + new AvailableMigration($v2, 'second', $this->stubMigration(), null), + new AvailableMigration($v3, 'third', $this->stubMigration(), null), + ); + + $after = $migrations->after($v2); + + self::assertCount(1, $after); + self::assertTrue($after->has($v3)); + self::assertFalse($after->has($v1)); + self::assertFalse($after->has($v2)); + } + + public function test_after_returns_empty_when_no_migrations_after() : void + { + $v1 = Version::fromString('20260401120000'); + + $migrations = new AvailableMigrations( + new AvailableMigration($v1, 'first', $this->stubMigration(), null), + ); + + self::assertTrue($migrations->after($v1)->isEmpty()); + } + + public function test_count_returns_number_of_migrations() : void + { + $migrations = new AvailableMigrations( + new AvailableMigration(Version::fromString('20260401120000'), 'first', $this->stubMigration(), null), + new AvailableMigration(Version::fromString('20260402120000'), 'second', $this->stubMigration(), null), + new AvailableMigration(Version::fromString('20260403120000'), 'third', $this->stubMigration(), null), + ); + + self::assertCount(3, $migrations); + } + + public function test_empty_collection_is_empty() : void + { + $migrations = new AvailableMigrations(); + + self::assertTrue($migrations->isEmpty()); + self::assertCount(0, $migrations); + self::assertNull($migrations->first()); + self::assertNull($migrations->last()); + } + + public function test_first_returns_earliest_version() : void + { + $v1 = Version::fromString('20260401120000'); + $v2 = Version::fromString('20260402120000'); + + $migrations = new AvailableMigrations( + new AvailableMigration($v2, 'second', $this->stubMigration(), null), + new AvailableMigration($v1, 'first', $this->stubMigration(), null), + ); + + self::assertNotNull($migrations->first()); + self::assertTrue($v1->equals($migrations->first()->version)); + } + + public function test_get_returns_migration_for_existing_version() : void + { + $version = Version::fromString('20260401120000'); + $available = new AvailableMigration($version, 'test', $this->stubMigration(), null); + $migrations = new AvailableMigrations($available); + + self::assertSame($available, $migrations->get($version)); + } + + public function test_get_throws_on_missing_version() : void + { + $migrations = new AvailableMigrations(); + + $this->expectException(MigrationException::class); + $migrations->get(Version::fromString('20260401120000')); + } + + public function test_has_returns_false_for_missing_version() : void + { + $migrations = new AvailableMigrations(); + + self::assertFalse($migrations->has(Version::fromString('20260401120000'))); + } + + public function test_has_returns_true_for_existing_version() : void + { + $version = Version::fromString('20260401120000'); + $migrations = new AvailableMigrations( + new AvailableMigration($version, 'test', $this->stubMigration(), null), + ); + + self::assertTrue($migrations->has($version)); + } + + public function test_iteration_is_sorted_by_version() : void + { + $v1 = Version::fromString('20260401120000'); + $v2 = Version::fromString('20260402120000'); + $v3 = Version::fromString('20260403120000'); + + $migrations = new AvailableMigrations( + new AvailableMigration($v3, 'third', $this->stubMigration(), null), + new AvailableMigration($v1, 'first', $this->stubMigration(), null), + new AvailableMigration($v2, 'second', $this->stubMigration(), null), + ); + + $items = \iterator_to_array($migrations); + + self::assertTrue($v1->equals($items[0]->version)); + self::assertTrue($v2->equals($items[1]->version)); + self::assertTrue($v3->equals($items[2]->version)); + } + + public function test_last_returns_latest_version() : void + { + $v1 = Version::fromString('20260401120000'); + $v2 = Version::fromString('20260402120000'); + + $migrations = new AvailableMigrations( + new AvailableMigration($v1, 'first', $this->stubMigration(), null), + new AvailableMigration($v2, 'second', $this->stubMigration(), null), + ); + + self::assertNotNull($migrations->last()); + self::assertTrue($v2->equals($migrations->last()->version)); + } + + public function test_non_empty_collection_is_not_empty() : void + { + $migrations = new AvailableMigrations( + new AvailableMigration(Version::fromString('20260401120000'), 'test', $this->stubMigration(), null), + ); + + self::assertFalse($migrations->isEmpty()); + } + + public function test_up_to_filters_migrations_up_to_and_including_version() : void + { + $v1 = Version::fromString('20260401120000'); + $v2 = Version::fromString('20260402120000'); + $v3 = Version::fromString('20260403120000'); + + $migrations = new AvailableMigrations( + new AvailableMigration($v1, 'first', $this->stubMigration(), null), + new AvailableMigration($v2, 'second', $this->stubMigration(), null), + new AvailableMigration($v3, 'third', $this->stubMigration(), null), + ); + + $upTo = $migrations->upTo($v2); + + self::assertCount(2, $upTo); + self::assertTrue($upTo->has($v1)); + self::assertTrue($upTo->has($v2)); + self::assertFalse($upTo->has($v3)); + } + + public function test_up_to_returns_empty_when_all_versions_are_after() : void + { + $v1 = Version::fromString('20260401120000'); + $earlier = Version::fromString('20260101000000'); + + $migrations = new AvailableMigrations( + new AvailableMigration($v1, 'first', $this->stubMigration(), null), + ); + + self::assertTrue($migrations->upTo($earlier)->isEmpty()); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/Store/ExecutedMigrationsTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/Store/ExecutedMigrationsTest.php new file mode 100644 index 0000000000..17f74f8c2c --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/Store/ExecutedMigrationsTest.php @@ -0,0 +1,100 @@ +isEmpty()); + self::assertCount(0, $migrations); + self::assertNull($migrations->latest()); + } + + public function test_get_returns_migration_for_existing_version() : void + { + $version = Version::fromString('20260403120000'); + $executed = new ExecutedMigration($version, new \DateTimeImmutable(), 100); + $migrations = new ExecutedMigrations($executed); + + self::assertSame($executed, $migrations->get($version)); + } + + public function test_get_throws_on_missing_version() : void + { + $migrations = new ExecutedMigrations(); + + $this->expectException(MigrationException::class); + $migrations->get(Version::fromString('20260403120000')); + } + + public function test_has_returns_false_for_missing_version() : void + { + $migrations = new ExecutedMigrations(); + + self::assertFalse($migrations->has(Version::fromString('20260403120000'))); + } + + public function test_has_returns_true_for_existing_version() : void + { + $version = Version::fromString('20260403120000'); + $migrations = new ExecutedMigrations( + new ExecutedMigration($version, new \DateTimeImmutable(), 100), + ); + + self::assertTrue($migrations->has($version)); + } + + public function test_iteration() : void + { + $first = new ExecutedMigration(Version::fromString('20260403120000'), new \DateTimeImmutable(), 100); + $second = new ExecutedMigration(Version::fromString('20260403130000'), new \DateTimeImmutable(), 200); + $migrations = new ExecutedMigrations($first, $second); + + $items = \iterator_to_array($migrations); + + self::assertSame($first, $items[0]); + self::assertSame($second, $items[1]); + } + + public function test_latest_returns_last_by_version_order() : void + { + $earliest = new ExecutedMigration(Version::fromString('20260403120000'), new \DateTimeImmutable(), 100); + $middle = new ExecutedMigration(Version::fromString('20260403130000'), new \DateTimeImmutable(), 200); + $latest = new ExecutedMigration(Version::fromString('20260403140000'), new \DateTimeImmutable(), 300); + + $migrations = new ExecutedMigrations($middle, $latest, $earliest); + + self::assertNotNull($migrations->latest()); + self::assertTrue($latest->version->equals($migrations->latest()->version)); + } + + public function test_non_empty_collection_is_not_empty() : void + { + $migrations = new ExecutedMigrations( + new ExecutedMigration(Version::fromString('20260403120000'), new \DateTimeImmutable(), 100), + ); + + self::assertFalse($migrations->isEmpty()); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/VersionGenerator/RandomHexVersionGeneratorTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/VersionGenerator/RandomHexVersionGeneratorTest.php new file mode 100644 index 0000000000..ecf452b189 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/VersionGenerator/RandomHexVersionGeneratorTest.php @@ -0,0 +1,32 @@ +generate()); + } + + public function test_generates_hex_string_with_custom_length() : void + { + $generator = new RandomHexVersionGenerator(8); + + self::assertMatchesRegularExpression('/^[a-f0-9]{8}$/', (string) $generator->generate()); + } + + public function test_generates_unique_values() : void + { + $generator = new RandomHexVersionGenerator(); + + self::assertNotSame((string) $generator->generate(), (string) $generator->generate()); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/VersionGenerator/SequentialVersionGeneratorTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/VersionGenerator/SequentialVersionGeneratorTest.php new file mode 100644 index 0000000000..4ed49491f9 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/VersionGenerator/SequentialVersionGeneratorTest.php @@ -0,0 +1,49 @@ +method('executedMigrations')->willReturn(new ExecutedMigrations()); + + $generator = new SequentialVersionGenerator($store); + + self::assertSame('00001', (string) $generator->generate()); + } + + public function test_generates_version_with_custom_padding() : void + { + $store = self::createStub(MigrationStore::class); + $store->method('executedMigrations')->willReturn(new ExecutedMigrations()); + + $generator = new SequentialVersionGenerator($store, 3); + + self::assertSame('001', (string) $generator->generate()); + } + + public function test_increments_from_latest_version() : void + { + $store = self::createStub(MigrationStore::class); + $store->method('executedMigrations')->willReturn( + new ExecutedMigrations( + new ExecutedMigration(Version::fromString('00001'), new \DateTimeImmutable(), 100), + new ExecutedMigration(Version::fromString('00003'), new \DateTimeImmutable(), 200), + new ExecutedMigration(Version::fromString('00002'), new \DateTimeImmutable(), 150), + ), + ); + + $generator = new SequentialVersionGenerator($store); + + self::assertSame('00004', (string) $generator->generate()); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/VersionGenerator/TimestampVersionGeneratorTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/VersionGenerator/TimestampVersionGeneratorTest.php new file mode 100644 index 0000000000..b51657c1db --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/VersionGenerator/TimestampVersionGeneratorTest.php @@ -0,0 +1,32 @@ +generate()); + } + + public function test_generates_version_with_custom_format() : void + { + $generator = new TimestampVersionGenerator('Ymd_His'); + + self::assertMatchesRegularExpression('/^\d{8}_\d{6}$/', (string) $generator->generate()); + } + + public function test_generates_version_with_date_only_format() : void + { + $generator = new TimestampVersionGenerator('Ymd'); + + self::assertMatchesRegularExpression('/^\d{8}$/', (string) $generator->generate()); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/VersionResolverTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/VersionResolverTest.php new file mode 100644 index 0000000000..c5309ae634 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/VersionResolverTest.php @@ -0,0 +1,123 @@ +equals($resolver->resolve('first'))); + } + + public function test_resolve_first_throws_when_empty() : void + { + $resolver = new VersionResolver( + new FakeMigrationRepository(), + new FakeMigrationStore(), + ); + + $this->expectException(MigrationException::class); + $resolver->resolve('first'); + } + + public function test_resolve_latest() : void + { + $resolver = new VersionResolver( + new FakeMigrationRepository( + new AvailableMigration(Version::fromString('20260401120000'), 'first', new SpyMigration(), null), + new AvailableMigration(Version::fromString('20260402120000'), 'second', new SpyMigration(), null), + ), + new FakeMigrationStore(), + ); + + self::assertTrue(Version::fromString('20260402120000')->equals($resolver->resolve('latest'))); + } + + public function test_resolve_literal_version() : void + { + $resolver = new VersionResolver( + new FakeMigrationRepository(), + new FakeMigrationStore(), + ); + + self::assertTrue(Version::fromString('20260401120000')->equals($resolver->resolve('20260401120000'))); + } + + public function test_resolve_next_with_executed() : void + { + $store = new FakeMigrationStore(); + $store->complete(Version::fromString('20260401120000'), 100); + + $resolver = new VersionResolver( + new FakeMigrationRepository( + new AvailableMigration(Version::fromString('20260401120000'), 'first', new SpyMigration(), null), + new AvailableMigration(Version::fromString('20260402120000'), 'second', new SpyMigration(), null), + new AvailableMigration(Version::fromString('20260403120000'), 'third', new SpyMigration(), null), + ), + $store, + ); + + self::assertTrue(Version::fromString('20260402120000')->equals($resolver->resolve('next'))); + } + + public function test_resolve_next_without_executed() : void + { + $resolver = new VersionResolver( + new FakeMigrationRepository( + new AvailableMigration(Version::fromString('20260401120000'), 'first', new SpyMigration(), null), + new AvailableMigration(Version::fromString('20260402120000'), 'second', new SpyMigration(), null), + ), + new FakeMigrationStore(), + ); + + self::assertTrue(Version::fromString('20260401120000')->equals($resolver->resolve('next'))); + } + + public function test_resolve_prev() : void + { + $store = new FakeMigrationStore(); + $store->complete(Version::fromString('20260401120000'), 100); + $store->complete(Version::fromString('20260402120000'), 100); + + $resolver = new VersionResolver( + new FakeMigrationRepository( + new AvailableMigration(Version::fromString('20260401120000'), 'first', new SpyMigration(), null), + new AvailableMigration(Version::fromString('20260402120000'), 'second', new SpyMigration(), null), + new AvailableMigration(Version::fromString('20260403120000'), 'third', new SpyMigration(), null), + ), + $store, + ); + + self::assertTrue(Version::fromString('20260401120000')->equals($resolver->resolve('prev'))); + } + + public function test_resolve_prev_throws_when_no_executed() : void + { + $resolver = new VersionResolver( + new FakeMigrationRepository( + new AvailableMigration(Version::fromString('20260401120000'), 'first', new SpyMigration(), null), + ), + new FakeMigrationStore(), + ); + + $this->expectException(MigrationException::class); + $resolver->resolve('prev'); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/VersionTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/VersionTest.php new file mode 100644 index 0000000000..6de76f59c6 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Migrations/Tests/Unit/VersionTest.php @@ -0,0 +1,100 @@ +equals($version2)); + } + + public function test_equals_with_same_version() : void + { + $version1 = Version::fromString('20260403120000'); + $version2 = Version::fromString('20260403120000'); + + self::assertTrue($version1->equals($version2)); + } + + public function test_from_string_rejects_special_characters() : void + { + $this->expectException(MigrationException::class); + + Version::fromString('version-1.0'); + } + + public function test_from_string_with_alphanumeric_version() : void + { + $version = Version::fromString('abc123def456'); + + self::assertSame('abc123def456', (string) $version); + } + + public function test_from_string_with_empty_string() : void + { + $this->expectException(MigrationException::class); + + Version::fromString(''); + } + + public function test_from_string_with_numeric_version() : void + { + $version = Version::fromString('00001'); + + self::assertSame('00001', (string) $version); + } + + public function test_from_string_with_timestamp_version() : void + { + $version = Version::fromString('20260403120000'); + + self::assertSame('20260403120000', (string) $version); + } + + public function test_from_string_with_underscore_version() : void + { + $version = Version::fromString('2026_0403_120000'); + + self::assertSame('2026_0403_120000', (string) $version); + } + + public function test_is_after_returns_false_for_earlier_version() : void + { + $earlier = Version::fromString('20260401120000'); + $later = Version::fromString('20260403120000'); + + self::assertFalse($earlier->isAfter($later)); + } + + public function test_is_after_returns_false_for_same_version() : void + { + $version = Version::fromString('20260403120000'); + + self::assertFalse($version->isAfter(Version::fromString('20260403120000'))); + } + + public function test_is_after_returns_true_for_later_version() : void + { + $earlier = Version::fromString('20260401120000'); + $later = Version::fromString('20260403120000'); + + self::assertTrue($later->isAfter($earlier)); + } + + public function test_to_string() : void + { + $version = Version::fromString('20260403120000'); + + self::assertSame('20260403120000', (string) $version); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/ClientTestCase.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/ClientTestCase.php deleted file mode 100644 index 5e3bf67648..0000000000 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/ClientTestCase.php +++ /dev/null @@ -1,39 +0,0 @@ -client = pgsql_client( - pgsql_connection_dsn($dsn), - mapper: pgsql_mapper(), - ); - } - - protected function tearDown() : void - { - if (isset($this->client)) { - $this->client->close(); - } - } -} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/PgCatalogSchemaProviderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/PgCatalogSchemaProviderTest.php new file mode 100644 index 0000000000..ea6a260ec7 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/PgCatalogSchemaProviderTest.php @@ -0,0 +1,384 @@ +pgsqlContext()->dropSchemaIfExists(self::SCHEMA); + $this->pgsqlContext()->client()->execute(create()->schema(self::SCHEMA)->toSql()); + } + + protected function tearDown() : void + { + $this->pgsqlContext()->dropSchemaIfExists(self::SCHEMA); + + parent::tearDown(); + } + + public function test_read_complex_schema() : void + { + $s = self::SCHEMA; + + $this->pgsqlContext()->client()->execute(create()->enumType("{$s}.user_status")->labels('active', 'inactive', 'banned')->toSql()); + + $this->pgsqlContext()->client()->execute( + create()->compositeType("{$s}.address_type") + ->attributes( + type_attr('street', ColumnType::text()), + type_attr('city', ColumnType::text()), + type_attr('zip', ColumnType::varchar(10)), + ) + ->toSql() + ); + + $this->pgsqlContext()->client()->execute( + create()->domain("{$s}.positive_integer") + ->as(column_type_integer()) + ->notNull() + ->check(gt(col('value'), literal(0))) + ->toSql() + ); + + $this->pgsqlContext()->client()->execute( + create()->function("{$s}.update_modified_column") + ->arguments() + ->returns(ColumnType::custom('trigger')) + ->language('plpgsql') + ->as('BEGIN NEW.updated_at = now(); RETURN NEW; END;') + ->toSql() + ); + + $this->pgsqlContext()->client()->execute( + create()->table('users', $s) + ->column(column('id', column_type_serial())) + ->column(column('email', column_type_varchar(255))->notNull()) + ->column(column('name', column_type_text())) + ->column(column('active', column_type_boolean())->notNull()->default(true)) + ->column(column('metadata', column_type_jsonb())) + ->column(column('created_at', column_type_timestamptz())->defaultRaw(func('now'))) + ->constraint(primary_key('id')) + ->constraint(unique_constraint('email')) + ->constraint(check_constraint(new OperatorCondition(col('email'), '~*', literal('^.+@.+')))) + ->toSql() + ); + + $this->pgsqlContext()->client()->execute( + create()->index("{$s}.idx_users_active") + ->on("{$s}.users") + ->columns(index_col('email')) + ->where(eq(col('active'), literal(true))) + ->toSql() + ); + + $this->pgsqlContext()->client()->execute( + create()->table('posts', $s) + ->column(column('id', column_type_bigserial())) + ->column(column('user_id', column_type_integer())->notNull()) + ->column(column('title', column_type_text())->notNull()) + ->column(column('body', column_type_text())) + ->column(column('external_id', column_type_uuid())->defaultRaw(func('gen_random_uuid'))) + ->column(column('updated_at', column_type_timestamptz())) + ->constraint(primary_key('id')) + ->constraint(foreign_key(['user_id'], "{$s}.users", ['id'])->onDelete(ReferentialAction::CASCADE)) + ->toSql() + ); + + $this->pgsqlContext()->client()->execute( + create()->trigger('trg_posts_updated') + ->before(BuilderTriggerEvent::UPDATE) + ->on("{$s}.posts") + ->forEachRow() + ->execute("{$s}.update_modified_column") + ->toSql() + ); + + $this->pgsqlContext()->client()->execute( + create()->table('audit_log', $s) + ->column(column('id', column_type_bigint())->identity()) + ->column(column('action', column_type_text())->notNull()) + ->column(column('ip_address', column_type_inet())) + ->column(column('logged_at', column_type_timestamp())->defaultRaw(func('now'))) + ->toSql() + ); + + $this->pgsqlContext()->client()->execute(create()->sequence('invoice_number_seq', $s)->startWith(1000)->incrementBy(1)->toSql()); + + $this->pgsqlContext()->client()->execute( + create()->view('active_users_view', $s) + ->as(select(col('id'), col('email'))->from(table('users', $s))) + ->toSql() + ); + + $this->pgsqlContext()->client()->execute( + create()->materializedView('user_post_counts', $s) + ->as(select(col('user_id'), agg_count()->as('post_count'))->from(table('posts', $s))->groupBy(col('user_id'))) + ->toSql() + ); + + $schema = client_catalog_provider($this->pgsqlContext()->client(), [$s])->get()->get($s); + + self::assertSame($s, $schema->name); + + self::assertTrue($schema->hasTable('users')); + self::assertTrue($schema->hasTable('posts')); + self::assertTrue($schema->hasTable('audit_log')); + self::assertCount(3, $schema->tables); + + $users = $schema->table('users'); + self::assertFalse($users->column('id')->nullable); + self::assertFalse($users->column('email')->nullable); + self::assertTrue($users->column('name')->nullable); + self::assertFalse($users->column('active')->nullable); + self::assertNotNull($users->primaryKey); + self::assertSame(['id'], $users->primaryKey->columns); + self::assertCount(1, $users->uniqueConstraints); + self::assertCount(1, $users->checkConstraints); + + $posts = $schema->table('posts'); + self::assertCount(1, $posts->foreignKeys); + self::assertSame(['user_id'], $posts->foreignKeys[0]->columns); + self::assertSame('users', $posts->foreignKeys[0]->referenceTable); + self::assertSame(ReferentialAction::CASCADE, $posts->foreignKeys[0]->onDelete); + + self::assertCount(1, $posts->triggers); + self::assertSame(TriggerTiming::BEFORE, $posts->triggers[0]->timing); + self::assertContains(TriggerEvent::UPDATE, $posts->triggers[0]->events); + self::assertTrue($posts->triggers[0]->forEachRow); + + self::assertTrue($schema->hasSequence('invoice_number_seq')); + + self::assertCount(1, $schema->views); + self::assertSame('active_users_view', $schema->views[0]->name); + + self::assertCount(1, $schema->materializedViews); + self::assertSame('user_post_counts', $schema->materializedViews[0]->name); + + $functionNames = \array_map(static fn ($f) => $f->name, $schema->functions); + self::assertContains('update_modified_column', $functionNames); + + self::assertCount(1, $schema->domains); + self::assertSame('positive_integer', $schema->domains[0]->name); + self::assertFalse($schema->domains[0]->nullable); + self::assertCount(1, $schema->domains[0]->checkConstraints); + } + + public function test_read_non_partitioned_table_has_no_partition_info() : void + { + $s = self::SCHEMA; + + $this->pgsqlContext()->client()->execute( + create()->table('regular', $s) + ->column(column('id', column_type_serial())) + ->constraint(primary_key('id')) + ->toSql() + ); + + $table = client_catalog_provider($this->pgsqlContext()->client(), [$s])->get()->get($s)->table('regular'); + + self::assertNull($table->partitionStrategy); + self::assertSame([], $table->partitionColumns); + self::assertSame([], $table->inherits); + } + + public function test_read_partitioned_table_by_hash() : void + { + $s = self::SCHEMA; + + $this->pgsqlContext()->client()->execute( + create()->table('distributed', $s) + ->column(column('id', column_type_integer())->notNull()) + ->column(column('name', column_type_varchar(255))) + ->partitionByHash('id') + ->toSql() + ); + + $table = client_catalog_provider($this->pgsqlContext()->client(), [$s])->get()->get($s)->table('distributed'); + + self::assertSame(PartitionStrategy::HASH, $table->partitionStrategy); + self::assertSame(['id'], $table->partitionColumns); + } + + public function test_read_partitioned_table_by_list() : void + { + $s = self::SCHEMA; + + $this->pgsqlContext()->client()->execute( + create()->table('regional_data', $s) + ->column(column('id', column_type_serial())) + ->column(column('region', column_type_varchar(50))->notNull()) + ->partitionByList('region') + ->toSql() + ); + + $table = client_catalog_provider($this->pgsqlContext()->client(), [$s])->get()->get($s)->table('regional_data'); + + self::assertSame(PartitionStrategy::LIST, $table->partitionStrategy); + self::assertSame(['region'], $table->partitionColumns); + } + + public function test_read_partitioned_table_by_range() : void + { + $s = self::SCHEMA; + + $this->pgsqlContext()->client()->execute( + create()->table('events', $s) + ->column(column('id', column_type_serial())) + ->column(column('created_at', column_type_timestamptz())->notNull()) + ->column(column('name', column_type_varchar(255))) + ->partitionByRange('created_at') + ->toSql() + ); + + $table = client_catalog_provider($this->pgsqlContext()->client(), [$s])->get()->get($s)->table('events'); + + self::assertSame(PartitionStrategy::RANGE, $table->partitionStrategy); + self::assertSame(['created_at'], $table->partitionColumns); + } + + public function test_read_single_table() : void + { + $s = self::SCHEMA; + + $this->pgsqlContext()->client()->execute( + create()->table('simple_table', $s) + ->column(column('id', column_type_serial())) + ->column(column('name', column_type_varchar(100))->notNull()) + ->column(column('description', column_type_text())) + ->column(column('is_active', column_type_boolean())->default(true)) + ->column(column('score', ColumnType::numeric(5, 2))) + ->column(column('created_at', column_type_timestamptz())->defaultRaw(func('now'))) + ->constraint(primary_key('id')) + ->toSql() + ); + + $table = client_catalog_provider($this->pgsqlContext()->client(), [$s])->get()->get($s)->table('simple_table'); + + self::assertSame('simple_table', $table->name); + self::assertCount(6, $table->columns); + self::assertFalse($table->column('id')->nullable); + self::assertFalse($table->column('name')->nullable); + self::assertTrue($table->column('description')->nullable); + self::assertNotNull($table->primaryKey); + self::assertSame(['id'], $table->primaryKey->columns); + } + + public function test_read_table_default_tablespace_is_null() : void + { + $s = self::SCHEMA; + + $this->pgsqlContext()->client()->execute( + create()->table('simple', $s) + ->column(column('id', column_type_serial())) + ->constraint(primary_key('id')) + ->toSql() + ); + + $table = client_catalog_provider($this->pgsqlContext()->client(), [$s])->get()->get($s)->table('simple'); + + self::assertNull($table->tablespace); + } + + public function test_read_table_names() : void + { + $s = self::SCHEMA; + + $this->pgsqlContext()->client()->execute(create()->table('alpha', $s)->column(column('id', column_type_serial()))->constraint(primary_key('id'))->toSql()); + $this->pgsqlContext()->client()->execute(create()->table('beta', $s)->column(column('id', column_type_serial()))->constraint(primary_key('id'))->toSql()); + $this->pgsqlContext()->client()->execute(create()->table('gamma', $s)->column(column('id', column_type_serial()))->constraint(primary_key('id'))->toSql()); + + $schema = client_catalog_provider($this->pgsqlContext()->client(), [$s])->get()->get($s); + + self::assertSame(['alpha', 'beta', 'gamma'], $schema->tableNames()); + } + + public function test_read_table_with_inheritance() : void + { + $s = self::SCHEMA; + + $this->pgsqlContext()->client()->execute("SET search_path TO {$s}, public"); + + $this->pgsqlContext()->client()->execute( + create()->table('persons', $s) + ->column(column('id', column_type_serial())) + ->column(column('name', column_type_varchar(255))->notNull()) + ->constraint(primary_key('id')) + ->toSql() + ); + + $this->pgsqlContext()->client()->execute( + create()->table('employees', $s) + ->column(column('department', column_type_varchar(100))) + ->inherits('persons') + ->toSql() + ); + + $schema = client_catalog_provider($this->pgsqlContext()->client(), [$s])->get()->get($s); + $employees = $schema->table('employees'); + + self::assertSame(["{$s}.persons"], $employees->inherits); + } + + public function test_schemas_returns_catalog_with_all_schemas_when_no_filter() : void + { + $catalog = client_catalog_provider($this->pgsqlContext()->client())->get(); + + self::assertTrue($catalog->has(self::SCHEMA)); + self::assertContains(self::SCHEMA, $catalog->names()); + self::assertNotContains('pg_catalog', $catalog->names()); + self::assertNotContains('information_schema', $catalog->names()); + } + + public function test_schemas_returns_only_filtered_schemas() : void + { + $catalog = client_catalog_provider($this->pgsqlContext()->client(), [self::SCHEMA])->get(); + + self::assertSame([self::SCHEMA], $catalog->names()); + self::assertCount(1, $catalog->all()); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/PgSqlClientTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/PgSqlClientTest.php index eccf54cda4..9f7f29b6b2 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/PgSqlClientTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/PgSqlClientTest.php @@ -8,14 +8,15 @@ binary_expr, cast, col, - cond_false, + column_type_double_precision, + column_type_integer, + constructor_mapper, create, - data_type_double_precision, - data_type_integer, delete, func, gt, insert, + is_true, literal, param, row_expr, @@ -25,32 +26,33 @@ }; use Flow\PostgreSql\Client\Exception\{QueryException, ResultException}; use Flow\PostgreSql\Client\TypedValue; -use Flow\PostgreSql\Client\Types\PostgreSqlType; -use Flow\PostgreSql\QueryBuilder\Schema\{ColumnDefinition, DataType}; +use Flow\PostgreSql\Client\Types\ValueType; +use Flow\PostgreSql\QueryBuilder\Schema\{ColumnDefinition, ColumnType}; +use Flow\PostgreSql\Tests\Integration\PostgreSqlTestCase; -final class PgSqlClientTest extends ClientTestCase +final class PgSqlClientTest extends PostgreSqlTestCase { public function test_close_disconnects() : void { - $this->client->close(); + $this->pgsqlContext()->client()->close(); - self::assertFalse($this->client->isConnected()); + self::assertFalse($this->pgsqlContext()->client()->isConnected()); } public function test_execute_returns_affected_rows() : void { - $this->client->execute( + $this->pgsqlContext()->client()->execute( create()->temporaryTable('test_execute') - ->column(ColumnDefinition::create('id', DataType::integer())) + ->column(ColumnDefinition::create('id', ColumnType::integer())) ); - $this->client->execute( + $this->pgsqlContext()->client()->execute( insert()->into('test_execute')->columns('id') ->values(literal(1)) ->values(literal(2)) ->values(literal(3)) ); - $affected = $this->client->execute( + $affected = $this->pgsqlContext()->client()->execute( delete()->from('test_execute')->where(gt(col('id'), literal(1))) ); @@ -59,8 +61,8 @@ public function test_execute_returns_affected_rows() : void public function test_fetch_all_into_maps_to_objects() : void { - $users = $this->client->fetchAllInto( - TestUser::class, + $users = $this->pgsqlContext()->client()->fetchAllInto( + constructor_mapper(TestUser::class), select(star())->from( values_table( row_expr([literal(1), literal('Alice'), literal('alice@example.com')]), @@ -78,7 +80,7 @@ public function test_fetch_all_into_maps_to_objects() : void public function test_fetch_all_returns_all_rows() : void { - $rows = $this->client->fetchAll( + $rows = $this->pgsqlContext()->client()->fetchAll( select(func('generate_series', [literal(1), literal(3)])->as('num')) ); @@ -90,8 +92,8 @@ public function test_fetch_all_returns_all_rows() : void public function test_fetch_all_returns_empty_array_when_no_rows() : void { - $rows = $this->client->fetchAll( - select(literal(1))->where(cond_false()) + $rows = $this->pgsqlContext()->client()->fetchAll( + select(literal(1))->where(is_true(literal(false))) ); self::assertSame([], $rows); @@ -99,8 +101,8 @@ public function test_fetch_all_returns_empty_array_when_no_rows() : void public function test_fetch_into_maps_to_object() : void { - $user = $this->client->fetchInto( - TestUser::class, + $user = $this->pgsqlContext()->client()->fetchInto( + constructor_mapper(TestUser::class), select(literal(1)->as('id'), param(1)->as('name'), param(2)->as('email')), ['John Doe', 'john@example.com'] ); @@ -113,10 +115,10 @@ public function test_fetch_into_maps_to_object() : void public function test_fetch_into_returns_null_when_no_rows() : void { - $user = $this->client->fetchInto( - TestUser::class, + $user = $this->pgsqlContext()->client()->fetchInto( + constructor_mapper(TestUser::class), select(literal(1)->as('id'), param(1)->as('name'), param(2)->as('email')) - ->where(cond_false()), + ->where(is_true(literal(false))), ['John', 'john@example.com'] ); @@ -125,8 +127,8 @@ public function test_fetch_into_returns_null_when_no_rows() : void public function test_fetch_one_into_maps_to_object() : void { - $user = $this->client->fetchOneInto( - TestUser::class, + $user = $this->pgsqlContext()->client()->fetchOneInto( + constructor_mapper(TestUser::class), select(literal(1)->as('id'), param(1)->as('name'), param(2)->as('email')), ['Jane Doe', 'jane@example.com'] ); @@ -137,7 +139,7 @@ public function test_fetch_one_into_maps_to_object() : void public function test_fetch_one_returns_exactly_one_row() : void { - $row = $this->client->fetchOne( + $row = $this->pgsqlContext()->client()->fetchOne( select(literal(42)->as('value')) ); @@ -149,7 +151,7 @@ public function test_fetch_one_throws_when_multiple_rows() : void $this->expectException(ResultException::class); $this->expectExceptionMessage('Expected exactly one row'); - $this->client->fetchOne( + $this->pgsqlContext()->client()->fetchOne( select(func('generate_series', [literal(1), literal(3)])) ); } @@ -159,15 +161,15 @@ public function test_fetch_one_throws_when_no_rows() : void $this->expectException(ResultException::class); $this->expectExceptionMessage('Expected exactly one row'); - $this->client->fetchOne( - select(literal(1))->where(cond_false()) + $this->pgsqlContext()->client()->fetchOne( + select(literal(1))->where(is_true(literal(false))) ); } public function test_fetch_returns_null_when_no_rows() : void { - $row = $this->client->fetch( - select(literal(1))->where(cond_false()) + $row = $this->pgsqlContext()->client()->fetch( + select(literal(1))->where(is_true(literal(false))) ); self::assertNull($row); @@ -175,7 +177,7 @@ public function test_fetch_returns_null_when_no_rows() : void public function test_fetch_returns_single_row() : void { - $row = $this->client->fetch( + $row = $this->pgsqlContext()->client()->fetch( select(literal(1)->as('id'), param(1)->as('name')), ['Alice'] ); @@ -187,13 +189,13 @@ public function test_fetch_returns_single_row() : void public function test_fetch_scalar_bool_returns_boolean() : void { - $value = $this->client->fetchScalarBool( + $value = $this->pgsqlContext()->client()->fetchScalarBool( select(literal(true)) ); self::assertTrue($value); - $value = $this->client->fetchScalarBool( + $value = $this->pgsqlContext()->client()->fetchScalarBool( select(literal(false)) ); @@ -202,8 +204,8 @@ public function test_fetch_scalar_bool_returns_boolean() : void public function test_fetch_scalar_float_returns_float() : void { - $value = $this->client->fetchScalarFloat( - select(cast(literal(3.14), data_type_double_precision())) + $value = $this->pgsqlContext()->client()->fetchScalarFloat( + select(cast(literal(3.14), column_type_double_precision())) ); self::assertSame(3.14, $value); @@ -211,7 +213,7 @@ public function test_fetch_scalar_float_returns_float() : void public function test_fetch_scalar_int_returns_integer() : void { - $value = $this->client->fetchScalarInt( + $value = $this->pgsqlContext()->client()->fetchScalarInt( select(literal(42)) ); @@ -220,8 +222,8 @@ public function test_fetch_scalar_int_returns_integer() : void public function test_fetch_scalar_returns_null_when_no_rows() : void { - $value = $this->client->fetchScalar( - select(literal(1))->where(cond_false()) + $value = $this->pgsqlContext()->client()->fetchScalar( + select(literal(1))->where(is_true(literal(false))) ); self::assertNull($value); @@ -229,12 +231,12 @@ public function test_fetch_scalar_returns_null_when_no_rows() : void public function test_fetch_scalar_returns_single_value() : void { - $value = $this->client->fetchScalar( + $value = $this->pgsqlContext()->client()->fetchScalar( select( binary_expr( - cast(param(1), data_type_integer()), + cast(param(1), column_type_integer()), '+', - cast(param(2), data_type_integer()) + cast(param(2), column_type_integer()) ) ), ['10', '32'] @@ -245,7 +247,7 @@ public function test_fetch_scalar_returns_single_value() : void public function test_fetch_scalar_string_returns_string() : void { - $value = $this->client->fetchScalarString( + $value = $this->pgsqlContext()->client()->fetchScalarString( select(literal('hello world')) ); @@ -254,49 +256,49 @@ public function test_fetch_scalar_string_returns_string() : void public function test_is_connected() : void { - self::assertTrue($this->client->isConnected()); + self::assertTrue($this->pgsqlContext()->client()->isConnected()); } public function test_last_insert_id_returns_sequence_value() : void { - $this->client->execute( + $this->pgsqlContext()->client()->execute( create()->temporaryTable('test_last_insert_id') - ->column(ColumnDefinition::create('id', DataType::serial())->primaryKey()) - ->column(ColumnDefinition::create('name', DataType::text())) + ->column(ColumnDefinition::create('id', ColumnType::serial())->primaryKey()) + ->column(ColumnDefinition::create('name', ColumnType::text())) ); - $this->client->execute( + $this->pgsqlContext()->client()->execute( insert()->into('test_last_insert_id')->columns('name')->values(literal('first')) ); - $id = $this->client->lastInsertId('test_last_insert_id_id_seq'); + $id = $this->pgsqlContext()->client()->lastInsertId('test_last_insert_id_id_seq'); self::assertSame(1, $id); - $this->client->execute( + $this->pgsqlContext()->client()->execute( insert()->into('test_last_insert_id')->columns('name')->values(literal('second')) ); - $id = $this->client->lastInsertId('test_last_insert_id_id_seq'); + $id = $this->pgsqlContext()->client()->lastInsertId('test_last_insert_id_id_seq'); self::assertSame(2, $id); } public function test_last_insert_id_throws_when_sequence_not_used() : void { - $this->client->execute( + $this->pgsqlContext()->client()->execute( create()->temporarySequence('test_unused_seq') ); $this->expectException(QueryException::class); $this->expectExceptionMessage('Query execution failed [55000]: Object not in prerequisite state. SQL: SELECT currval($1)'); - $this->client->lastInsertId('test_unused_seq'); + $this->pgsqlContext()->client()->lastInsertId('test_unused_seq'); } public function test_typed_value_forces_type() : void { - $value = new TypedValue(42, PostgreSqlType::INT4); - $row = $this->client->fetchOne( - select(cast(param(1), data_type_integer())->as('val')), + $value = new TypedValue(42, ValueType::INT4); + $row = $this->pgsqlContext()->client()->fetchOne( + select(cast(param(1), column_type_integer())->as('val')), [$value] ); diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/PgSqlCursorTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/PgSqlCursorTest.php index be93aaa7a9..cd814ebd97 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/PgSqlCursorTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/PgSqlCursorTest.php @@ -4,13 +4,14 @@ namespace Flow\PostgreSql\Tests\Integration\Client; -use function Flow\PostgreSql\DSL\{func, literal, select}; +use function Flow\PostgreSql\DSL\{cast, column_type_boolean, column_type_integer, constructor_mapper, func, is_true, literal, row_expr, select, star, values_table}; +use Flow\PostgreSql\Tests\Integration\PostgreSqlTestCase; -final class PgSqlCursorTest extends ClientTestCase +final class PgSqlCursorTest extends PostgreSqlTestCase { public function test_cursor_count() : void { - $cursor = $this->client->cursor( + $cursor = $this->pgsqlContext()->client()->cursor( select(func('generate_series', [literal(1), literal(5)])->as('num')) ); @@ -19,7 +20,7 @@ public function test_cursor_count() : void public function test_cursor_free() : void { - $cursor = $this->client->cursor( + $cursor = $this->pgsqlContext()->client()->cursor( select(literal(1)->as('num')) ); @@ -31,7 +32,7 @@ public function test_cursor_free() : void public function test_cursor_iterate_method() : void { - $cursor = $this->client->cursor( + $cursor = $this->pgsqlContext()->client()->cursor( select(func('generate_series', [literal(1), literal(2)])->as('num')) ); @@ -42,7 +43,7 @@ public function test_cursor_iterate_method() : void public function test_cursor_iterates_rows() : void { - $cursor = $this->client->cursor( + $cursor = $this->pgsqlContext()->client()->cursor( select(func('generate_series', [literal(1), literal(3)])->as('num')) ); @@ -60,11 +61,16 @@ public function test_cursor_iterates_rows() : void public function test_cursor_map_to_objects() : void { - $cursor = $this->client->cursor( - "SELECT * FROM (VALUES (1, 'Alice'), (2, 'Bob')) AS t(id, name)" + $cursor = $this->pgsqlContext()->client()->cursor( + select(star())->from( + values_table( + row_expr([literal(1), literal('Alice')]), + row_expr([literal(2), literal('Bob')]) + )->as('t', ['id', 'name']) + ) ); - $objects = \iterator_to_array($cursor->map(CursorTestUser::class)); + $objects = \iterator_to_array($cursor->map(constructor_mapper(CursorTestUser::class))); self::assertCount(2, $objects); self::assertInstanceOf(CursorTestUser::class, $objects[0]); @@ -75,7 +81,7 @@ public function test_cursor_map_to_objects() : void public function test_cursor_next_method() : void { - $cursor = $this->client->cursor( + $cursor = $this->pgsqlContext()->client()->cursor( select(func('generate_series', [literal(1), literal(3)])->as('num')) ); @@ -96,8 +102,8 @@ public function test_cursor_next_method() : void public function test_cursor_with_type_conversion() : void { - $cursor = $this->client->cursor( - 'SELECT 42::integer AS num, true::boolean AS flag' + $cursor = $this->pgsqlContext()->client()->cursor( + select(cast(literal(42), column_type_integer())->as('num'), cast(literal(true), column_type_boolean())->as('flag')) ); $row = $cursor->next(); @@ -109,7 +115,7 @@ public function test_cursor_with_type_conversion() : void public function test_empty_cursor() : void { - $cursor = $this->client->cursor('SELECT 1 WHERE false'); + $cursor = $this->pgsqlContext()->client()->cursor(select(literal(1))->where(is_true(literal(false)))); self::assertSame(0, $cursor->count()); self::assertNull($cursor->next()); diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/PgSqlExplainTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/PgSqlExplainTest.php index 26d9eb40c8..07b5c92aa6 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/PgSqlExplainTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/PgSqlExplainTest.php @@ -5,11 +5,13 @@ namespace Flow\PostgreSql\Tests\Integration\Client; use function Flow\PostgreSql\DSL\{ + binary_expr, + cast, col, column, + column_type_integer, + column_type_text, create, - data_type_integer, - data_type_text, eq, insert, literal, @@ -22,9 +24,10 @@ use Flow\PostgreSql\AST\Transformers\ExplainConfig; use Flow\PostgreSql\Explain\Analyzer\{PlanAnalyzer, PlanSummary}; use Flow\PostgreSql\Explain\Plan\PlanNodeType; +use Flow\PostgreSql\Tests\Integration\PostgreSqlTestCase; use PHPUnit\Framework\Attributes\DataProvider; -final class PgSqlExplainTest extends ClientTestCase +final class PgSqlExplainTest extends PostgreSqlTestCase { /** * @return \Generatorclient->explain( + $plan = $this->pgsqlContext()->client()->explain( select(literal(1)), config: ExplainConfig::forEstimate() ); @@ -129,13 +132,13 @@ public function test_explain_for_estimate() : void public function test_explain_returns_plan_for_select_query() : void { - $this->client->execute( + $this->pgsqlContext()->client()->execute( create()->temporaryTable('test_explain') - ->column(column('id', data_type_integer())) - ->column(column('name', data_type_text())) + ->column(column('id', column_type_integer())) + ->column(column('name', column_type_text())) ); - $plan = $this->client->explain( + $plan = $this->pgsqlContext()->client()->explain( select(star())->from(table('test_explain')) ); @@ -145,13 +148,13 @@ public function test_explain_returns_plan_for_select_query() : void public function test_explain_returns_plan_with_parameters() : void { - $this->client->execute( + $this->pgsqlContext()->client()->execute( create()->temporaryTable('test_explain_params') - ->column(column('id', data_type_integer())) - ->column(column('name', data_type_text())) + ->column(column('id', column_type_integer())) + ->column(column('name', column_type_text())) ); - $plan = $this->client->explain( + $plan = $this->pgsqlContext()->client()->explain( select(star())->from(table('test_explain_params'))->where(eq(col('id'), param(1))), ['42'] ); @@ -161,8 +164,8 @@ public function test_explain_returns_plan_with_parameters() : void public function test_explain_returns_plan_with_raw_sql() : void { - $plan = $this->client->explain( - 'SELECT $1::int + $2::int', + $plan = $this->pgsqlContext()->client()->explain( + select(binary_expr(cast(param(1), column_type_integer()), '+', cast(param(2), column_type_integer()))), ['10', '32'] ); @@ -181,17 +184,17 @@ public function test_explain_returns_plan_with_raw_sql() : void #[DataProvider('provideExplainConfigCombinations')] public function test_explain_with_config_combinations(ExplainConfig $config, array $expected) : void { - $this->client->execute( + $this->pgsqlContext()->client()->execute( create()->temporaryTable('test_explain_combinations') - ->column(column('id', data_type_integer())) - ->column(column('name', data_type_text())) + ->column(column('id', column_type_integer())) + ->column(column('name', column_type_text())) ); - $this->client->execute( + $this->pgsqlContext()->client()->execute( insert()->into('test_explain_combinations')->columns('id', 'name') ->values(literal(1), literal('test')) ); - $plan = $this->client->explain( + $plan = $this->pgsqlContext()->client()->explain( select(star())->from(table('test_explain_combinations')), config: $config ); @@ -231,12 +234,12 @@ public function test_explain_with_config_combinations(ExplainConfig $config, arr public function test_explain_with_custom_config() : void { - $this->client->execute( + $this->pgsqlContext()->client()->execute( create()->temporaryTable('test_explain_config') - ->column(column('id', data_type_integer())) + ->column(column('id', column_type_integer())) ); - $plan = $this->client->explain( + $plan = $this->pgsqlContext()->client()->explain( select(star())->from(table('test_explain_config')), config: sql_explain_config() ); @@ -247,7 +250,7 @@ public function test_explain_with_custom_config() : void public function test_explain_without_analyze() : void { - $plan = $this->client->explain( + $plan = $this->pgsqlContext()->client()->explain( select(literal(1)), config: sql_explain_config( analyze: false, @@ -273,17 +276,17 @@ public function test_explain_without_analyze() : void #[DataProvider('provideExplainConfigCombinations')] public function test_plan_summary_with_config_combinations(ExplainConfig $config, array $expected) : void { - $this->client->execute( + $this->pgsqlContext()->client()->execute( create()->temporaryTable('test_summary_combinations') - ->column(column('id', data_type_integer())) - ->column(column('name', data_type_text())) + ->column(column('id', column_type_integer())) + ->column(column('name', column_type_text())) ); - $this->client->execute( + $this->pgsqlContext()->client()->execute( insert()->into('test_summary_combinations')->columns('id', 'name') ->values(literal(1), literal('test')) ); - $plan = $this->client->explain( + $plan = $this->pgsqlContext()->client()->explain( select(star())->from(table('test_summary_combinations')), config: $config ); diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/QueryExceptionTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/QueryExceptionTest.php index ce9310c410..f2e0f2e380 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/QueryExceptionTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/QueryExceptionTest.php @@ -4,23 +4,27 @@ namespace Flow\PostgreSql\Tests\Integration\Client; -use function Flow\PostgreSql\DSL\{create, insert, literal}; +use function Flow\PostgreSql\DSL\{alter, cast, check_constraint, col, column_type_integer, create, foreign_key, gt, insert, literal, select}; use Flow\PostgreSql\Client\Exception\{PostgreSqlErrorCategory, QueryException}; -use Flow\PostgreSql\QueryBuilder\Schema\{ColumnDefinition, DataType}; +use Flow\PostgreSql\QueryBuilder\Schema\{ColumnDefinition, ColumnType}; +use Flow\PostgreSql\Tests\Integration\PostgreSqlTestCase; -final class QueryExceptionTest extends ClientTestCase +final class QueryExceptionTest extends PostgreSqlTestCase { public function test_check_constraint_violation() : void { - $this->client->execute( + $this->pgsqlContext()->client()->execute( create()->temporaryTable('test_check_violation') - ->column(ColumnDefinition::create('id', DataType::integer())->primaryKey()) - ->column(ColumnDefinition::create('age', DataType::integer())) + ->column(ColumnDefinition::create('id', ColumnType::integer())->primaryKey()) + ->column(ColumnDefinition::create('age', ColumnType::integer())) + ); + $this->pgsqlContext()->client()->execute( + alter()->table('test_check_violation') + ->addConstraint(check_constraint(gt(col('age'), literal(0)))->name('age_positive')) ); - $this->client->execute('ALTER TABLE test_check_violation ADD CONSTRAINT age_positive CHECK (age > 0)'); try { - $this->client->execute( + $this->pgsqlContext()->client()->execute( insert()->into('test_check_violation') ->columns('id', 'age') ->values(literal(1), literal(-5)) @@ -41,7 +45,7 @@ public function test_check_constraint_violation() : void public function test_data_exception() : void { try { - $this->client->execute("SELECT 'not_a_number'::integer"); + $this->pgsqlContext()->client()->execute(select(cast(literal('not_a_number'), column_type_integer()))); self::fail('Expected QueryException to be thrown'); } catch (QueryException $e) { $error = $e->error(); @@ -54,16 +58,16 @@ public function test_data_exception() : void public function test_exception_message_format() : void { - $this->client->execute( + $this->pgsqlContext()->client()->execute( create()->temporaryTable('test_safe_message') - ->column(ColumnDefinition::create('id', DataType::integer())->primaryKey()) + ->column(ColumnDefinition::create('id', ColumnType::integer())->primaryKey()) ); - $this->client->execute( + $this->pgsqlContext()->client()->execute( insert()->into('test_safe_message')->columns('id')->values(literal(1)) ); try { - $this->client->execute( + $this->pgsqlContext()->client()->execute( insert()->into('test_safe_message')->columns('id')->values(literal(1)) ); self::fail('Expected QueryException to be thrown'); @@ -75,19 +79,22 @@ public function test_exception_message_format() : void public function test_foreign_key_violation() : void { - $this->client->execute( + $this->pgsqlContext()->client()->execute( create()->temporaryTable('test_fk_parent') - ->column(ColumnDefinition::create('id', DataType::integer())->primaryKey()) + ->column(ColumnDefinition::create('id', ColumnType::integer())->primaryKey()) ); - $this->client->execute( + $this->pgsqlContext()->client()->execute( create()->temporaryTable('test_fk_child') - ->column(ColumnDefinition::create('id', DataType::integer())->primaryKey()) - ->column(ColumnDefinition::create('parent_id', DataType::integer())->notNull()) + ->column(ColumnDefinition::create('id', ColumnType::integer())->primaryKey()) + ->column(ColumnDefinition::create('parent_id', ColumnType::integer())->notNull()) + ); + $this->pgsqlContext()->client()->execute( + alter()->table('test_fk_child') + ->addConstraint(foreign_key(['parent_id'], 'test_fk_parent', ['id'])->name('test_fk')) ); - $this->client->execute('ALTER TABLE test_fk_child ADD CONSTRAINT test_fk FOREIGN KEY (parent_id) REFERENCES test_fk_parent(id)'); try { - $this->client->execute( + $this->pgsqlContext()->client()->execute( insert()->into('test_fk_child') ->columns('id', 'parent_id') ->values(literal(1), literal(999)) @@ -107,14 +114,14 @@ public function test_foreign_key_violation() : void public function test_not_null_violation() : void { - $this->client->execute( + $this->pgsqlContext()->client()->execute( create()->temporaryTable('test_not_null_violation') - ->column(ColumnDefinition::create('id', DataType::integer())->primaryKey()) - ->column(ColumnDefinition::create('name', DataType::text())->notNull()) + ->column(ColumnDefinition::create('id', ColumnType::integer())->primaryKey()) + ->column(ColumnDefinition::create('name', ColumnType::text())->notNull()) ); try { - $this->client->execute( + $this->pgsqlContext()->client()->execute( insert()->into('test_not_null_violation') ->columns('id', 'name') ->values(literal(1), literal(null)) @@ -135,7 +142,7 @@ public function test_not_null_violation() : void public function test_sql_is_accessible() : void { try { - $this->client->execute('SELECT * FORM invalid_syntax'); + $this->pgsqlContext()->client()->execute('SELECT * FORM invalid_syntax'); self::fail('Expected QueryException to be thrown'); } catch (QueryException $e) { self::assertSame('SELECT * FORM invalid_syntax', $e->sql()); @@ -145,7 +152,7 @@ public function test_sql_is_accessible() : void public function test_syntax_error() : void { try { - $this->client->execute('SELECT * FORM users'); + $this->pgsqlContext()->client()->execute('SELECT * FORM users'); self::fail('Expected QueryException to be thrown'); } catch (QueryException $e) { $error = $e->error(); @@ -159,19 +166,19 @@ public function test_syntax_error() : void public function test_unique_violation() : void { - $this->client->execute( + $this->pgsqlContext()->client()->execute( create()->temporaryTable('test_unique_violation') - ->column(ColumnDefinition::create('id', DataType::integer())->primaryKey()) - ->column(ColumnDefinition::create('email', DataType::text())->unique()) + ->column(ColumnDefinition::create('id', ColumnType::integer())->primaryKey()) + ->column(ColumnDefinition::create('email', ColumnType::text())->unique()) ); - $this->client->execute( + $this->pgsqlContext()->client()->execute( insert()->into('test_unique_violation') ->columns('id', 'email') ->values(literal(1), literal('test@example.com')) ); try { - $this->client->execute( + $this->pgsqlContext()->client()->execute( insert()->into('test_unique_violation') ->columns('id', 'email') ->values(literal(2), literal('test@example.com')) diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Telemetry/TraceableClientTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Telemetry/TraceableClientTest.php index 60f28be8b4..cbc9e639da 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Telemetry/TraceableClientTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Telemetry/TraceableClientTest.php @@ -4,57 +4,40 @@ namespace Flow\PostgreSql\Tests\Integration\Client\Telemetry; -use function Flow\PostgreSql\DSL\{pgsql_client, pgsql_connection_dsn, pgsql_mapper, postgresql_telemetry_config, postgresql_telemetry_options, traceable_postgresql_client}; +use function Flow\PostgreSql\DSL\{column, column_type_serial, column_type_text, create, insert, literal, param, postgresql_telemetry_config, postgresql_telemetry_options, primary_key, select, star, table, traceable_postgresql_client}; use function Flow\Telemetry\DSL\{logger_provider, memory_context_storage, memory_log_processor, memory_metric_processor, memory_span_processor, meter_provider, resource, telemetry, tracer_provider, void_log_exporter, void_metric_exporter, void_span_exporter}; use Flow\PostgreSql\Client\Client; use Flow\PostgreSql\Client\Telemetry\PostgreSqlTelemetryAttributes; +use Flow\PostgreSql\Tests\Integration\PostgreSqlTestCase; use Flow\Telemetry\Logger\Severity; use Flow\Telemetry\Meter\MetricType; use Flow\Telemetry\Provider\Clock\SystemClock; use Flow\Telemetry\Provider\Memory\{MemoryLogProcessor, MemoryMetricProcessor, MemorySpanProcessor}; -use PHPUnit\Framework\TestCase; -final class TraceableClientTest extends TestCase +final class TraceableClientTest extends PostgreSqlTestCase { - private Client $baseClient; - - protected function setUp() : void - { - if (!\extension_loaded('pgsql')) { - self::markTestSkipped('ext-pgsql is not available'); - } - - $dsn = \getenv('PGSQL_DATABASE_URL'); - - if (!$dsn) { - self::markTestSkipped('PGSQL_DATABASE_URL environment variable is not set'); - } - - $this->baseClient = pgsql_client( - pgsql_connection_dsn($dsn), - mapper: pgsql_mapper(), - ); - } - - protected function tearDown() : void - { - if (isset($this->baseClient)) { - $this->baseClient->close(); - } - } - public function test_cursor_iteration_creates_span() : void { $spanProcessor = memory_span_processor(void_span_exporter()); $config = $this->createConfig($spanProcessor, options: postgresql_telemetry_options( traceQueries: true, )); - $client = traceable_postgresql_client($this->baseClient, $config); + $client = traceable_postgresql_client($this->pgsqlContext()->client(), $config); - $client->execute('CREATE TEMP TABLE test_cursor (id serial PRIMARY KEY, name text)'); - $client->execute('INSERT INTO test_cursor (name) VALUES ($1), ($2)', ['John', 'Jane']); + $client->execute( + create()->temporaryTable('test_cursor') + ->column(column('id', column_type_serial())) + ->column(column('name', column_type_text())) + ->constraint(primary_key('id')) + ); + $client->execute( + insert()->into('test_cursor')->columns('name') + ->values(param(1)) + ->values(param(2)), + ['John', 'Jane'] + ); - $cursor = $client->cursor('SELECT * FROM test_cursor'); + $cursor = $client->cursor(select(star())->from(table('test_cursor'))); $rows = []; foreach ($cursor->iterate() as $row) { @@ -75,10 +58,18 @@ public function test_execute_creates_span_with_database_attributes() : void { $spanProcessor = memory_span_processor(void_span_exporter()); $config = $this->createConfig($spanProcessor); - $client = traceable_postgresql_client($this->baseClient, $config); + $client = traceable_postgresql_client($this->pgsqlContext()->client(), $config); - $client->execute('CREATE TEMP TABLE test_execute_span (id serial PRIMARY KEY, name text)'); - $client->execute('INSERT INTO test_execute_span (name) VALUES ($1)', ['John']); + $client->execute( + create()->temporaryTable('test_execute_span') + ->column(column('id', column_type_serial())) + ->column(column('name', column_type_text())) + ->constraint(primary_key('id')) + ); + $client->execute( + insert()->into('test_execute_span')->columns('name')->values(param(1)), + ['John'] + ); $spans = $spanProcessor->endedSpans(); self::assertCount(2, $spans); @@ -96,10 +87,10 @@ public function test_failed_query_records_error_in_span() : void { $spanProcessor = memory_span_processor(void_span_exporter()); $config = $this->createConfig($spanProcessor); - $client = traceable_postgresql_client($this->baseClient, $config); + $client = traceable_postgresql_client($this->pgsqlContext()->client(), $config); try { - $client->execute('SELECT * FROM nonexistent_table_12345'); + $client->execute(select(star())->from(table('nonexistent_table_12345'))); } catch (\Throwable) { } @@ -114,11 +105,22 @@ public function test_fetch_creates_span_with_row_count() : void { $spanProcessor = memory_span_processor(void_span_exporter()); $config = $this->createConfig($spanProcessor); - $client = traceable_postgresql_client($this->baseClient, $config); + $client = traceable_postgresql_client($this->pgsqlContext()->client(), $config); - $client->execute('CREATE TEMP TABLE test_fetch_span (id serial PRIMARY KEY, name text)'); - $client->execute('INSERT INTO test_fetch_span (name) VALUES ($1), ($2), ($3)', ['John', 'Jane', 'Bob']); - $result = $client->fetchAll('SELECT * FROM test_fetch_span'); + $client->execute( + create()->temporaryTable('test_fetch_span') + ->column(column('id', column_type_serial())) + ->column(column('name', column_type_text())) + ->constraint(primary_key('id')) + ); + $client->execute( + insert()->into('test_fetch_span')->columns('name') + ->values(param(1)) + ->values(param(2)) + ->values(param(3)), + ['John', 'Jane', 'Bob'] + ); + $result = $client->fetchAll(select(star())->from(table('test_fetch_span'))); self::assertCount(3, $result); @@ -135,10 +137,14 @@ public function test_logging_records_query_execution() : void $config = $this->createConfig(logProcessor: $logProcessor, options: postgresql_telemetry_options( logQueries: true, )); - $client = traceable_postgresql_client($this->baseClient, $config); + $client = traceable_postgresql_client($this->pgsqlContext()->client(), $config); - $client->execute('CREATE TEMP TABLE test_logging (id serial PRIMARY KEY)'); - $client->execute('INSERT INTO test_logging DEFAULT VALUES'); + $client->execute( + create()->temporaryTable('test_logging') + ->column(column('id', column_type_serial())) + ->constraint(primary_key('id')) + ); + $client->execute(insert()->into('test_logging')->defaultValues()); $logs = $logProcessor->entries(); self::assertCount(2, $logs); @@ -152,9 +158,9 @@ public function test_metrics_record_operation_duration() : void $config = $this->createConfig(metricProcessor: $metricProcessor, options: postgresql_telemetry_options( collectMetrics: true, )); - $client = traceable_postgresql_client($this->baseClient, $config); + $client = traceable_postgresql_client($this->pgsqlContext()->client(), $config); - $client->execute('SELECT 1'); + $client->execute(select(literal(1))); $this->collectMetrics($config); @@ -171,14 +177,18 @@ public function test_nested_transaction_creates_savepoint_span() : void traceTransactions: true, traceQueries: false, )); - $client = traceable_postgresql_client($this->baseClient, $config); + $client = traceable_postgresql_client($this->pgsqlContext()->client(), $config); - $client->execute('CREATE TEMP TABLE test_nested_tx (id serial PRIMARY KEY)'); + $client->execute( + create()->temporaryTable('test_nested_tx') + ->column(column('id', column_type_serial())) + ->constraint(primary_key('id')) + ); $client->transaction(static function (Client $outer) : void { - $outer->execute('INSERT INTO test_nested_tx DEFAULT VALUES'); + $outer->execute(insert()->into('test_nested_tx')->defaultValues()); $outer->transaction(static function (Client $inner) : void { - $inner->execute('INSERT INTO test_nested_tx DEFAULT VALUES'); + $inner->execute(insert()->into('test_nested_tx')->defaultValues()); }); }); @@ -196,10 +206,18 @@ public function test_parameters_are_included_when_enabled() : void $config = $this->createConfig($spanProcessor, options: postgresql_telemetry_options( includeParameters: true, )); - $client = traceable_postgresql_client($this->baseClient, $config); + $client = traceable_postgresql_client($this->pgsqlContext()->client(), $config); - $client->execute('CREATE TEMP TABLE test_params (id serial PRIMARY KEY, name text)'); - $client->execute('INSERT INTO test_params (name) VALUES ($1)', ['John']); + $client->execute( + create()->temporaryTable('test_params') + ->column(column('id', column_type_serial())) + ->column(column('name', column_type_text())) + ->constraint(primary_key('id')) + ); + $client->execute( + insert()->into('test_params')->columns('name')->values(param(1)), + ['John'] + ); $spans = $spanProcessor->endedSpans(); $insertSpan = \array_filter($spans, static fn ($s) => \str_contains($s->name(), 'INSERT')); @@ -215,11 +233,15 @@ public function test_transaction_creates_span() : void traceTransactions: true, traceQueries: false, )); - $client = traceable_postgresql_client($this->baseClient, $config); + $client = traceable_postgresql_client($this->pgsqlContext()->client(), $config); - $client->execute('CREATE TEMP TABLE test_tx_span (id serial PRIMARY KEY)'); + $client->execute( + create()->temporaryTable('test_tx_span') + ->column(column('id', column_type_serial())) + ->constraint(primary_key('id')) + ); $client->transaction(static function (Client $c) : void { - $c->execute('INSERT INTO test_tx_span DEFAULT VALUES'); + $c->execute(insert()->into('test_tx_span')->defaultValues()); }); $spans = $spanProcessor->endedSpans(); diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/TransactionTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/TransactionTest.php index 0c1015abd1..890fedd741 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/TransactionTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/TransactionTest.php @@ -4,53 +4,59 @@ namespace Flow\PostgreSql\Tests\Integration\Client; -use function Flow\PostgreSql\DSL\{agg_count, asc, col, insert, literal, select, table}; +use function Flow\PostgreSql\DSL\{agg_count, asc, col, column, column_type_serial, column_type_text, create, insert, literal, primary_key, select, table}; use Flow\PostgreSql\Client\Exception\TransactionException; +use Flow\PostgreSql\Tests\Integration\PostgreSqlTestCase; -final class TransactionTest extends ClientTestCase +final class TransactionTest extends PostgreSqlTestCase { protected function setUp() : void { parent::setUp(); - $this->client->execute('CREATE TEMP TABLE test_transaction (id serial PRIMARY KEY, name text)'); + $this->pgsqlContext()->client()->execute( + create()->temporaryTable('test_transaction') + ->column(column('id', column_type_serial())) + ->column(column('name', column_type_text())) + ->constraint(primary_key('id')) + ); } public function test_auto_commit_default_is_true() : void { - self::assertTrue($this->client->isAutoCommit()); + self::assertTrue($this->pgsqlContext()->client()->isAutoCommit()); } public function test_auto_commit_disabled_allows_rollback() : void { - $this->client->setAutoCommit(false); + $this->pgsqlContext()->client()->setAutoCommit(false); - $this->client->execute(insert()->into('test_transaction')->columns('name')->values(literal('will be rolled back'))); + $this->pgsqlContext()->client()->execute(insert()->into('test_transaction')->columns('name')->values(literal('will be rolled back'))); - $this->client->rollBack(); + $this->pgsqlContext()->client()->rollBack(); - $count = $this->client->fetchScalar(select(agg_count())->from(table('test_transaction'))); + $count = $this->pgsqlContext()->client()->fetchScalar(select(agg_count())->from(table('test_transaction'))); self::assertSame(0, $count); - self::assertSame(0, $this->client->getTransactionNestingLevel()); + self::assertSame(0, $this->pgsqlContext()->client()->getTransactionNestingLevel()); } public function test_auto_commit_disabled_starts_transaction() : void { - self::assertSame(0, $this->client->getTransactionNestingLevel()); + self::assertSame(0, $this->pgsqlContext()->client()->getTransactionNestingLevel()); - $this->client->setAutoCommit(false); + $this->pgsqlContext()->client()->setAutoCommit(false); - self::assertFalse($this->client->isAutoCommit()); - self::assertSame(1, $this->client->getTransactionNestingLevel()); + self::assertFalse($this->pgsqlContext()->client()->isAutoCommit()); + self::assertSame(1, $this->pgsqlContext()->client()->getTransactionNestingLevel()); - $this->client->execute(insert()->into('test_transaction')->columns('name')->values(literal('in transaction'))); + $this->pgsqlContext()->client()->execute(insert()->into('test_transaction')->columns('name')->values(literal('in transaction'))); - $this->client->setAutoCommit(true); - self::assertTrue($this->client->isAutoCommit()); - self::assertSame(0, $this->client->getTransactionNestingLevel()); + $this->pgsqlContext()->client()->setAutoCommit(true); + self::assertTrue($this->pgsqlContext()->client()->isAutoCommit()); + self::assertSame(0, $this->pgsqlContext()->client()->getTransactionNestingLevel()); - $count = $this->client->fetchScalar(select(agg_count())->from(table('test_transaction'))); + $count = $this->pgsqlContext()->client()->fetchScalar(select(agg_count())->from(table('test_transaction'))); self::assertSame(1, $count); } @@ -59,12 +65,12 @@ public function test_commit_without_transaction_throws() : void $this->expectException(TransactionException::class); $this->expectExceptionMessage('no active transaction'); - $this->client->commit(); + $this->pgsqlContext()->client()->commit(); } public function test_deeply_nested_transactions() : void { - $this->client->transaction(static function ($client) : void { + $this->pgsqlContext()->client()->transaction(static function ($client) : void { $client->execute(insert()->into('test_transaction')->columns('name')->values(literal('level1'))); $client->transaction(static function ($client) : void { @@ -76,46 +82,46 @@ public function test_deeply_nested_transactions() : void }); }); - $count = $this->client->fetchScalar(select(agg_count())->from(table('test_transaction'))); + $count = $this->pgsqlContext()->client()->fetchScalar(select(agg_count())->from(table('test_transaction'))); self::assertSame(3, $count); } public function test_explicit_begin_commit() : void { - $this->client->beginTransaction(); - $this->client->execute(insert()->into('test_transaction')->columns('name')->values(literal('explicit'))); - $this->client->commit(); + $this->pgsqlContext()->client()->beginTransaction(); + $this->pgsqlContext()->client()->execute(insert()->into('test_transaction')->columns('name')->values(literal('explicit'))); + $this->pgsqlContext()->client()->commit(); - $count = $this->client->fetchScalar(select(agg_count())->from(table('test_transaction'))); + $count = $this->pgsqlContext()->client()->fetchScalar(select(agg_count())->from(table('test_transaction'))); self::assertSame(1, $count); } public function test_explicit_begin_rollback() : void { - $this->client->beginTransaction(); - $this->client->execute(insert()->into('test_transaction')->columns('name')->values(literal('will_rollback'))); - $this->client->rollBack(); + $this->pgsqlContext()->client()->beginTransaction(); + $this->pgsqlContext()->client()->execute(insert()->into('test_transaction')->columns('name')->values(literal('will_rollback'))); + $this->pgsqlContext()->client()->rollBack(); - $count = $this->client->fetchScalar(select(agg_count())->from(table('test_transaction'))); + $count = $this->pgsqlContext()->client()->fetchScalar(select(agg_count())->from(table('test_transaction'))); self::assertSame(0, $count); } public function test_multiple_operations_in_transaction() : void { - $this->client->transaction(static function ($client) : void { + $this->pgsqlContext()->client()->transaction(static function ($client) : void { $client->execute(insert()->into('test_transaction')->columns('name')->values(literal('first'))); $client->execute(insert()->into('test_transaction')->columns('name')->values(literal('second'))); $client->execute(insert()->into('test_transaction')->columns('name')->values(literal('third'))); }); - $count = $this->client->fetchScalar(select(agg_count())->from(table('test_transaction'))); + $count = $this->pgsqlContext()->client()->fetchScalar(select(agg_count())->from(table('test_transaction'))); self::assertSame(3, $count); } public function test_nested_transaction_commits() : void { - $this->client->transaction(static function ($client) : void { + $this->pgsqlContext()->client()->transaction(static function ($client) : void { $client->execute(insert()->into('test_transaction')->columns('name')->values(literal('outer'))); $client->transaction(static function ($client) : void { @@ -123,13 +129,13 @@ public function test_nested_transaction_commits() : void }); }); - $count = $this->client->fetchScalar(select(agg_count())->from(table('test_transaction'))); + $count = $this->pgsqlContext()->client()->fetchScalar(select(agg_count())->from(table('test_transaction'))); self::assertSame(2, $count); } public function test_nested_transaction_inner_rollback() : void { - $this->client->transaction(static function ($client) : void { + $this->pgsqlContext()->client()->transaction(static function ($client) : void { $client->execute(insert()->into('test_transaction')->columns('name')->values(literal('outer'))); try { @@ -144,10 +150,10 @@ public function test_nested_transaction_inner_rollback() : void $client->execute(insert()->into('test_transaction')->columns('name')->values(literal('after inner'))); }); - $count = $this->client->fetchScalar(select(agg_count())->from(table('test_transaction'))); + $count = $this->pgsqlContext()->client()->fetchScalar(select(agg_count())->from(table('test_transaction'))); self::assertSame(2, $count); - $names = $this->client->fetchAll(select(col('name'))->from(table('test_transaction'))->orderBy(asc(col('id')))); + $names = $this->pgsqlContext()->client()->fetchAll(select(col('name'))->from(table('test_transaction'))->orderBy(asc(col('id')))); self::assertSame('outer', $names[0]['name']); self::assertSame('after inner', $names[1]['name']); } @@ -155,7 +161,7 @@ public function test_nested_transaction_inner_rollback() : void public function test_nested_transaction_outer_rollback_includes_inner() : void { try { - $this->client->transaction(static function ($client) : void { + $this->pgsqlContext()->client()->transaction(static function ($client) : void { $client->execute(insert()->into('test_transaction')->columns('name')->values(literal('outer'))); $client->transaction(static function ($client) : void { @@ -167,25 +173,25 @@ public function test_nested_transaction_outer_rollback_includes_inner() : void } catch (\RuntimeException) { } - $count = $this->client->fetchScalar(select(agg_count())->from(table('test_transaction'))); + $count = $this->pgsqlContext()->client()->fetchScalar(select(agg_count())->from(table('test_transaction'))); self::assertSame(0, $count); } public function test_nesting_level_tracking() : void { - self::assertSame(0, $this->client->getTransactionNestingLevel()); + self::assertSame(0, $this->pgsqlContext()->client()->getTransactionNestingLevel()); - $this->client->beginTransaction(); - self::assertSame(1, $this->client->getTransactionNestingLevel()); + $this->pgsqlContext()->client()->beginTransaction(); + self::assertSame(1, $this->pgsqlContext()->client()->getTransactionNestingLevel()); - $this->client->beginTransaction(); - self::assertSame(2, $this->client->getTransactionNestingLevel()); + $this->pgsqlContext()->client()->beginTransaction(); + self::assertSame(2, $this->pgsqlContext()->client()->getTransactionNestingLevel()); - $this->client->commit(); - self::assertSame(1, $this->client->getTransactionNestingLevel()); + $this->pgsqlContext()->client()->commit(); + self::assertSame(1, $this->pgsqlContext()->client()->getTransactionNestingLevel()); - $this->client->rollBack(); - self::assertSame(0, $this->client->getTransactionNestingLevel()); + $this->pgsqlContext()->client()->rollBack(); + self::assertSame(0, $this->pgsqlContext()->client()->getTransactionNestingLevel()); } public function test_rollback_without_transaction_throws() : void @@ -193,23 +199,23 @@ public function test_rollback_without_transaction_throws() : void $this->expectException(TransactionException::class); $this->expectExceptionMessage('no active transaction'); - $this->client->rollBack(); + $this->pgsqlContext()->client()->rollBack(); } public function test_set_auto_commit_same_value_does_nothing() : void { - self::assertTrue($this->client->isAutoCommit()); - self::assertSame(0, $this->client->getTransactionNestingLevel()); + self::assertTrue($this->pgsqlContext()->client()->isAutoCommit()); + self::assertSame(0, $this->pgsqlContext()->client()->getTransactionNestingLevel()); - $this->client->setAutoCommit(true); + $this->pgsqlContext()->client()->setAutoCommit(true); - self::assertTrue($this->client->isAutoCommit()); - self::assertSame(0, $this->client->getTransactionNestingLevel()); + self::assertTrue($this->pgsqlContext()->client()->isAutoCommit()); + self::assertSame(0, $this->pgsqlContext()->client()->getTransactionNestingLevel()); } public function test_transaction_can_query_within() : void { - $result = $this->client->transaction(static function ($client) { + $result = $this->pgsqlContext()->client()->transaction(static function ($client) { $client->execute(insert()->into('test_transaction')->columns('name')->values(literal('query test'))); return $client->fetchScalar(select(agg_count())->from(table('test_transaction'))); @@ -220,18 +226,18 @@ public function test_transaction_can_query_within() : void public function test_transaction_commits_on_success() : void { - $this->client->transaction(static function ($client) : void { + $this->pgsqlContext()->client()->transaction(static function ($client) : void { $client->execute(insert()->into('test_transaction')->columns('name')->values(literal('committed'))); }); - $count = $this->client->fetchScalar(select(agg_count())->from(table('test_transaction'))); + $count = $this->pgsqlContext()->client()->fetchScalar(select(agg_count())->from(table('test_transaction'))); self::assertSame(1, $count); } public function test_transaction_returns_callback_value() : void { - $result = $this->client->transaction(static function ($client) { + $result = $this->pgsqlContext()->client()->transaction(static function ($client) { $client->execute(insert()->into('test_transaction')->columns('name')->values(literal('test'))); return 'success'; @@ -243,7 +249,7 @@ public function test_transaction_returns_callback_value() : void public function test_transaction_rollbacks_on_exception() : void { try { - $this->client->transaction(static function ($client) : void { + $this->pgsqlContext()->client()->transaction(static function ($client) : void { $client->execute(insert()->into('test_transaction')->columns('name')->values(literal('will be rolled back'))); throw new \RuntimeException('Simulated failure'); @@ -251,7 +257,7 @@ public function test_transaction_rollbacks_on_exception() : void } catch (\RuntimeException) { } - $count = $this->client->fetchScalar(select(agg_count())->from(table('test_transaction'))); + $count = $this->pgsqlContext()->client()->fetchScalar(select(agg_count())->from(table('test_transaction'))); self::assertSame(0, $count); } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/BooleanConverterTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/BooleanConverterTest.php index 2a5dd3c617..dabf7f4045 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/BooleanConverterTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/BooleanConverterTest.php @@ -4,11 +4,12 @@ namespace Flow\PostgreSql\Tests\Integration\Client\Types\Converter; -use function Flow\PostgreSql\DSL\typed; -use Flow\PostgreSql\Client\Types\PostgreSqlType; +use function Flow\PostgreSql\DSL\{cast, column_type_boolean, literal, param, select, typed}; +use Flow\PostgreSql\Client\Types\ValueType; +use Flow\PostgreSql\Tests\Integration\PostgreSqlTestCase; use PHPUnit\Framework\Attributes\DataProvider; -final class BooleanConverterTest extends ConverterTestCase +final class BooleanConverterTest extends PostgreSqlTestCase { /** * @return \Generator @@ -37,7 +38,7 @@ public static function provide_boolean_values() : \Generator #[DataProvider('provide_boolean_values')] public function test_boolean_round_trip(bool $input, bool $expected) : void { - $result = $this->fetchValue('SELECT $1::bool AS val', [typed($input, PostgreSqlType::BOOL)]); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(param(1), column_type_boolean())->as('val'))->toSql(), [typed($input, ValueType::BOOL)]); self::assertSame($expected, $result); } @@ -45,14 +46,14 @@ public function test_boolean_round_trip(bool $input, bool $expected) : void #[DataProvider('provide_boolean_strings')] public function test_boolean_string_conversion(string $input, bool $expected) : void { - $result = $this->fetchValue('SELECT $1::bool AS val', [$input]); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(param(1), column_type_boolean())->as('val'))->toSql(), [$input]); self::assertSame($expected, $result); } public function test_null_boolean() : void { - $result = $this->fetchValue('SELECT NULL::bool AS val'); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(literal(null), column_type_boolean())->as('val'))->toSql()); self::assertNull($result); } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/ByteaConverterTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/ByteaConverterTest.php index 4a63d64d8c..62b4a47647 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/ByteaConverterTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/ByteaConverterTest.php @@ -4,9 +4,11 @@ namespace Flow\PostgreSql\Tests\Integration\Client\Types\Converter; +use function Flow\PostgreSql\DSL\{cast, column_type_bytea, literal, param, select}; +use Flow\PostgreSql\Tests\Integration\PostgreSqlTestCase; use PHPUnit\Framework\Attributes\DataProvider; -final class ByteaConverterTest extends ConverterTestCase +final class ByteaConverterTest extends PostgreSqlTestCase { /** * @return \Generator @@ -31,14 +33,14 @@ public static function provide_hex_bytea_values() : \Generator public function test_binary_data_via_hex_literal() : void { - $result = $this->fetchValue("SELECT '\\x00010203'::bytea AS val"); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(literal('\\x00010203'), column_type_bytea())->as('val'))->toSql()); self::assertSame("\x00\x01\x02\x03", $result); } public function test_binary_data_with_null_bytes_via_hex() : void { - $result = $this->fetchValue("SELECT '\\x7465737400646174610a'::bytea AS val"); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(literal('\\x7465737400646174610a'), column_type_bytea())->as('val'))->toSql()); self::assertSame("test\x00data\x0a", $result); } @@ -46,7 +48,7 @@ public function test_binary_data_with_null_bytes_via_hex() : void #[DataProvider('provide_hex_bytea_values')] public function test_bytea_hex_format(string $hexInput, string $expected) : void { - $result = $this->fetchValue("SELECT '\\x{$hexInput}'::bytea AS val"); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(literal('\\x' . $hexInput), column_type_bytea())->as('val'))->toSql()); self::assertSame($expected, $result); } @@ -54,7 +56,7 @@ public function test_bytea_hex_format(string $hexInput, string $expected) : void #[DataProvider('provide_bytea_values')] public function test_bytea_round_trip(string $input, string $expected) : void { - $result = $this->fetchValue('SELECT $1::bytea AS val', [$input]); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(param(1), column_type_bytea())->as('val'))->toSql(), [$input]); self::assertSame($expected, $result); } @@ -63,14 +65,14 @@ public function test_large_bytea_data() : void { $data = \str_repeat('abcdefghijklmnopqrstuvwxyz0123456789', 100); - $result = $this->fetchValue('SELECT $1::bytea AS val', [$data]); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(param(1), column_type_bytea())->as('val'))->toSql(), [$data]); self::assertSame($data, $result); } public function test_null_bytea() : void { - $result = $this->fetchValue('SELECT NULL::bytea AS val'); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(literal(null), column_type_bytea())->as('val'))->toSql()); self::assertNull($result); } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/CidrConverterTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/CidrConverterTest.php index 60805d9f61..b8002e3690 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/CidrConverterTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/CidrConverterTest.php @@ -4,11 +4,12 @@ namespace Flow\PostgreSql\Tests\Integration\Client\Types\Converter; -use function Flow\PostgreSql\DSL\typed; -use Flow\PostgreSql\Client\Types\PostgreSqlType; +use function Flow\PostgreSql\DSL\{cast, column_type_cidr, literal, param, select, typed}; +use Flow\PostgreSql\Client\Types\ValueType; +use Flow\PostgreSql\Tests\Integration\PostgreSqlTestCase; use PHPUnit\Framework\Attributes\DataProvider; -final class CidrConverterTest extends ConverterTestCase +final class CidrConverterTest extends PostgreSqlTestCase { /** * @return \Generator @@ -24,14 +25,14 @@ public static function provide_cidr_values() : \Generator #[DataProvider('provide_cidr_values')] public function test_cidr_round_trip(string $input, string $expected) : void { - $result = $this->fetchValue('SELECT $1::cidr AS val', [typed($input, PostgreSqlType::CIDR)]); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(param(1), column_type_cidr())->as('val'))->toSql(), [typed($input, ValueType::CIDR)]); self::assertSame($expected, $result); } public function test_null_cidr() : void { - $result = $this->fetchValue('SELECT NULL::cidr AS val'); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(literal(null), column_type_cidr())->as('val'))->toSql()); self::assertNull($result); } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/ConverterTestCase.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/ConverterTestCase.php deleted file mode 100644 index 1d70d61ce5..0000000000 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/ConverterTestCase.php +++ /dev/null @@ -1,51 +0,0 @@ -client = pgsql_client( - pgsql_connection_dsn($dsn), - mapper: pgsql_mapper(), - ); - } - - protected function tearDown() : void - { - if (isset($this->client)) { - $this->client->close(); - } - } - - /** - * @param array $params - * - * @return mixed - */ - protected function fetchValue(string $sql, array $params = []) - { - $row = $this->client->fetchOne($sql, $params); - - return \array_values($row)[0]; - } -} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/DateConverterTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/DateConverterTest.php index a1468e72e9..5efd57d510 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/DateConverterTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/DateConverterTest.php @@ -4,11 +4,12 @@ namespace Flow\PostgreSql\Tests\Integration\Client\Types\Converter; -use function Flow\PostgreSql\DSL\typed; -use Flow\PostgreSql\Client\Types\PostgreSqlType; +use function Flow\PostgreSql\DSL\{cast, column_type_date, literal, param, select, typed}; +use Flow\PostgreSql\Client\Types\ValueType; +use Flow\PostgreSql\Tests\Integration\PostgreSqlTestCase; use PHPUnit\Framework\Attributes\DataProvider; -final class DateConverterTest extends ConverterTestCase +final class DateConverterTest extends PostgreSqlTestCase { /** * @return \Generator @@ -41,7 +42,7 @@ public static function provide_datetime_to_date() : \Generator #[DataProvider('provide_date_values')] public function test_date_round_trip(string $input, string $expected) : void { - $result = $this->fetchValue('SELECT $1::date AS val', [$input]); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(param(1), column_type_date())->as('val'))->toSql(), [$input]); self::assertIsString($result); self::assertSame($expected, $result); @@ -50,7 +51,7 @@ public function test_date_round_trip(string $input, string $expected) : void #[DataProvider('provide_datetime_to_date')] public function test_datetime_object_to_date(\DateTimeImmutable $input, string $expected) : void { - $result = $this->fetchValue('SELECT $1::date AS val', [typed($input, PostgreSqlType::DATE)]); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(param(1), column_type_date())->as('val'))->toSql(), [typed($input, ValueType::DATE)]); self::assertIsString($result); self::assertSame($expected, $result); @@ -58,7 +59,7 @@ public function test_datetime_object_to_date(\DateTimeImmutable $input, string $ public function test_null_date() : void { - $result = $this->fetchValue('SELECT NULL::date AS val'); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(literal(null), column_type_date())->as('val'))->toSql()); self::assertNull($result); } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/DateTimeConverterTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/DateTimeConverterTest.php index 7d951835ba..54552eb449 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/DateTimeConverterTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/DateTimeConverterTest.php @@ -4,11 +4,12 @@ namespace Flow\PostgreSql\Tests\Integration\Client\Types\Converter; -use function Flow\PostgreSql\DSL\typed; -use Flow\PostgreSql\Client\Types\PostgreSqlType; +use function Flow\PostgreSql\DSL\{cast, column_type_timestamp, column_type_timestamptz, literal, param, select, typed}; +use Flow\PostgreSql\Client\Types\ValueType; +use Flow\PostgreSql\Tests\Integration\PostgreSqlTestCase; use PHPUnit\Framework\Attributes\DataProvider; -final class DateTimeConverterTest extends ConverterTestCase +final class DateTimeConverterTest extends PostgreSqlTestCase { /** * @return \Generator @@ -53,7 +54,7 @@ public static function provide_timestamptz_values() : \Generator #[DataProvider('provide_datetime_objects')] public function test_datetime_object_to_timestamp(\DateTimeImmutable $input, string $expected) : void { - $result = $this->fetchValue('SELECT $1::timestamp AS val', [typed($input, PostgreSqlType::TIMESTAMP)]); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(param(1), column_type_timestamp())->as('val'))->toSql(), [typed($input, ValueType::TIMESTAMP)]); self::assertIsString($result); self::assertSame($expected, $result); @@ -61,14 +62,14 @@ public function test_datetime_object_to_timestamp(\DateTimeImmutable $input, str public function test_null_timestamp() : void { - $result = $this->fetchValue('SELECT NULL::timestamp AS val'); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(literal(null), column_type_timestamp())->as('val'))->toSql()); self::assertNull($result); } public function test_null_timestamptz() : void { - $result = $this->fetchValue('SELECT NULL::timestamptz AS val'); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(literal(null), column_type_timestamptz())->as('val'))->toSql()); self::assertNull($result); } @@ -76,7 +77,7 @@ public function test_null_timestamptz() : void #[DataProvider('provide_timestamp_values')] public function test_timestamp_round_trip(string $input, string $expected) : void { - $result = $this->fetchValue('SELECT $1::timestamp AS val', [$input]); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(param(1), column_type_timestamp())->as('val'))->toSql(), [$input]); self::assertIsString($result); self::assertSame($expected, $result); @@ -85,7 +86,7 @@ public function test_timestamp_round_trip(string $input, string $expected) : voi #[DataProvider('provide_timestamp_with_microseconds')] public function test_timestamp_with_microseconds(string $input, string $expected) : void { - $result = $this->fetchValue('SELECT $1::timestamp AS val', [$input]); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(param(1), column_type_timestamp())->as('val'))->toSql(), [$input]); self::assertIsString($result); self::assertStringStartsWith($expected, $result); @@ -94,7 +95,7 @@ public function test_timestamp_with_microseconds(string $input, string $expected #[DataProvider('provide_timestamptz_values')] public function test_timestamptz_round_trip(string $input) : void { - $result = $this->fetchValue('SELECT $1::timestamptz AS val', [$input]); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(param(1), column_type_timestamptz())->as('val'))->toSql(), [$input]); self::assertIsString($result); } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/FloatConverterTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/FloatConverterTest.php index 93633fd6ce..2e9268de40 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/FloatConverterTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/FloatConverterTest.php @@ -4,11 +4,12 @@ namespace Flow\PostgreSql\Tests\Integration\Client\Types\Converter; -use function Flow\PostgreSql\DSL\typed; -use Flow\PostgreSql\Client\Types\PostgreSqlType; +use function Flow\PostgreSql\DSL\{cast, column_type_double_precision, column_type_numeric, column_type_real, literal, param, select, typed}; +use Flow\PostgreSql\Client\Types\ValueType; +use Flow\PostgreSql\Tests\Integration\PostgreSqlTestCase; use PHPUnit\Framework\Attributes\DataProvider; -final class FloatConverterTest extends ConverterTestCase +final class FloatConverterTest extends PostgreSqlTestCase { /** * @return \Generator @@ -48,7 +49,7 @@ public static function provide_numeric_values() : \Generator #[DataProvider('provide_float4_values')] public function test_float4_round_trip(float $input, float $expected) : void { - $result = $this->fetchValue('SELECT $1::float4 AS val', [typed($input, PostgreSqlType::FLOAT4)]); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(param(1), column_type_real())->as('val'))->toSql(), [typed($input, ValueType::FLOAT4)]); self::assertEqualsWithDelta($expected, $result, 0.0001); } @@ -56,14 +57,14 @@ public function test_float4_round_trip(float $input, float $expected) : void #[DataProvider('provide_float8_values')] public function test_float8_round_trip(float $input, float $expected) : void { - $result = $this->fetchValue('SELECT $1::float8 AS val', [typed($input, PostgreSqlType::FLOAT8)]); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(param(1), column_type_double_precision())->as('val'))->toSql(), [typed($input, ValueType::FLOAT8)]); self::assertEqualsWithDelta($expected, $result, 0.00000001); } public function test_null_float() : void { - $result = $this->fetchValue('SELECT NULL::float8 AS val'); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(literal(null), column_type_double_precision())->as('val'))->toSql()); self::assertNull($result); } @@ -71,28 +72,28 @@ public function test_null_float() : void #[DataProvider('provide_numeric_values')] public function test_numeric_round_trip(string $input, string $expected) : void { - $result = $this->fetchValue('SELECT $1::numeric AS val', [$input]); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(param(1), column_type_numeric())->as('val'))->toSql(), [$input]); self::assertSame($expected, $result); } public function test_special_float_infinity() : void { - $result = $this->fetchValue("SELECT 'Infinity'::float8 AS val"); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(literal('Infinity'), column_type_double_precision())->as('val'))->toSql()); self::assertSame(INF, $result); } public function test_special_float_nan() : void { - $result = $this->fetchValue("SELECT 'NaN'::float8 AS val"); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(literal('NaN'), column_type_double_precision())->as('val'))->toSql()); self::assertNan($result); } public function test_special_float_negative_infinity() : void { - $result = $this->fetchValue("SELECT '-Infinity'::float8 AS val"); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(literal('-Infinity'), column_type_double_precision())->as('val'))->toSql()); self::assertSame(-INF, $result); } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/InetConverterTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/InetConverterTest.php index a25fec8a0c..5fc6150275 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/InetConverterTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/InetConverterTest.php @@ -4,11 +4,12 @@ namespace Flow\PostgreSql\Tests\Integration\Client\Types\Converter; -use function Flow\PostgreSql\DSL\typed; -use Flow\PostgreSql\Client\Types\PostgreSqlType; +use function Flow\PostgreSql\DSL\{cast, column_type_inet, literal, param, select, typed}; +use Flow\PostgreSql\Client\Types\ValueType; +use Flow\PostgreSql\Tests\Integration\PostgreSqlTestCase; use PHPUnit\Framework\Attributes\DataProvider; -final class InetConverterTest extends ConverterTestCase +final class InetConverterTest extends PostgreSqlTestCase { /** * @return \Generator @@ -25,14 +26,14 @@ public static function provide_inet_values() : \Generator #[DataProvider('provide_inet_values')] public function test_inet_round_trip(string $input, string $expected) : void { - $result = $this->fetchValue('SELECT $1::inet AS val', [typed($input, PostgreSqlType::INET)]); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(param(1), column_type_inet())->as('val'))->toSql(), [typed($input, ValueType::INET)]); self::assertSame($expected, $result); } public function test_null_inet() : void { - $result = $this->fetchValue('SELECT NULL::inet AS val'); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(literal(null), column_type_inet())->as('val'))->toSql()); self::assertNull($result); } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/IntegerConverterTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/IntegerConverterTest.php index 130daacd4b..2411bed309 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/IntegerConverterTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/IntegerConverterTest.php @@ -4,11 +4,12 @@ namespace Flow\PostgreSql\Tests\Integration\Client\Types\Converter; -use function Flow\PostgreSql\DSL\typed; -use Flow\PostgreSql\Client\Types\PostgreSqlType; +use function Flow\PostgreSql\DSL\{cast, column_type_bigint, column_type_integer, column_type_smallint, literal, param, select, typed}; +use Flow\PostgreSql\Client\Types\ValueType; +use Flow\PostgreSql\Tests\Integration\PostgreSqlTestCase; use PHPUnit\Framework\Attributes\DataProvider; -final class IntegerConverterTest extends ConverterTestCase +final class IntegerConverterTest extends PostgreSqlTestCase { /** * @return \Generator @@ -47,7 +48,7 @@ public static function provide_int8_values() : \Generator #[DataProvider('provide_int2_values')] public function test_int2_round_trip(int $input, int $expected) : void { - $result = $this->fetchValue('SELECT $1::int2 AS val', [typed($input, PostgreSqlType::INT2)]); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(param(1), column_type_smallint())->as('val'))->toSql(), [typed($input, ValueType::INT2)]); self::assertSame($expected, $result); } @@ -55,7 +56,7 @@ public function test_int2_round_trip(int $input, int $expected) : void #[DataProvider('provide_int4_values')] public function test_int4_round_trip(int $input, int $expected) : void { - $result = $this->fetchValue('SELECT $1::int4 AS val', [typed($input, PostgreSqlType::INT4)]); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(param(1), column_type_integer())->as('val'))->toSql(), [typed($input, ValueType::INT4)]); self::assertSame($expected, $result); } @@ -63,14 +64,14 @@ public function test_int4_round_trip(int $input, int $expected) : void #[DataProvider('provide_int8_values')] public function test_int8_round_trip(int $input, int $expected) : void { - $result = $this->fetchValue('SELECT $1::int8 AS val', [typed($input, PostgreSqlType::INT8)]); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(param(1), column_type_bigint())->as('val'))->toSql(), [typed($input, ValueType::INT8)]); self::assertSame($expected, $result); } public function test_null_integer() : void { - $result = $this->fetchValue('SELECT NULL::int4 AS val'); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(literal(null), column_type_integer())->as('val'))->toSql()); self::assertNull($result); } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/JsonConverterTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/JsonConverterTest.php index 1299c43f4e..3a4a3eea50 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/JsonConverterTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/JsonConverterTest.php @@ -4,11 +4,12 @@ namespace Flow\PostgreSql\Tests\Integration\Client\Types\Converter; -use function Flow\PostgreSql\DSL\typed; -use Flow\PostgreSql\Client\Types\PostgreSqlType; +use function Flow\PostgreSql\DSL\{cast, column_type_json, column_type_jsonb, literal, param, select, typed}; +use Flow\PostgreSql\Client\Types\ValueType; +use Flow\PostgreSql\Tests\Integration\PostgreSqlTestCase; use PHPUnit\Framework\Attributes\DataProvider; -final class JsonConverterTest extends ConverterTestCase +final class JsonConverterTest extends PostgreSqlTestCase { /** * @return \Generator, string}> @@ -77,7 +78,7 @@ public static function provide_nested_json() : \Generator #[DataProvider('provide_json_arrays')] public function test_json_array_round_trip(array $input, string $expected) : void { - $result = $this->fetchValue('SELECT $1::json AS val', [typed($input, PostgreSqlType::JSON)]); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(param(1), column_type_json())->as('val'))->toSql(), [typed($input, ValueType::JSON)]); self::assertIsString($result); self::assertSame($expected, $result); @@ -86,7 +87,7 @@ public function test_json_array_round_trip(array $input, string $expected) : voi #[DataProvider('provide_json_strings')] public function test_json_string_round_trip(string $input) : void { - $result = $this->fetchValue('SELECT $1::json AS val', [$input]); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(param(1), column_type_json())->as('val'))->toSql(), [$input]); self::assertIsString($result); self::assertSame($input, $result); @@ -95,7 +96,7 @@ public function test_json_string_round_trip(string $input) : void #[DataProvider('provide_jsonb_strings')] public function test_jsonb_string_round_trip(string $input, string $expected) : void { - $result = $this->fetchValue('SELECT $1::jsonb AS val', [$input]); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(param(1), column_type_jsonb())->as('val'))->toSql(), [$input]); self::assertIsString($result); self::assertSame($expected, $result); @@ -107,7 +108,7 @@ public function test_jsonb_string_round_trip(string $input, string $expected) : #[DataProvider('provide_nested_json')] public function test_nested_json_round_trip(array $input) : void { - $result = $this->fetchValue('SELECT $1::json AS val', [typed($input, PostgreSqlType::JSON)]); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(param(1), column_type_json())->as('val'))->toSql(), [typed($input, ValueType::JSON)]); self::assertIsString($result); self::assertSame($input, \json_decode($result, true, 512, \JSON_THROW_ON_ERROR)); @@ -115,14 +116,14 @@ public function test_nested_json_round_trip(array $input) : void public function test_null_json() : void { - $result = $this->fetchValue('SELECT NULL::json AS val'); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(literal(null), column_type_json())->as('val'))->toSql()); self::assertNull($result); } public function test_null_jsonb() : void { - $result = $this->fetchValue('SELECT NULL::jsonb AS val'); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(literal(null), column_type_jsonb())->as('val'))->toSql()); self::assertNull($result); } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/MoneyConverterTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/MoneyConverterTest.php index 350370885c..a8f966a227 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/MoneyConverterTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/MoneyConverterTest.php @@ -4,11 +4,12 @@ namespace Flow\PostgreSql\Tests\Integration\Client\Types\Converter; -use function Flow\PostgreSql\DSL\typed; -use Flow\PostgreSql\Client\Types\PostgreSqlType; +use function Flow\PostgreSql\DSL\{cast, column_type_custom, literal, param, select, typed}; +use Flow\PostgreSql\Client\Types\ValueType; +use Flow\PostgreSql\Tests\Integration\PostgreSqlTestCase; use PHPUnit\Framework\Attributes\DataProvider; -final class MoneyConverterTest extends ConverterTestCase +final class MoneyConverterTest extends PostgreSqlTestCase { /** * @return \Generator @@ -22,7 +23,7 @@ public static function provide_money_values() : \Generator public function test_money_from_numeric() : void { - $result = $this->fetchValue('SELECT 99.99::money AS val'); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(literal(99.99), column_type_custom('money'))->as('val'))->toSql()); self::assertSame('$99.99', $result); } @@ -30,14 +31,14 @@ public function test_money_from_numeric() : void #[DataProvider('provide_money_values')] public function test_money_round_trip(string $input, string $expected) : void { - $result = $this->fetchValue('SELECT $1::money AS val', [typed($input, PostgreSqlType::MONEY)]); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(param(1), column_type_custom('money'))->as('val'))->toSql(), [typed($input, ValueType::MONEY)]); self::assertSame($expected, $result); } public function test_null_money() : void { - $result = $this->fetchValue('SELECT NULL::money AS val'); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(literal(null), column_type_custom('money'))->as('val'))->toSql()); self::assertNull($result); } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/NumericConverterTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/NumericConverterTest.php index d98ba01813..d4bbc27ac4 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/NumericConverterTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/NumericConverterTest.php @@ -4,11 +4,12 @@ namespace Flow\PostgreSql\Tests\Integration\Client\Types\Converter; -use function Flow\PostgreSql\DSL\typed; -use Flow\PostgreSql\Client\Types\PostgreSqlType; +use function Flow\PostgreSql\DSL\{cast, column_type_numeric, literal, param, select, typed}; +use Flow\PostgreSql\Client\Types\ValueType; +use Flow\PostgreSql\Tests\Integration\PostgreSqlTestCase; use PHPUnit\Framework\Attributes\DataProvider; -final class NumericConverterTest extends ConverterTestCase +final class NumericConverterTest extends PostgreSqlTestCase { /** * @return \Generator @@ -25,7 +26,7 @@ public static function provide_numeric_values() : \Generator public function test_null_numeric() : void { - $result = $this->fetchValue('SELECT NULL::numeric AS val'); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(literal(null), column_type_numeric())->as('val'))->toSql()); self::assertNull($result); } @@ -33,14 +34,14 @@ public function test_null_numeric() : void #[DataProvider('provide_numeric_values')] public function test_numeric_round_trip(string $input, string $expected) : void { - $result = $this->fetchValue('SELECT $1::numeric AS val', [typed($input, PostgreSqlType::NUMERIC)]); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(param(1), column_type_numeric())->as('val'))->toSql(), [typed($input, ValueType::NUMERIC)]); self::assertSame($expected, $result); } public function test_numeric_with_precision_and_scale() : void { - $result = $this->fetchValue('SELECT $1::numeric(10,2) AS val', [typed('1234.5678', PostgreSqlType::NUMERIC)]); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(param(1), column_type_numeric(10, 2))->as('val'))->toSql(), [typed('1234.5678', ValueType::NUMERIC)]); self::assertSame('1234.57', $result); } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/StringConverterTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/StringConverterTest.php index e2167f8adb..9464729f6b 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/StringConverterTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/StringConverterTest.php @@ -4,9 +4,11 @@ namespace Flow\PostgreSql\Tests\Integration\Client\Types\Converter; +use function Flow\PostgreSql\DSL\{cast, column_type_char, column_type_text, column_type_varchar, literal, param, select}; +use Flow\PostgreSql\Tests\Integration\PostgreSqlTestCase; use PHPUnit\Framework\Attributes\DataProvider; -final class StringConverterTest extends ConverterTestCase +final class StringConverterTest extends PostgreSqlTestCase { /** * @return \Generator @@ -45,14 +47,14 @@ public static function provide_varchar_values() : \Generator #[DataProvider('provide_char_values')] public function test_char_round_trip(string $input, string $expected) : void { - $result = $this->fetchValue('SELECT $1::char(10) AS val', [$input]); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(param(1), column_type_char(10))->as('val'))->toSql(), [$input]); self::assertSame($expected, $result); } public function test_null_text() : void { - $result = $this->fetchValue('SELECT NULL::text AS val'); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(literal(null), column_type_text())->as('val'))->toSql()); self::assertNull($result); } @@ -60,7 +62,7 @@ public function test_null_text() : void #[DataProvider('provide_text_values')] public function test_text_round_trip(string $input, string $expected) : void { - $result = $this->fetchValue('SELECT $1::text AS val', [$input]); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(param(1), column_type_text())->as('val'))->toSql(), [$input]); self::assertSame($expected, $result); } @@ -68,7 +70,7 @@ public function test_text_round_trip(string $input, string $expected) : void #[DataProvider('provide_varchar_values')] public function test_varchar_round_trip(string $input, string $expected) : void { - $result = $this->fetchValue('SELECT $1::varchar(255) AS val', [$input]); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(param(1), column_type_varchar(255))->as('val'))->toSql(), [$input]); self::assertSame($expected, $result); } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/TimeConverterTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/TimeConverterTest.php index 6012e9c9c2..5d3224de2a 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/TimeConverterTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/TimeConverterTest.php @@ -4,9 +4,11 @@ namespace Flow\PostgreSql\Tests\Integration\Client\Types\Converter; +use function Flow\PostgreSql\DSL\{cast, column_type_custom, column_type_time, literal, param, select}; +use Flow\PostgreSql\Tests\Integration\PostgreSqlTestCase; use PHPUnit\Framework\Attributes\DataProvider; -final class TimeConverterTest extends ConverterTestCase +final class TimeConverterTest extends PostgreSqlTestCase { /** * @return \Generator @@ -40,7 +42,7 @@ public static function provide_timetz_values() : \Generator public function test_null_time() : void { - $result = $this->fetchValue('SELECT NULL::time AS val'); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(literal(null), column_type_time())->as('val'))->toSql()); self::assertNull($result); } @@ -48,7 +50,7 @@ public function test_null_time() : void #[DataProvider('provide_time_values')] public function test_time_round_trip(string $input, string $expected) : void { - $result = $this->fetchValue('SELECT $1::time AS val', [$input]); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(param(1), column_type_time())->as('val'))->toSql(), [$input]); self::assertIsString($result); self::assertSame($expected, $result); @@ -57,7 +59,7 @@ public function test_time_round_trip(string $input, string $expected) : void #[DataProvider('provide_time_with_microseconds')] public function test_time_with_microseconds(string $input, string $expected) : void { - $result = $this->fetchValue('SELECT $1::time AS val', [$input]); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(param(1), column_type_time())->as('val'))->toSql(), [$input]); self::assertIsString($result); self::assertSame($expected, $result); @@ -66,7 +68,7 @@ public function test_time_with_microseconds(string $input, string $expected) : v #[DataProvider('provide_timetz_values')] public function test_timetz_round_trip(string $input, string $expectedTime, string $expectedOffset) : void { - $result = $this->fetchValue('SELECT $1::timetz AS val', [$input]); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(param(1), column_type_custom('timetz'))->as('val'))->toSql(), [$input]); self::assertIsString($result); self::assertStringStartsWith($expectedTime, $result); diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/UuidConverterTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/UuidConverterTest.php index 752ee1d286..3d943c16bf 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/UuidConverterTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/Client/Types/Converter/UuidConverterTest.php @@ -4,9 +4,11 @@ namespace Flow\PostgreSql\Tests\Integration\Client\Types\Converter; +use function Flow\PostgreSql\DSL\{cast, column_type_uuid, func, literal, param, select}; +use Flow\PostgreSql\Tests\Integration\PostgreSqlTestCase; use PHPUnit\Framework\Attributes\DataProvider; -final class UuidConverterTest extends ConverterTestCase +final class UuidConverterTest extends PostgreSqlTestCase { /** * @return \Generator @@ -21,7 +23,7 @@ public static function provide_uuid_strings() : \Generator public function test_gen_random_uuid() : void { - $result = $this->fetchValue('SELECT gen_random_uuid() AS val'); + $result = $this->pgsqlContext()->client()->fetchScalar(select(func('gen_random_uuid')->as('val'))->toSql()); self::assertIsString($result); self::assertMatchesRegularExpression( @@ -32,7 +34,7 @@ public function test_gen_random_uuid() : void public function test_null_uuid() : void { - $result = $this->fetchValue('SELECT NULL::uuid AS val'); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(literal(null), column_type_uuid())->as('val'))->toSql()); self::assertNull($result); } @@ -40,7 +42,7 @@ public function test_null_uuid() : void #[DataProvider('provide_uuid_strings')] public function test_uuid_string_round_trip(string $input) : void { - $result = $this->fetchValue('SELECT $1::uuid AS val', [$input]); + $result = $this->pgsqlContext()->client()->fetchScalar(select(cast(param(1), column_type_uuid())->as('val'))->toSql(), [$input]); self::assertIsString($result); self::assertSame(\strtolower($input), $result); diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/PostgreSqlContext.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/PostgreSqlContext.php new file mode 100644 index 0000000000..ea4232e2f2 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/PostgreSqlContext.php @@ -0,0 +1,85 @@ +client = pgsql_client(pgsql_connection_dsn($dsn)); + } + + public function client() : Client + { + return $this->client; + } + + public function close() : void + { + $this->client->close(); + } + + public function dropDomainIfExists(string $domain) : void + { + $this->client->execute(drop()->domain($domain)->ifExists()->cascade()->toSql()); + } + + public function dropFunctionIfExists(string $function) : void + { + $this->client->execute(drop()->function($function)->ifExists()->cascade()->toSql()); + } + + public function dropIndexIfExists(string $index) : void + { + $this->client->execute(drop()->index($index)->ifExists()->cascade()->toSql()); + } + + public function dropMaterializedViewIfExists(string $view) : void + { + $this->client->execute(drop()->materializedView($view)->ifExists()->cascade()->toSql()); + } + + public function dropSchemaIfExists(string $schema) : void + { + $this->client->execute(drop()->schema($schema)->ifExists()->cascade()->toSql()); + } + + public function dropSequenceIfExists(string $sequence) : void + { + $this->client->execute(drop()->sequence($sequence)->ifExists()->cascade()->toSql()); + } + + public function dropTableIfExists(string $table) : void + { + $this->client->execute(drop()->table($table)->ifExists()->cascade()->toSql()); + } + + public function dropTriggerIfExists(string $trigger, string $table) : void + { + $this->client->execute(drop()->trigger($trigger)->on($table)->ifExists()->cascade()->toSql()); + } + + public function dropTypeIfExists(string $type) : void + { + $this->client->execute(drop()->type($type)->ifExists()->cascade()->toSql()); + } + + public function dropViewIfExists(string $view) : void + { + $this->client->execute(drop()->view($view)->ifExists()->cascade()->toSql()); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/PostgreSqlTestCase.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/PostgreSqlTestCase.php new file mode 100644 index 0000000000..aebecc3c84 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/PostgreSqlTestCase.php @@ -0,0 +1,42 @@ +pgsqlContext = new PostgreSqlContext(); + } + + protected function tearDown() : void + { + if ($this->pgsqlContext !== null) { + $this->pgsqlContext->close(); + $this->pgsqlContext = null; + } + } + + protected function pgsqlContext() : PostgreSqlContext + { + if ($this->pgsqlContext === null) { + static::fail('PostgreSqlContext not initialized. Ensure setUp() was called.'); + } + + return $this->pgsqlContext; + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Assertions/QueryBuilderAssertions.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Assertions/QueryBuilderAssertions.php deleted file mode 100644 index 5d09a413ca..0000000000 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Assertions/QueryBuilderAssertions.php +++ /dev/null @@ -1,1014 +0,0 @@ -deparseAlterDomainStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertAlterEnumTypeQuery(AlterEnumTypeFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseAlterEnumStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertAlterExtensionQuery(AlterExtensionFinalStep $builder, string $expectedSql) : void - { - $ast = $builder->toAst(); - - if ($ast instanceof AlterExtensionStmt) { - $sql = $this->deparseAlterExtensionStmt($ast); - } else { - $sql = $this->deparseAlterExtensionContentsStmt($ast); - } - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertAlterFunctionQuery(AlterFunctionFinalStep $builder, string $expectedSql) : void - { - $ast = $builder->toAst(); - Assert::assertInstanceOf(AlterFunctionStmt::class, $ast); - $sql = $this->deparseAlterFunctionStmt($ast); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertAlterFunctionRenameQuery(AlterFunctionFinalStep $builder, string $expectedSql) : void - { - $ast = $builder->toAst(); - Assert::assertInstanceOf(RenameStmt::class, $ast); - $sql = $this->deparseRenameStmt($ast); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertAlterIndexRenameQuery(RenameIndexFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseRenameStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertAlterIndexTablespaceQuery(AlterTablespaceIndexFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseAlterTableStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertAlterMaterializedViewOwnerQuery(AlterMatViewOwnerFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseAlterTableStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertAlterMaterializedViewRenameQuery(RenameMatViewFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseRenameStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertAlterMaterializedViewSchemaQuery(AlterMatViewSchemaFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseAlterObjectSchemaStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertAlterMaterializedViewTablespaceQuery(AlterMatViewTablespaceFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseAlterTableStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertAlterObjectSchemaQuery(AlterTableSchemaBuilder $builder, string $expectedSql) : void - { - $sql = $this->deparseAlterObjectSchemaStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertAlterProcedureQuery(AlterProcedureFinalStep $builder, string $expectedSql) : void - { - $ast = $builder->toAst(); - Assert::assertInstanceOf(AlterFunctionStmt::class, $ast); - $sql = $this->deparseAlterFunctionStmt($ast); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertAlterProcedureRenameQuery(AlterProcedureFinalStep $builder, string $expectedSql) : void - { - $ast = $builder->toAst(); - Assert::assertInstanceOf(RenameStmt::class, $ast); - $sql = $this->deparseRenameStmt($ast); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertAlterRoleQuery(AlterRoleFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseAlterRoleStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertAlterRoleRenameQuery(AlterRoleRenameFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseRenameStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertAlterSchemaOwnerQuery(AlterSchemaOwnerFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseAlterOwnerStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertAlterSchemaRenameQuery(AlterSchemaRenameFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseRenameStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertAlterSequenceLoggingQuery(AlterSequenceLoggingFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseAlterTableStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertAlterSequenceOwnerQuery(AlterSequenceOwnerFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseAlterTableStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertAlterSequenceQuery(AlterSequenceOptionsStep $builder, string $expectedSql) : void - { - $sql = $this->deparseAlterSeqStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertAlterSequenceRenameQuery(RenameSequenceFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseRenameStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertAlterSequenceSchemaQuery(AlterSequenceSchemaFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseAlterObjectSchemaStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertAlterTableQuery(AlterTableFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseAlterTableStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertAlterTriggerDependsQuery(AlterTriggerFinalStep $builder, string $expectedSql) : void - { - $ast = $builder->toAst(); - Assert::assertInstanceOf(AlterObjectDependsStmt::class, $ast); - $sql = $this->deparseAlterObjectDependsStmt($ast); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertAlterTriggerRenameQuery(AlterTriggerFinalStep $builder, string $expectedSql) : void - { - $ast = $builder->toAst(); - Assert::assertInstanceOf(RenameStmt::class, $ast); - $sql = $this->deparseRenameStmt($ast); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertAlterViewOwnerQuery(AlterViewOwnerFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseAlterTableStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertAlterViewRenameQuery(RenameViewFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseRenameStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertAlterViewSchemaQuery(AlterViewSchemaFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseAlterObjectSchemaStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertAnalyzeQuery(AnalyzeFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseVacuumStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertCallQuery(CallFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseCallStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertClusterQuery(ClusterFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseClusterStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertCommentQuery(CommentFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseCommentStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertCreateCompositeTypeQuery(CreateCompositeTypeFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseCompositeTypeStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertCreateDomainQuery(CreateDomainOptionsStep $builder, string $expectedSql) : void - { - $sql = $this->deparseCreateDomainStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertCreateEnumTypeQuery(CreateEnumTypeFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseCreateEnumStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertCreateExtensionQuery(CreateExtensionOptionsStep $builder, string $expectedSql) : void - { - $sql = $this->deparseCreateExtensionStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertCreateFunctionQuery(CreateFunctionFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseCreateFunctionStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertCreateIndexQuery(CreateIndexFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseIndexStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertCreateMaterializedViewQuery(CreateMatViewFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseCreateTableAsStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertCreateProcedureQuery(CreateProcedureFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseCreateFunctionStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertCreateRangeTypeQuery(CreateRangeTypeFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseCreateRangeStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertCreateRoleQuery(CreateRoleFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseCreateRoleStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertCreateRuleQuery(CreateRuleFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseRuleStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertCreateSchemaQuery(CreateSchemaFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseCreateSchemaStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertCreateSequenceQuery(CreateSequenceOptionsStep $builder, string $expectedSql) : void - { - $sql = $this->deparseCreateSeqStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertCreateTableAsQuery(CreateTableAsFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseCreateTableAsStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertCreateTableQuery(CreateTableFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseCreateStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertCreateTriggerQuery(CreateTriggerFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseCreateTrigStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertCreateViewQuery(CreateViewFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseViewStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertDeleteQueryRoundTrip(DeleteFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseDeleteStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - - $parsed = sql_parse($sql); - $stmts = $parsed->raw()->getStmts(); - Assert::assertCount(1, $stmts); - - $rebuiltStmt = $stmts[0]->getStmt(); - Assert::assertNotNull($rebuiltStmt); - - $deleteStmt = $rebuiltStmt->getDeleteStmt(); - Assert::assertNotNull($deleteStmt); - - $rebuilt = DeleteBuilder::fromAst($deleteStmt); - $rebuiltSql = $this->deparseDeleteStmt($rebuilt->toAst()); - - Assert::assertSame($sql, $rebuiltSql); - } - - protected function assertDiscardQuery(DiscardFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseDiscardStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertDoQuery(DoFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseDoStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertDropDomainQuery(DropDomainFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseDropStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertDropExtensionQuery(DropExtensionFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseDropStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertDropFunctionQuery(DropFunctionFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseDropStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertDropIndexQuery(DropIndexFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseDropStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertDropMaterializedViewQuery(DropMatViewFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseDropStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertDropOwnedQuery(DropOwnedFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseDropOwnedStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertDropProcedureQuery(DropProcedureFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseDropStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertDropRoleQuery(DropRoleFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseDropRoleStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertDropRuleQuery(DropRuleFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseDropStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertDropSchemaQuery(DropSchemaFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseDropStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertDropSequenceQuery(DropSequenceFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseDropStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertDropTableQuery(DropTableFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseDropStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertDropTriggerQuery(DropTriggerFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseDropStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertDropTypeQuery(DropTypeFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseDropStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertDropViewQuery(DropViewFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseDropStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertExplainQuery(ExplainFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseExplainStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertGrantQuery(GrantFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseGrantStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertGrantRoleQuery(GrantRoleFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseGrantRoleStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertInsertQueryRoundTrip(InsertFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseInsertStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - - $parsed = sql_parse($sql); - $stmts = $parsed->raw()->getStmts(); - Assert::assertCount(1, $stmts); - - $rebuiltStmt = $stmts[0]->getStmt(); - Assert::assertNotNull($rebuiltStmt); - - $insertStmt = $rebuiltStmt->getInsertStmt(); - Assert::assertNotNull($insertStmt); - - $rebuilt = InsertBuilder::fromAst($insertStmt); - $rebuiltSql = $this->deparseInsertStmt($rebuilt->toAst()); - - Assert::assertSame($sql, $rebuiltSql); - } - - protected function assertLockQuery(LockFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseLockStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertReassignOwnedQuery(ReassignOwnedFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseReassignOwnedStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertRefreshMaterializedViewQuery(RefreshMatViewFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseRefreshMatViewStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertReindexQuery(ReindexFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseReindexStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertRenameQuery(RenameTableBuilder $builder, string $expectedSql) : void - { - $sql = $this->deparseRenameStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertResetRoleQuery(ResetRoleFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseVariableSetStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertRevokeQuery(RevokeFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseGrantStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertRevokeRoleQuery(RevokeRoleFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseGrantRoleStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertSelectQueryRoundTrip(SelectFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseSelectStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - - $parsed = sql_parse($sql); - $stmts = $parsed->raw()->getStmts(); - Assert::assertCount(1, $stmts); - - $rebuiltStmt = $stmts[0]->getStmt(); - Assert::assertNotNull($rebuiltStmt); - - $selectStmt = $rebuiltStmt->getSelectStmt(); - Assert::assertNotNull($selectStmt); - - $rebuilt = SelectBuilder::fromAst($selectStmt); - $rebuiltSql = $this->deparseSelectStmt($rebuilt->toAst()); - - Assert::assertSame($sql, $rebuiltSql); - } - - protected function assertSetRoleQuery(SetRoleFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseVariableSetStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertSetTransactionQueryEquals(SetTransactionFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseVariableSetStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertTransactionQueryEquals(BeginFinalStep|CommitFinalStep|RollbackFinalStep|SavepointFinalStep|PreparedTransactionFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseTransactionStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertTruncateQuery(TruncateFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseTruncateStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function assertUpdateQueryRoundTrip(UpdateFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseUpdateStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - - $parsed = sql_parse($sql); - $stmts = $parsed->raw()->getStmts(); - Assert::assertCount(1, $stmts); - - $rebuiltStmt = $stmts[0]->getStmt(); - Assert::assertNotNull($rebuiltStmt); - - $updateStmt = $rebuiltStmt->getUpdateStmt(); - Assert::assertNotNull($updateStmt); - - $rebuilt = UpdateBuilder::fromAst($updateStmt); - $rebuiltSql = $this->deparseUpdateStmt($rebuilt->toAst()); - - Assert::assertSame($sql, $rebuiltSql); - } - - protected function assertVacuumQuery(VacuumFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseVacuumStmt($builder->toAst()); - - Assert::assertSame($expectedSql, $sql); - } - - protected function deparseAlterDomainStmt(AlterDomainStmt $stmt) : string - { - return $this->deparseNode(new Node(['alter_domain_stmt' => $stmt])); - } - - protected function deparseAlterEnumStmt(AlterEnumStmt $stmt) : string - { - return $this->deparseNode(new Node(['alter_enum_stmt' => $stmt])); - } - - protected function deparseAlterExtensionContentsStmt(AlterExtensionContentsStmt $stmt) : string - { - return $this->deparseNode(new Node(['alter_extension_contents_stmt' => $stmt])); - } - - protected function deparseAlterExtensionStmt(AlterExtensionStmt $stmt) : string - { - return $this->deparseNode(new Node(['alter_extension_stmt' => $stmt])); - } - - protected function deparseAlterFunctionStmt(AlterFunctionStmt $stmt) : string - { - return $this->deparseNode(new Node(['alter_function_stmt' => $stmt])); - } - - protected function deparseAlterObjectDependsStmt(AlterObjectDependsStmt $stmt) : string - { - return $this->deparseNode(new Node(['alter_object_depends_stmt' => $stmt])); - } - - protected function deparseAlterObjectSchemaStmt(AlterObjectSchemaStmt $stmt) : string - { - return $this->deparseNode(new Node(['alter_object_schema_stmt' => $stmt])); - } - - protected function deparseAlterOwnerStmt(AlterOwnerStmt $stmt) : string - { - return $this->deparseNode(new Node(['alter_owner_stmt' => $stmt])); - } - - protected function deparseAlterRoleStmt(AlterRoleStmt $stmt) : string - { - return $this->deparseNode(new Node(['alter_role_stmt' => $stmt])); - } - - protected function deparseAlterSeqStmt(AlterSeqStmt $stmt) : string - { - return $this->deparseNode(new Node(['alter_seq_stmt' => $stmt])); - } - - protected function deparseAlterTableStmt(AlterTableStmt $stmt) : string - { - return $this->deparseNode(new Node(['alter_table_stmt' => $stmt])); - } - - protected function deparseCallStmt(CallStmt $stmt) : string - { - return $this->deparseNode(new Node(['call_stmt' => $stmt])); - } - - protected function deparseClusterStmt(ClusterStmt $stmt) : string - { - return $this->deparseNode(new Node(['cluster_stmt' => $stmt])); - } - - protected function deparseCommentStmt(CommentStmt $stmt) : string - { - return $this->deparseNode(new Node(['comment_stmt' => $stmt])); - } - - protected function deparseCompositeTypeStmt(CompositeTypeStmt $stmt) : string - { - return $this->deparseNode(new Node(['composite_type_stmt' => $stmt])); - } - - protected function deparseCreateDomainStmt(CreateDomainStmt $stmt) : string - { - return $this->deparseNode(new Node(['create_domain_stmt' => $stmt])); - } - - protected function deparseCreateEnumStmt(CreateEnumStmt $stmt) : string - { - return $this->deparseNode(new Node(['create_enum_stmt' => $stmt])); - } - - protected function deparseCreateExtensionStmt(CreateExtensionStmt $stmt) : string - { - return $this->deparseNode(new Node(['create_extension_stmt' => $stmt])); - } - - protected function deparseCreateFunctionStmt(CreateFunctionStmt $stmt) : string - { - return $this->deparseNode(new Node(['create_function_stmt' => $stmt])); - } - - protected function deparseCreateRangeStmt(CreateRangeStmt $stmt) : string - { - return $this->deparseNode(new Node(['create_range_stmt' => $stmt])); - } - - protected function deparseCreateRoleStmt(CreateRoleStmt $stmt) : string - { - return $this->deparseNode(new Node(['create_role_stmt' => $stmt])); - } - - protected function deparseCreateSchemaStmt(CreateSchemaStmt $stmt) : string - { - return $this->deparseNode(new Node(['create_schema_stmt' => $stmt])); - } - - protected function deparseCreateSeqStmt(CreateSeqStmt $stmt) : string - { - return $this->deparseNode(new Node(['create_seq_stmt' => $stmt])); - } - - protected function deparseCreateStmt(CreateStmt $stmt) : string - { - return $this->deparseNode(new Node(['create_stmt' => $stmt])); - } - - protected function deparseCreateTableAsStmt(CreateTableAsStmt $stmt) : string - { - return $this->deparseNode(new Node(['create_table_as_stmt' => $stmt])); - } - - protected function deparseCreateTrigStmt(CreateTrigStmt $stmt) : string - { - return $this->deparseNode(new Node(['create_trig_stmt' => $stmt])); - } - - protected function deparseDeleteStmt(DeleteStmt $deleteStmt) : string - { - return $this->deparseNode(new Node(['delete_stmt' => $deleteStmt])); - } - - protected function deparseDiscardStmt(DiscardStmt $stmt) : string - { - return $this->deparseNode(new Node(['discard_stmt' => $stmt])); - } - - protected function deparseDoStmt(DoStmt $stmt) : string - { - return $this->deparseNode(new Node(['do_stmt' => $stmt])); - } - - protected function deparseDropOwnedStmt(DropOwnedStmt $stmt) : string - { - return $this->deparseNode(new Node(['drop_owned_stmt' => $stmt])); - } - - protected function deparseDropRoleStmt(DropRoleStmt $stmt) : string - { - return $this->deparseNode(new Node(['drop_role_stmt' => $stmt])); - } - - protected function deparseDropStmt(DropStmt $stmt) : string - { - return $this->deparseNode(new Node(['drop_stmt' => $stmt])); - } - - protected function deparseExplainStmt(ExplainStmt $stmt) : string - { - return $this->deparseNode(new Node(['explain_stmt' => $stmt])); - } - - protected function deparseGrantRoleStmt(GrantRoleStmt $stmt) : string - { - return $this->deparseNode(new Node(['grant_role_stmt' => $stmt])); - } - - protected function deparseGrantStmt(GrantStmt $stmt) : string - { - return $this->deparseNode(new Node(['grant_stmt' => $stmt])); - } - - protected function deparseIndexStmt(IndexStmt $stmt) : string - { - return $this->deparseNode(new Node(['index_stmt' => $stmt])); - } - - protected function deparseInsertStmt(InsertStmt $insertStmt) : string - { - return $this->deparseNode(new Node(['insert_stmt' => $insertStmt])); - } - - protected function deparseLockStmt(LockStmt $stmt) : string - { - return $this->deparseNode(new Node(['lock_stmt' => $stmt])); - } - - protected function deparseReassignOwnedStmt(ReassignOwnedStmt $stmt) : string - { - return $this->deparseNode(new Node(['reassign_owned_stmt' => $stmt])); - } - - protected function deparseRefreshMatViewStmt(RefreshMatViewStmt $stmt) : string - { - return $this->deparseNode(new Node(['refresh_mat_view_stmt' => $stmt])); - } - - protected function deparseReindexStmt(ReindexStmt $stmt) : string - { - return $this->deparseNode(new Node(['reindex_stmt' => $stmt])); - } - - protected function deparseRenameStmt(RenameStmt $stmt) : string - { - return $this->deparseNode(new Node(['rename_stmt' => $stmt])); - } - - protected function deparseRuleStmt(RuleStmt $stmt) : string - { - return $this->deparseNode(new Node(['rule_stmt' => $stmt])); - } - - protected function deparseSelectStmt(SelectStmt $selectStmt) : string - { - return $this->deparseNode(new Node(['select_stmt' => $selectStmt])); - } - - protected function deparseTransactionStmt(TransactionStmt $stmt) : string - { - return $this->deparseNode(new Node(['transaction_stmt' => $stmt])); - } - - protected function deparseTruncateStmt(TruncateStmt $stmt) : string - { - return $this->deparseNode(new Node(['truncate_stmt' => $stmt])); - } - - protected function deparseUpdateStmt(UpdateStmt $updateStmt) : string - { - return $this->deparseNode(new Node(['update_stmt' => $updateStmt])); - } - - protected function deparseVacuumStmt(VacuumStmt $stmt) : string - { - return $this->deparseNode(new Node(['vacuum_stmt' => $stmt])); - } - - protected function deparseVariableSetStmt(VariableSetStmt $stmt) : string - { - return $this->deparseNode(new Node(['variable_set_stmt' => $stmt])); - } - - protected function deparseViewStmt(ViewStmt $stmt) : string - { - return $this->deparseNode(new Node(['view_stmt' => $stmt])); - } - - private function deparseNode(Node $node) : string - { - $parser = new Parser(); - $rawStmt = new RawStmt(['stmt' => $node]); - $parsed = $parser->parse('SELECT 1'); - $parseResult = $parsed->raw(); - $parseResult->setStmts([$rawStmt]); - - return (new ParsedQuery($parseResult))->deparse(); - } -} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/DatabaseTestCase.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/DatabaseTestCase.php deleted file mode 100644 index df7d8dd9a8..0000000000 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/DatabaseTestCase.php +++ /dev/null @@ -1,134 +0,0 @@ -connection = $this->connect($dsn); - } - - protected function tearDown() : void - { - if ($this->connection !== null) { - \pg_close($this->connection); - $this->connection = null; - } - } - - protected function affectedRows(Result $result) : int - { - return \pg_affected_rows($result); - } - - protected function connect(string $dsn) : Connection - { - $parts = \parse_url($dsn); - - if ($parts === false) { - static::fail('Failed to parse PGSQL_DATABASE_URL'); - } - - $connString = \sprintf( - "host='%s' port='%s' dbname='%s' user='%s' password='%s'", - $parts['host'] ?? 'localhost', - $parts['port'] ?? '5432', - \ltrim($parts['path'] ?? '/postgres', '/'), - $parts['user'] ?? 'postgres', - $parts['pass'] ?? '' - ); - - $conn = \pg_connect($connString); - - if ($conn === false) { - static::fail('Failed to connect to PostgreSQL'); - } - - return $conn; - } - - protected function dropIndexIfExists(string $index) : void - { - $this->execute(drop()->index($index)->ifExists()->cascade()->toSql()); - } - - protected function dropMaterializedViewIfExists(string $view) : void - { - $this->execute(drop()->materializedView($view)->ifExists()->cascade()->toSql()); - } - - protected function dropSequenceIfExists(string $sequence) : void - { - $this->execute(drop()->sequence($sequence)->ifExists()->cascade()->toSql()); - } - - protected function dropTableIfExists(string $table) : void - { - $this->execute(drop()->table($table)->ifExists()->cascade()->toSql()); - } - - protected function dropViewIfExists(string $view) : void - { - $this->execute(drop()->view($view)->ifExists()->cascade()->toSql()); - } - - protected function execute(string $sql) : Result|false - { - if ($this->connection === null) { - static::fail('No database connection'); - } - - return \pg_query($this->connection, $sql); - } - - /** - * Fetch all rows from a result. Asserts result is valid. - * - * @return array> - */ - protected function fetchAll(Result|false $result) : array - { - static::assertNotFalse($result, 'Query failed'); - - return \pg_fetch_all($result) ?: []; - } - - /** - * Fetch one row from a result. Asserts result is valid. - * - * @return array - */ - protected function fetchOne(Result|false $result) : array - { - static::assertNotFalse($result, 'Query failed'); - - $row = \pg_fetch_assoc($result); - static::assertIsArray($row, 'No row returned'); - - /** @var array $row */ - return $row; - } -} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/DeleteDatabaseTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/DeleteDatabaseTest.php index ae80cd3766..7cc00d2f56 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/DeleteDatabaseTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/DeleteDatabaseTest.php @@ -8,24 +8,25 @@ agg_count, col, column, - cond_or, + column_type_integer, + column_type_serial, + column_type_text, + column_type_timestamp, + column_type_varchar, create, - data_type_integer, - data_type_serial, - data_type_text, - data_type_timestamp, - data_type_varchar, delete, eq, insert, literal, + or_, primary_key, select, star, table }; +use Flow\PostgreSql\Tests\Integration\PostgreSqlTestCase; -final class DeleteDatabaseTest extends DatabaseTestCase +final class DeleteDatabaseTest extends PostgreSqlTestCase { private const SCHEMA_NAME = 'flow_postgres_test_delete_schema'; @@ -39,25 +40,25 @@ protected function setUp() : void { parent::setUp(); - $this->execute( + $this->pgsqlContext()->client()->execute( create()->table(self::TABLE_LOGS) - ->column(column('id', data_type_serial())) - ->column(column('level', data_type_varchar(20))->notNull()) - ->column(column('message', data_type_text())) - ->column(column('created_at', data_type_timestamp())) + ->column(column('id', column_type_serial())) + ->column(column('level', column_type_varchar(20))->notNull()) + ->column(column('message', column_type_text())) + ->column(column('created_at', column_type_timestamp())) ->constraint(primary_key('id')) ->toSql() ); - $this->execute( + $this->pgsqlContext()->client()->execute( create()->table(self::TABLE_ARCHIVE) - ->column(column('id', data_type_serial())) - ->column(column('log_id', data_type_integer())->notNull()) + ->column(column('id', column_type_serial())) + ->column(column('log_id', column_type_integer())->notNull()) ->constraint(primary_key('id')) ->toSql() ); - $this->execute( + $this->pgsqlContext()->client()->execute( insert() ->into(self::TABLE_LOGS) ->columns('level', 'message') @@ -69,7 +70,7 @@ protected function setUp() : void ->toSql() ); - $this->execute( + $this->pgsqlContext()->client()->execute( insert() ->into(self::TABLE_ARCHIVE) ->columns('log_id') @@ -81,9 +82,9 @@ protected function setUp() : void protected function tearDown() : void { - $this->dropTableIfExists(self::TABLE_ARCHIVE); - $this->dropTableIfExists(self::TABLE_LOGS); - $this->execute('DROP SCHEMA IF EXISTS ' . self::SCHEMA_NAME . ' CASCADE'); + $this->pgsqlContext()->dropTableIfExists(self::TABLE_ARCHIVE); + $this->pgsqlContext()->dropTableIfExists(self::TABLE_LOGS); + $this->pgsqlContext()->dropSchemaIfExists(self::SCHEMA_NAME); parent::tearDown(); } @@ -93,18 +94,14 @@ public function test_delete_all() : void $query = delete() ->from(self::TABLE_ARCHIVE); - $result = $this->execute($query->toSql()); + self::assertSame(2, $this->pgsqlContext()->client()->execute($query->toSql())); - self::assertNotFalse($result); - self::assertSame(2, $this->affectedRows($result)); - - $check = $this->execute( + $row = $this->pgsqlContext()->client()->fetchOne( select(agg_count(star())->as('cnt')) ->from(table(self::TABLE_ARCHIVE)) ->toSql() ); - $row = $this->fetchOne($check); - self::assertSame('0', $row['cnt']); + self::assertSame(0, $row['cnt']); } public function test_delete_with_multiple_conditions() : void @@ -112,16 +109,13 @@ public function test_delete_with_multiple_conditions() : void $query = delete() ->from(self::TABLE_LOGS) ->where( - cond_or( + or_( eq(col('level'), literal('INFO')), eq(col('level'), literal('WARNING')) ) ); - $result = $this->execute($query->toSql()); - - self::assertNotFalse($result); - self::assertSame(2, $this->affectedRows($result)); + self::assertSame(2, $this->pgsqlContext()->client()->execute($query->toSql())); } public function test_delete_with_returning() : void @@ -131,17 +125,15 @@ public function test_delete_with_returning() : void ->where(eq(col('level'), literal('ERROR'))) ->returning(col('id'), col('level'), col('message')); - $result = $this->execute($query->toSql()); + $row = $this->pgsqlContext()->client()->fetchOne($query->toSql()); - self::assertNotFalse($result); - $row = $this->fetchOne($result); self::assertSame('ERROR', $row['level']); self::assertSame('Error occurred', $row['message']); } public function test_delete_with_returning_all() : void { - $this->execute( + $this->pgsqlContext()->client()->execute( insert() ->into(self::TABLE_LOGS) ->columns('level', 'message') @@ -154,10 +146,8 @@ public function test_delete_with_returning_all() : void ->where(eq(col('level'), literal('TRACE'))) ->returningAll(); - $result = $this->execute($query->toSql()); + $row = $this->pgsqlContext()->client()->fetchOne($query->toSql()); - self::assertNotFalse($result); - $row = $this->fetchOne($result); self::assertArrayHasKey('id', $row); self::assertArrayHasKey('level', $row); self::assertArrayHasKey('message', $row); @@ -166,18 +156,18 @@ public function test_delete_with_returning_all() : void public function test_delete_with_schema_qualified_table() : void { - $this->execute('CREATE SCHEMA IF NOT EXISTS ' . self::SCHEMA_NAME); + $this->pgsqlContext()->client()->execute('CREATE SCHEMA IF NOT EXISTS ' . self::SCHEMA_NAME); - $this->execute( + $this->pgsqlContext()->client()->execute( create()->table(self::SCHEMA_TABLE, self::SCHEMA_NAME) - ->column(column('id', data_type_serial())) - ->column(column('level', data_type_varchar(20))->notNull()) - ->column(column('message', data_type_text())) + ->column(column('id', column_type_serial())) + ->column(column('level', column_type_varchar(20))->notNull()) + ->column(column('message', column_type_text())) ->constraint(primary_key('id')) ->toSql() ); - $this->execute( + $this->pgsqlContext()->client()->execute( insert() ->into(self::SCHEMA_NAME . '.' . self::SCHEMA_TABLE) ->columns('level', 'message') @@ -190,18 +180,14 @@ public function test_delete_with_schema_qualified_table() : void ->from(self::SCHEMA_NAME . '.' . self::SCHEMA_TABLE) ->where(eq(col('level'), literal('DEBUG'))); - $result = $this->execute($query->toSql()); - - self::assertNotFalse($result); - self::assertSame(1, $this->affectedRows($result)); + self::assertSame(1, $this->pgsqlContext()->client()->execute($query->toSql())); - $check = $this->execute( + $row = $this->pgsqlContext()->client()->fetchOne( select(agg_count(star())->as('cnt')) ->from(table(self::SCHEMA_TABLE, self::SCHEMA_NAME)) ->toSql() ); - $row = $this->fetchOne($check); - self::assertSame('1', $row['cnt']); + self::assertSame(1, $row['cnt']); } public function test_delete_with_using() : void @@ -216,10 +202,7 @@ public function test_delete_with_using() : void ) ); - $result = $this->execute($query->toSql()); - - self::assertNotFalse($result); - self::assertSame(2, $this->affectedRows($result)); + self::assertSame(2, $this->pgsqlContext()->client()->execute($query->toSql())); } public function test_delete_with_where() : void @@ -228,18 +211,14 @@ public function test_delete_with_where() : void ->from(self::TABLE_LOGS) ->where(eq(col('level'), literal('DEBUG'))); - $result = $this->execute($query->toSql()); - - self::assertNotFalse($result); - self::assertSame(2, $this->affectedRows($result)); + self::assertSame(2, $this->pgsqlContext()->client()->execute($query->toSql())); - $check = $this->execute( + $row = $this->pgsqlContext()->client()->fetchOne( select(agg_count(star())->as('cnt')) ->from(table(self::TABLE_LOGS)) ->where(eq(col('level'), literal('DEBUG'))) ->toSql() ); - $row = $this->fetchOne($check); - self::assertSame('0', $row['cnt']); + self::assertSame(0, $row['cnt']); } } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/DomainDatabaseTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/DomainDatabaseTest.php index cf59bc8bb4..034cf5ac8d 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/DomainDatabaseTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/DomainDatabaseTest.php @@ -6,10 +6,12 @@ use function Flow\PostgreSql\DSL\{ alter, + col, column, + column_type_serial, create, - data_type_serial, drop, + gt, insert, literal, primary_key, @@ -18,9 +20,11 @@ table }; -use Flow\PostgreSql\QueryBuilder\Schema\DataType; +use Flow\PostgreSql\QueryBuilder\Condition\OperatorCondition; +use Flow\PostgreSql\QueryBuilder\Schema\ColumnType; +use Flow\PostgreSql\Tests\Integration\PostgreSqlTestCase; -final class DomainDatabaseTest extends DatabaseTestCase +final class DomainDatabaseTest extends PostgreSqlTestCase { private const DOMAIN_NAME = 'flow_postgres_email_domain'; @@ -30,150 +34,149 @@ final class DomainDatabaseTest extends DatabaseTestCase protected function tearDown() : void { - $this->dropTableIfExists(self::TABLE_NAME); - $this->dropDomainIfExists(self::DOMAIN_NAME); - $this->dropDomainIfExists(self::DOMAIN_NAME_2); + $this->pgsqlContext()->dropTableIfExists(self::TABLE_NAME); + $this->pgsqlContext()->dropDomainIfExists(self::DOMAIN_NAME); + $this->pgsqlContext()->dropDomainIfExists(self::DOMAIN_NAME_2); parent::tearDown(); } public function test_alter_domain_add_constraint() : void { - $this->execute( + $this->expectNotToPerformAssertions(); + + $this->pgsqlContext()->client()->execute( create()->domain(self::DOMAIN_NAME_2) - ->as(DataType::integer()) + ->as(ColumnType::integer()) ->toSql() ); - $result = $this->execute( + $this->pgsqlContext()->client()->execute( alter()->domain(self::DOMAIN_NAME_2) - ->addConstraint('positive_check', 'VALUE > 0') + ->addConstraint('positive_check', gt(col('value'), literal(0))) ->toSql() ); - - self::assertNotFalse($result); } public function test_alter_domain_drop_constraint() : void { - $this->execute( + $this->expectNotToPerformAssertions(); + + $this->pgsqlContext()->client()->execute( create()->domain(self::DOMAIN_NAME_2) - ->as(DataType::integer()) + ->as(ColumnType::integer()) ->constraint('positive_check') - ->check('VALUE > 0') + ->check(gt(col('value'), literal(0))) ->toSql() ); - $result = $this->execute( + $this->pgsqlContext()->client()->execute( alter()->domain(self::DOMAIN_NAME_2) ->dropConstraint('positive_check') ->toSql() ); - - self::assertNotFalse($result); } public function test_alter_domain_drop_default() : void { - $this->execute( + $this->expectNotToPerformAssertions(); + + $this->pgsqlContext()->client()->execute( create()->domain(self::DOMAIN_NAME_2) - ->as(DataType::integer()) - ->default('0') + ->as(ColumnType::integer()) + ->default(literal(0)) ->toSql() ); - $result = $this->execute( + $this->pgsqlContext()->client()->execute( alter()->domain(self::DOMAIN_NAME_2) ->dropDefault() ->toSql() ); - - self::assertNotFalse($result); } public function test_alter_domain_drop_not_null() : void { - $this->execute( + $this->expectNotToPerformAssertions(); + + $this->pgsqlContext()->client()->execute( create()->domain(self::DOMAIN_NAME_2) - ->as(DataType::integer()) + ->as(ColumnType::integer()) ->notNull() ->toSql() ); - $result = $this->execute( + $this->pgsqlContext()->client()->execute( alter()->domain(self::DOMAIN_NAME_2) ->dropNotNull() ->toSql() ); - - self::assertNotFalse($result); } public function test_alter_domain_set_default() : void { - $this->execute( + $this->expectNotToPerformAssertions(); + + $this->pgsqlContext()->client()->execute( create()->domain(self::DOMAIN_NAME_2) - ->as(DataType::integer()) + ->as(ColumnType::integer()) ->toSql() ); - $result = $this->execute( + $this->pgsqlContext()->client()->execute( alter()->domain(self::DOMAIN_NAME_2) - ->setDefault('100') + ->setDefault(literal(100)) ->toSql() ); - - self::assertNotFalse($result); } public function test_alter_domain_set_not_null() : void { - $this->execute( + $this->expectNotToPerformAssertions(); + + $this->pgsqlContext()->client()->execute( create()->domain(self::DOMAIN_NAME_2) - ->as(DataType::integer()) + ->as(ColumnType::integer()) ->toSql() ); - $result = $this->execute( + $this->pgsqlContext()->client()->execute( alter()->domain(self::DOMAIN_NAME_2) ->setNotNull() ->toSql() ); - - self::assertNotFalse($result); } public function test_create_domain() : void { - $result = $this->execute( + $this->pgsqlContext()->client()->execute( create()->domain(self::DOMAIN_NAME) - ->as(DataType::varchar(255)) + ->as(ColumnType::varchar(255)) ->toSql() ); - self::assertNotFalse($result); self::assertTrue($this->domainExists(self::DOMAIN_NAME)); } public function test_create_domain_and_use_in_table() : void { - $this->execute( + $this->pgsqlContext()->client()->execute( create()->domain(self::DOMAIN_NAME) - ->as(DataType::varchar(255)) + ->as(ColumnType::varchar(255)) ->constraint('valid_email') - ->check("VALUE ~ '^[^@]+@[^@]+\\.[^@]+$'") + ->check(new OperatorCondition(col('value'), '~', literal('^[^@]+@[^@]+\\.[^@]+$'))) ->toSql() ); - $this->execute( + $this->pgsqlContext()->client()->execute( create()->table(self::TABLE_NAME) - ->column(column('id', data_type_serial())) - ->column(column('email', DataType::custom(self::DOMAIN_NAME))->notNull()) + ->column(column('id', column_type_serial())) + ->column(column('email', ColumnType::custom(self::DOMAIN_NAME))->notNull()) ->constraint(primary_key('id')) ->toSql() ); - $this->execute( + $this->pgsqlContext()->client()->execute( insert() ->into(self::TABLE_NAME) ->columns('email') @@ -181,10 +184,8 @@ public function test_create_domain_and_use_in_table() : void ->toSql() ); - $row = $this->fetchOne( - $this->execute( - select(star())->from(table(self::TABLE_NAME))->toSql() - ) + $row = $this->pgsqlContext()->client()->fetchOne( + select(star())->from(table(self::TABLE_NAME))->toSql() ); self::assertSame('test@example.com', $row['email']); @@ -192,113 +193,101 @@ public function test_create_domain_and_use_in_table() : void public function test_create_domain_with_check_constraint() : void { - $result = $this->execute( + $this->pgsqlContext()->client()->execute( create()->domain(self::DOMAIN_NAME) - ->as(DataType::varchar(255)) + ->as(ColumnType::varchar(255)) ->constraint('valid_email') - ->check("VALUE ~ '^[^@]+@[^@]+\\.[^@]+$'") + ->check(new OperatorCondition(col('value'), '~', literal('^[^@]+@[^@]+\\.[^@]+$'))) ->toSql() ); - self::assertNotFalse($result); self::assertTrue($this->domainExists(self::DOMAIN_NAME)); } public function test_create_domain_with_default() : void { - $result = $this->execute( + $this->pgsqlContext()->client()->execute( create()->domain(self::DOMAIN_NAME_2) - ->as(DataType::integer()) - ->default('0') + ->as(ColumnType::integer()) + ->default(literal(0)) ->toSql() ); - self::assertNotFalse($result); self::assertTrue($this->domainExists(self::DOMAIN_NAME_2)); } public function test_create_domain_with_not_null() : void { - $result = $this->execute( + $this->pgsqlContext()->client()->execute( create()->domain(self::DOMAIN_NAME) - ->as(DataType::varchar(255)) + ->as(ColumnType::varchar(255)) ->notNull() ->toSql() ); - self::assertNotFalse($result); self::assertTrue($this->domainExists(self::DOMAIN_NAME)); } public function test_drop_domain() : void { - $this->execute( + $this->pgsqlContext()->client()->execute( create()->domain(self::DOMAIN_NAME) - ->as(DataType::varchar(255)) + ->as(ColumnType::varchar(255)) ->toSql() ); self::assertTrue($this->domainExists(self::DOMAIN_NAME)); - $result = $this->execute( + $this->pgsqlContext()->client()->execute( drop()->domain(self::DOMAIN_NAME)->toSql() ); - self::assertNotFalse($result); self::assertFalse($this->domainExists(self::DOMAIN_NAME)); } public function test_drop_domain_cascade() : void { - $this->execute( + $this->pgsqlContext()->client()->execute( create()->domain(self::DOMAIN_NAME) - ->as(DataType::varchar(255)) + ->as(ColumnType::varchar(255)) ->toSql() ); - $this->execute( + $this->pgsqlContext()->client()->execute( create()->table(self::TABLE_NAME) - ->column(column('id', data_type_serial())) - ->column(column('email', DataType::custom(self::DOMAIN_NAME))) + ->column(column('id', column_type_serial())) + ->column(column('email', ColumnType::custom(self::DOMAIN_NAME))) ->constraint(primary_key('id')) ->toSql() ); - $result = $this->execute( + $this->pgsqlContext()->client()->execute( drop()->domain(self::DOMAIN_NAME)->cascade()->toSql() ); - self::assertNotFalse($result); self::assertFalse($this->domainExists(self::DOMAIN_NAME)); } public function test_drop_domain_if_exists() : void { - $result = $this->execute( + $this->expectNotToPerformAssertions(); + + $this->pgsqlContext()->client()->execute( drop()->domain(self::DOMAIN_NAME)->ifExists()->toSql() ); - - self::assertNotFalse($result); } - protected function domainExists(string $name) : bool + private function domainExists(string $name) : bool { - $row = $this->fetchOne( - $this->execute( - "SELECT EXISTS( + $row = $this->pgsqlContext()->client()->fetchOne( + "SELECT EXISTS( SELECT 1 FROM pg_type t JOIN pg_namespace n ON t.typnamespace = n.oid WHERE t.typname = '{$name}' AND t.typtype = 'd' ) AS domain_exists" - ) ); - return $row['domain_exists'] === 't'; - } - - protected function dropDomainIfExists(string $name) : void - { - $this->execute("DROP DOMAIN IF EXISTS {$name} CASCADE"); + return $row['domain_exists'] === true; } } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/FunctionDatabaseTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/FunctionDatabaseTest.php index e57f6b5181..41ab56ba53 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/FunctionDatabaseTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/FunctionDatabaseTest.php @@ -5,15 +5,23 @@ namespace Flow\PostgreSql\Tests\Integration\QueryBuilder\Database; use function Flow\PostgreSql\DSL\{ + agg_count, alter, + col, + column_type_integer, create, - data_type_integer, drop, - func_arg + eq, + func, + func_arg, + literal, + select, + table }; use Flow\PostgreSql\QueryBuilder\Schema\Function\ParallelSafety; +use Flow\PostgreSql\Tests\Integration\PostgreSqlTestCase; -final class FunctionDatabaseTest extends DatabaseTestCase +final class FunctionDatabaseTest extends PostgreSqlTestCase { private const FUNCTION_NAME = 'flow_postgres_test_func'; @@ -23,61 +31,59 @@ final class FunctionDatabaseTest extends DatabaseTestCase protected function tearDown() : void { - $this->dropFunctionIfExists(self::FUNCTION_NAME); - $this->dropFunctionIfExists(self::FUNCTION_NAME_2); - $this->dropFunctionIfExists(self::FUNCTION_NAME_RENAMED); + $this->pgsqlContext()->dropFunctionIfExists(self::FUNCTION_NAME); + $this->pgsqlContext()->dropFunctionIfExists(self::FUNCTION_NAME_2); + $this->pgsqlContext()->dropFunctionIfExists(self::FUNCTION_NAME_RENAMED); parent::tearDown(); } public function test_alter_function_rename() : void { - $this->execute( + $this->pgsqlContext()->client()->execute( create()->function(self::FUNCTION_NAME) ->arguments() - ->returns(data_type_integer()) + ->returns(column_type_integer()) ->language('sql') ->as('SELECT 42') ->toSql() ); - $result = $this->execute( + $this->pgsqlContext()->client()->execute( alter()->function(self::FUNCTION_NAME) ->arguments() ->renameTo(self::FUNCTION_NAME_RENAMED) ->toSql() ); - self::assertNotFalse($result); self::assertFalse($this->functionExists(self::FUNCTION_NAME)); self::assertTrue($this->functionExists(self::FUNCTION_NAME_RENAMED)); } public function test_alter_function_set_volatility() : void { - $this->execute( + $this->pgsqlContext()->client()->execute( create()->function(self::FUNCTION_NAME) ->arguments() - ->returns(data_type_integer()) + ->returns(column_type_integer()) ->language('sql') ->as('SELECT 42') ->toSql() ); - $result = $this->execute( + $this->pgsqlContext()->client()->execute( alter()->function(self::FUNCTION_NAME) ->arguments() ->immutable() ->toSql() ); - self::assertNotFalse($result); self::assertTrue($this->functionExists(self::FUNCTION_NAME)); } public function test_create_function_returns_void() : void { - $result = $this->execute( + $this->pgsqlContext()->client()->execute( create()->function(self::FUNCTION_NAME) ->arguments() ->returnsVoid() @@ -86,140 +92,143 @@ public function test_create_function_returns_void() : void ->toSql() ); - self::assertNotFalse($result); self::assertTrue($this->functionExists(self::FUNCTION_NAME)); } public function test_create_function_with_arguments() : void { - $result = $this->execute( + $this->pgsqlContext()->client()->execute( create()->function(self::FUNCTION_NAME) ->arguments( - func_arg(data_type_integer())->named('a'), - func_arg(data_type_integer())->named('b') + func_arg(column_type_integer())->named('a'), + func_arg(column_type_integer())->named('b') ) - ->returns(data_type_integer()) + ->returns(column_type_integer()) ->language('sql') ->as('SELECT a + b') ->toSql() ); - self::assertNotFalse($result); self::assertTrue($this->functionExists(self::FUNCTION_NAME)); - $row = $this->fetchOne($this->execute('SELECT ' . self::FUNCTION_NAME . '(10, 5) AS result')); - self::assertSame('15', $row['result']); + $row = $this->pgsqlContext()->client()->fetchOne( + select(func(self::FUNCTION_NAME, [literal(10), literal(5)])->as('result'))->toSql() + ); + self::assertSame(15, $row['result']); } public function test_create_function_with_default_argument() : void { - $result = $this->execute( + $this->pgsqlContext()->client()->execute( create()->function(self::FUNCTION_NAME) ->arguments( - func_arg(data_type_integer())->named('a'), - func_arg(data_type_integer())->named('b')->default('10') + func_arg(column_type_integer())->named('a'), + func_arg(column_type_integer())->named('b')->default('10') ) - ->returns(data_type_integer()) + ->returns(column_type_integer()) ->language('sql') ->as('SELECT a + b') ->toSql() ); - self::assertNotFalse($result); - - $row = $this->fetchOne($this->execute('SELECT ' . self::FUNCTION_NAME . '(5) AS result')); - self::assertSame('15', $row['result']); + $row = $this->pgsqlContext()->client()->fetchOne( + select(func(self::FUNCTION_NAME, [literal(5)])->as('result'))->toSql() + ); + self::assertSame(15, $row['result']); - $row = $this->fetchOne($this->execute('SELECT ' . self::FUNCTION_NAME . '(5, 3) AS result')); - self::assertSame('8', $row['result']); + $row = $this->pgsqlContext()->client()->fetchOne( + select(func(self::FUNCTION_NAME, [literal(5), literal(3)])->as('result'))->toSql() + ); + self::assertSame(8, $row['result']); } public function test_create_function_with_parallel_safety() : void { - $result = $this->execute( + $this->pgsqlContext()->client()->execute( create()->function(self::FUNCTION_NAME) ->arguments() - ->returns(data_type_integer()) + ->returns(column_type_integer()) ->language('sql') ->parallel(ParallelSafety::SAFE) ->as('SELECT 42') ->toSql() ); - self::assertNotFalse($result); self::assertTrue($this->functionExists(self::FUNCTION_NAME)); } public function test_create_function_with_volatility() : void { - $result = $this->execute( + $this->pgsqlContext()->client()->execute( create()->function(self::FUNCTION_NAME) ->arguments() - ->returns(data_type_integer()) + ->returns(column_type_integer()) ->language('sql') ->immutable() ->as('SELECT 42') ->toSql() ); - self::assertNotFalse($result); self::assertTrue($this->functionExists(self::FUNCTION_NAME)); } public function test_create_or_replace_function() : void { - $this->execute( + $this->pgsqlContext()->client()->execute( create()->function(self::FUNCTION_NAME) ->arguments() - ->returns(data_type_integer()) + ->returns(column_type_integer()) ->language('sql') ->as('SELECT 1') ->toSql() ); - $row = $this->fetchOne($this->execute('SELECT ' . self::FUNCTION_NAME . '() AS result')); - self::assertSame('1', $row['result']); + $row = $this->pgsqlContext()->client()->fetchOne( + select(func(self::FUNCTION_NAME)->as('result'))->toSql() + ); + self::assertSame(1, $row['result']); - $result = $this->execute( + $this->pgsqlContext()->client()->execute( create()->function(self::FUNCTION_NAME) ->orReplace() ->arguments() - ->returns(data_type_integer()) + ->returns(column_type_integer()) ->language('sql') ->as('SELECT 2') ->toSql() ); - self::assertNotFalse($result); - - $row = $this->fetchOne($this->execute('SELECT ' . self::FUNCTION_NAME . '() AS result')); - self::assertSame('2', $row['result']); + $row = $this->pgsqlContext()->client()->fetchOne( + select(func(self::FUNCTION_NAME)->as('result'))->toSql() + ); + self::assertSame(2, $row['result']); } public function test_create_simple_function() : void { - $result = $this->execute( + $this->pgsqlContext()->client()->execute( create()->function(self::FUNCTION_NAME) ->arguments() - ->returns(data_type_integer()) + ->returns(column_type_integer()) ->language('sql') ->as('SELECT 42') ->toSql() ); - self::assertNotFalse($result); self::assertTrue($this->functionExists(self::FUNCTION_NAME)); - $row = $this->fetchOne($this->execute('SELECT ' . self::FUNCTION_NAME . '() AS result')); - self::assertSame('42', $row['result']); + $row = $this->pgsqlContext()->client()->fetchOne( + select(func(self::FUNCTION_NAME)->as('result'))->toSql() + ); + self::assertSame(42, $row['result']); } public function test_drop_function() : void { - $this->execute( + $this->pgsqlContext()->client()->execute( create()->function(self::FUNCTION_NAME) ->arguments() - ->returns(data_type_integer()) + ->returns(column_type_integer()) ->language('sql') ->as('SELECT 42') ->toSql() @@ -227,55 +236,51 @@ public function test_drop_function() : void self::assertTrue($this->functionExists(self::FUNCTION_NAME)); - $result = $this->execute( + $this->pgsqlContext()->client()->execute( drop()->function(self::FUNCTION_NAME)->toSql() ); - self::assertNotFalse($result); self::assertFalse($this->functionExists(self::FUNCTION_NAME)); } public function test_drop_function_if_exists() : void { - $result = $this->execute( + $this->expectNotToPerformAssertions(); + + $this->pgsqlContext()->client()->execute( drop()->function(self::FUNCTION_NAME)->ifExists()->toSql() ); - - self::assertNotFalse($result); } public function test_drop_function_with_arguments() : void { - $this->execute( + $this->pgsqlContext()->client()->execute( create()->function(self::FUNCTION_NAME) - ->arguments(func_arg(data_type_integer())->named('a')) - ->returns(data_type_integer()) + ->arguments(func_arg(column_type_integer())->named('a')) + ->returns(column_type_integer()) ->language('sql') ->as('SELECT a * 2') ->toSql() ); - $result = $this->execute( + $this->pgsqlContext()->client()->execute( drop()->function(self::FUNCTION_NAME) - ->arguments(func_arg(data_type_integer())) + ->arguments(func_arg(column_type_integer())) ->toSql() ); - self::assertNotFalse($result); self::assertFalse($this->functionExists(self::FUNCTION_NAME)); } - protected function dropFunctionIfExists(string $name) : void - { - $this->execute("DROP FUNCTION IF EXISTS {$name} CASCADE"); - } - protected function functionExists(string $name) : bool { - $row = $this->fetchOne( - $this->execute("SELECT EXISTS(SELECT 1 FROM pg_proc WHERE proname = '{$name}') AS func_exists") + $row = $this->pgsqlContext()->client()->fetchOne( + select(agg_count()->as('cnt')) + ->from(table('pg_proc')) + ->where(eq(col('proname'), literal($name))) + ->toSql() ); - return $row['func_exists'] === 't'; + return $row['cnt'] > 0; } } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/IndexDatabaseTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/IndexDatabaseTest.php index cb55a13092..446c35f44e 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/IndexDatabaseTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/IndexDatabaseTest.php @@ -8,10 +8,10 @@ agg_count, col, column, + column_type_integer, + column_type_serial, + column_type_varchar, create, - data_type_integer, - data_type_serial, - data_type_varchar, drop, eq, index_col, @@ -23,8 +23,10 @@ star, table }; +use Flow\PostgreSql\Client\Exception\QueryException; +use Flow\PostgreSql\Tests\Integration\PostgreSqlTestCase; -final class IndexDatabaseTest extends DatabaseTestCase +final class IndexDatabaseTest extends PostgreSqlTestCase { private const INDEX_COMPOSITE = 'flow_postgres_idx_composite'; @@ -39,14 +41,14 @@ protected function setUp() : void parent::setUp(); $query = create()->table(self::TABLE_INDEXED) - ->column(column('id', data_type_serial())) - ->column(column('name', data_type_varchar(100))) - ->column(column('email', data_type_varchar(255))) - ->column(column('age', data_type_integer())); + ->column(column('id', column_type_serial())) + ->column(column('name', column_type_varchar(100))) + ->column(column('email', column_type_varchar(255))) + ->column(column('age', column_type_integer())); - $this->execute($query->toSql()); + $this->pgsqlContext()->client()->execute($query->toSql()); - $this->execute( + $this->pgsqlContext()->client()->execute( insert() ->into(self::TABLE_INDEXED) ->columns('name', 'email', 'age') @@ -57,10 +59,10 @@ protected function setUp() : void protected function tearDown() : void { - $this->dropIndexIfExists(self::INDEX_NAME); - $this->dropIndexIfExists(self::INDEX_EMAIL); - $this->dropIndexIfExists(self::INDEX_COMPOSITE); - $this->dropTableIfExists(self::TABLE_INDEXED); + $this->pgsqlContext()->dropIndexIfExists(self::INDEX_NAME); + $this->pgsqlContext()->dropIndexIfExists(self::INDEX_EMAIL); + $this->pgsqlContext()->dropIndexIfExists(self::INDEX_COMPOSITE); + $this->pgsqlContext()->dropTableIfExists(self::TABLE_INDEXED); parent::tearDown(); } @@ -71,9 +73,15 @@ public function test_create_composite_index() : void ->on(self::TABLE_INDEXED) ->columns(index_col('name'), index_col('email')); - $result = $this->execute($query->toSql()); + $this->pgsqlContext()->client()->execute($query->toSql()); - self::assertNotFalse($result); + $row = $this->pgsqlContext()->client()->fetchOne( + select(agg_count(star())->as('cnt')) + ->from(table('pg_indexes')) + ->where(eq(col('indexname'), literal(self::INDEX_COMPOSITE))) + ->toSql() + ); + self::assertSame(1, (int) $row['cnt']); } public function test_create_index() : void @@ -82,11 +90,9 @@ public function test_create_index() : void ->on(self::TABLE_INDEXED) ->columns(index_col('name')); - $result = $this->execute($query->toSql()); + $this->pgsqlContext()->client()->execute($query->toSql()); - self::assertNotFalse($result); - - $check = $this->execute( + $row = $this->pgsqlContext()->client()->fetchOne( select(agg_count(star())->as('cnt')) ->from(table('pg_indexes')) ->where( @@ -94,7 +100,6 @@ public function test_create_index() : void ) ->toSql() ); - $row = $this->fetchOne($check); self::assertGreaterThanOrEqual(1, (int) $row['cnt']); } @@ -105,10 +110,16 @@ public function test_create_index_if_not_exists() : void ->on(self::TABLE_INDEXED) ->columns(index_col('name')); - $this->execute($query->toSql()); - $result = $this->execute($query->toSql()); + $this->pgsqlContext()->client()->execute($query->toSql()); + $this->pgsqlContext()->client()->execute($query->toSql()); - self::assertNotFalse($result); + $row = $this->pgsqlContext()->client()->fetchOne( + select(agg_count(star())->as('cnt')) + ->from(table('pg_indexes')) + ->where(eq(col('indexname'), literal(self::INDEX_NAME))) + ->toSql() + ); + self::assertSame(1, (int) $row['cnt']); } public function test_create_index_with_btree_method() : void @@ -118,9 +129,15 @@ public function test_create_index_with_btree_method() : void ->using(index_method_btree()) ->columns(index_col('name')); - $result = $this->execute($query->toSql()); + $this->pgsqlContext()->client()->execute($query->toSql()); - self::assertNotFalse($result); + $row = $this->pgsqlContext()->client()->fetchOne( + select(agg_count(star())->as('cnt')) + ->from(table('pg_indexes')) + ->where(eq(col('indexname'), literal(self::INDEX_NAME))) + ->toSql() + ); + self::assertSame(1, (int) $row['cnt']); } public function test_create_index_with_hash_method() : void @@ -130,9 +147,15 @@ public function test_create_index_with_hash_method() : void ->using(index_method_hash()) ->columns(index_col('name')); - $result = $this->execute($query->toSql()); + $this->pgsqlContext()->client()->execute($query->toSql()); - self::assertNotFalse($result); + $row = $this->pgsqlContext()->client()->fetchOne( + select(agg_count(star())->as('cnt')) + ->from(table('pg_indexes')) + ->where(eq(col('indexname'), literal(self::INDEX_NAME))) + ->toSql() + ); + self::assertSame(1, (int) $row['cnt']); } public function test_create_unique_index() : void @@ -142,18 +165,16 @@ public function test_create_unique_index() : void ->on(self::TABLE_INDEXED) ->columns(index_col('email')); - $result = $this->execute($query->toSql()); - - self::assertNotFalse($result); + $this->pgsqlContext()->client()->execute($query->toSql()); - $duplicateResult = @$this->execute( + $this->expectException(QueryException::class); + $this->pgsqlContext()->client()->execute( insert() ->into(self::TABLE_INDEXED) ->columns('name', 'email', 'age') ->values(literal('Test2'), literal('test@example.com'), literal(25)) ->toSql() ); - self::assertFalse($duplicateResult); } public function test_drop_index() : void @@ -161,21 +182,31 @@ public function test_drop_index() : void $createQuery = create()->index(self::INDEX_NAME) ->on(self::TABLE_INDEXED) ->columns(index_col('name')); - $this->execute($createQuery->toSql()); + $this->pgsqlContext()->client()->execute($createQuery->toSql()); $dropQuery = drop()->index(self::INDEX_NAME); + $this->pgsqlContext()->client()->execute($dropQuery->toSql()); - $result = $this->execute($dropQuery->toSql()); - - self::assertNotFalse($result); + $row = $this->pgsqlContext()->client()->fetchOne( + select(agg_count(star())->as('cnt')) + ->from(table('pg_indexes')) + ->where(eq(col('indexname'), literal(self::INDEX_NAME))) + ->toSql() + ); + self::assertSame(0, (int) $row['cnt']); } public function test_drop_index_if_exists() : void { $dropQuery = drop()->index(self::INDEX_NAME)->ifExists(); + $this->pgsqlContext()->client()->execute($dropQuery->toSql()); - $result = $this->execute($dropQuery->toSql()); - - self::assertNotFalse($result); + $row = $this->pgsqlContext()->client()->fetchOne( + select(agg_count(star())->as('cnt')) + ->from(table('pg_indexes')) + ->where(eq(col('indexname'), literal(self::INDEX_NAME))) + ->toSql() + ); + self::assertSame(0, (int) $row['cnt']); } } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/InsertDatabaseTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/InsertDatabaseTest.php index 8ed439f80c..f3b30a8155 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/InsertDatabaseTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/InsertDatabaseTest.php @@ -7,12 +7,12 @@ use function Flow\PostgreSql\DSL\{ col, column, + column_type_decimal, + column_type_integer, + column_type_serial, + column_type_varchar, conflict_columns, create, - data_type_decimal, - data_type_integer, - data_type_serial, - data_type_varchar, eq, insert, literal, @@ -23,8 +23,9 @@ table, unique_constraint }; +use Flow\PostgreSql\Tests\Integration\PostgreSqlTestCase; -final class InsertDatabaseTest extends DatabaseTestCase +final class InsertDatabaseTest extends PostgreSqlTestCase { private const SCHEMA_NAME = 'flow_postgres_test_insert_schema'; @@ -36,13 +37,13 @@ protected function setUp() : void { parent::setUp(); - $this->execute( + $this->pgsqlContext()->client()->execute( create()->table(self::TABLE_PRODUCTS) - ->column(column('id', data_type_serial())) - ->column(column('sku', data_type_varchar(50))->notNull()) - ->column(column('name', data_type_varchar(100))->notNull()) - ->column(column('price', data_type_decimal(10, 2))->default(0)) - ->column(column('stock', data_type_integer())->default(0)) + ->column(column('id', column_type_serial())) + ->column(column('sku', column_type_varchar(50))->notNull()) + ->column(column('name', column_type_varchar(100))->notNull()) + ->column(column('price', column_type_decimal(10, 2))->default(0)) + ->column(column('stock', column_type_integer())->default(0)) ->constraint(primary_key('id')) ->constraint(unique_constraint('sku')) ->toSql() @@ -51,8 +52,8 @@ protected function setUp() : void protected function tearDown() : void { - $this->dropTableIfExists(self::TABLE_PRODUCTS); - $this->execute('DROP SCHEMA IF EXISTS ' . self::SCHEMA_NAME . ' CASCADE'); + $this->pgsqlContext()->dropTableIfExists(self::TABLE_PRODUCTS); + $this->pgsqlContext()->dropSchemaIfExists(self::SCHEMA_NAME); parent::tearDown(); } @@ -64,18 +65,14 @@ public function test_basic_insert() : void ->columns('sku', 'name', 'price') ->values(literal('SKU001'), literal('Product A'), literal(100)); - $result = $this->execute($query->toSql()); + self::assertSame(1, $this->pgsqlContext()->client()->execute($query->toSql())); - self::assertNotFalse($result); - self::assertSame(1, $this->affectedRows($result)); - - $check = $this->execute( + $row = $this->pgsqlContext()->client()->fetchOne( select(col('name')) ->from(table(self::TABLE_PRODUCTS)) ->where(eq(col('sku'), literal('SKU001'))) ->toSql() ); - $row = $this->fetchOne($check); self::assertSame('Product A', $row['name']); } @@ -87,15 +84,12 @@ public function test_insert_multiple_rows() : void ->values(literal('SKU002'), literal('Product B'), literal(200)) ->values(literal('SKU003'), literal('Product C'), literal(300)); - $result = $this->execute($query->toSql()); - - self::assertNotFalse($result); - self::assertSame(2, $this->affectedRows($result)); + self::assertSame(2, $this->pgsqlContext()->client()->execute($query->toSql())); } public function test_insert_on_conflict_do_nothing() : void { - $this->execute( + $this->pgsqlContext()->client()->execute( insert() ->into(self::TABLE_PRODUCTS) ->columns('sku', 'name') @@ -109,23 +103,20 @@ public function test_insert_on_conflict_do_nothing() : void ->values(literal('SKU006'), literal('Duplicate')) ->onConflict(on_conflict_nothing(conflict_columns(['sku']))); - $result = $this->execute($query->toSql()); - - self::assertNotFalse($result); + $this->pgsqlContext()->client()->execute($query->toSql()); - $check = $this->execute( + $row = $this->pgsqlContext()->client()->fetchOne( select(col('name')) ->from(table(self::TABLE_PRODUCTS)) ->where(eq(col('sku'), literal('SKU006'))) ->toSql() ); - $row = $this->fetchOne($check); self::assertSame('Original', $row['name']); } public function test_insert_on_conflict_do_update() : void { - $this->execute( + $this->pgsqlContext()->client()->execute( insert() ->into(self::TABLE_PRODUCTS) ->columns('sku', 'name', 'price') @@ -144,17 +135,14 @@ public function test_insert_on_conflict_do_update() : void ) ); - $result = $this->execute($query->toSql()); + $this->pgsqlContext()->client()->execute($query->toSql()); - self::assertNotFalse($result); - - $check = $this->execute( + $row = $this->pgsqlContext()->client()->fetchOne( select(col('name'), col('price')) ->from(table(self::TABLE_PRODUCTS)) ->where(eq(col('sku'), literal('SKU007'))) ->toSql() ); - $row = $this->fetchOne($check); self::assertSame('Updated', $row['name']); self::assertSame('999.00', $row['price']); } @@ -167,10 +155,8 @@ public function test_insert_with_returning() : void ->values(literal('SKU004'), literal('Product D'), literal(400)) ->returning(col('id'), col('sku')); - $result = $this->execute($query->toSql()); + $row = $this->pgsqlContext()->client()->fetchOne($query->toSql()); - self::assertNotFalse($result); - $row = $this->fetchOne($result); self::assertArrayHasKey('id', $row); self::assertArrayHasKey('sku', $row); self::assertSame('SKU004', $row['sku']); @@ -184,10 +170,8 @@ public function test_insert_with_returning_all() : void ->values(literal('SKU005'), literal('Product E'), literal(500)) ->returningAll(); - $result = $this->execute($query->toSql()); + $row = $this->pgsqlContext()->client()->fetchOne($query->toSql()); - self::assertNotFalse($result); - $row = $this->fetchOne($result); self::assertArrayHasKey('id', $row); self::assertArrayHasKey('sku', $row); self::assertArrayHasKey('name', $row); @@ -197,13 +181,15 @@ public function test_insert_with_returning_all() : void public function test_insert_with_schema_qualified_table() : void { - $this->execute('CREATE SCHEMA IF NOT EXISTS ' . self::SCHEMA_NAME); + $this->pgsqlContext()->client()->execute( + create()->schema(self::SCHEMA_NAME)->ifNotExists()->toSql() + ); - $this->execute( + $this->pgsqlContext()->client()->execute( create()->table(self::SCHEMA_TABLE, self::SCHEMA_NAME) - ->column(column('id', data_type_serial())) - ->column(column('sku', data_type_varchar(50))->notNull()) - ->column(column('name', data_type_varchar(100))->notNull()) + ->column(column('id', column_type_serial())) + ->column(column('sku', column_type_varchar(50))->notNull()) + ->column(column('name', column_type_varchar(100))->notNull()) ->constraint(primary_key('id')) ->toSql() ); @@ -213,18 +199,14 @@ public function test_insert_with_schema_qualified_table() : void ->columns('sku', 'name') ->values(literal('SCHEMA-SKU'), literal('Schema Product')); - $result = $this->execute($query->toSql()); - - self::assertNotFalse($result); - self::assertSame(1, $this->affectedRows($result)); + self::assertSame(1, $this->pgsqlContext()->client()->execute($query->toSql())); - $check = $this->execute( + $row = $this->pgsqlContext()->client()->fetchOne( select(col('name')) ->from(table(self::SCHEMA_TABLE, self::SCHEMA_NAME)) ->where(eq(col('sku'), literal('SCHEMA-SKU'))) ->toSql() ); - $row = $this->fetchOne($check); self::assertSame('Schema Product', $row['name']); } } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/MergeDatabaseTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/MergeDatabaseTest.php index f86e05ecd5..c1bb7dc808 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/MergeDatabaseTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/MergeDatabaseTest.php @@ -7,10 +7,10 @@ use function Flow\PostgreSql\DSL\{ col, column, + column_type_integer, + column_type_serial, + column_type_varchar, create, - data_type_integer, - data_type_serial, - data_type_varchar, eq, gt, insert, @@ -22,8 +22,9 @@ star, table }; +use Flow\PostgreSql\Tests\Integration\PostgreSqlTestCase; -final class MergeDatabaseTest extends DatabaseTestCase +final class MergeDatabaseTest extends PostgreSqlTestCase { private const SCHEMA_NAME = 'flow_postgres_test_merge_schema'; @@ -39,25 +40,25 @@ protected function setUp() : void { parent::setUp(); - $this->execute( + $this->pgsqlContext()->client()->execute( create()->table(self::TABLE_TARGET) - ->column(column('id', data_type_serial())) - ->column(column('name', data_type_varchar(100))->notNull()) - ->column(column('value', data_type_integer())->default(0)) + ->column(column('id', column_type_serial())) + ->column(column('name', column_type_varchar(100))->notNull()) + ->column(column('value', column_type_integer())->default(0)) ->constraint(primary_key('id')) ->toSql() ); - $this->execute( + $this->pgsqlContext()->client()->execute( create()->table(self::TABLE_SOURCE) - ->column(column('id', data_type_integer())->notNull()) - ->column(column('name', data_type_varchar(100))->notNull()) - ->column(column('value', data_type_integer())->default(0)) + ->column(column('id', column_type_integer())->notNull()) + ->column(column('name', column_type_varchar(100))->notNull()) + ->column(column('value', column_type_integer())->default(0)) ->constraint(primary_key('id')) ->toSql() ); - $this->execute( + $this->pgsqlContext()->client()->execute( insert() ->into(self::TABLE_TARGET) ->columns('name', 'value') @@ -66,7 +67,7 @@ protected function setUp() : void ->toSql() ); - $this->execute( + $this->pgsqlContext()->client()->execute( insert() ->into(self::TABLE_SOURCE) ->columns('id', 'name', 'value') @@ -79,9 +80,9 @@ protected function setUp() : void protected function tearDown() : void { - $this->dropTableIfExists(self::TABLE_SOURCE); - $this->dropTableIfExists(self::TABLE_TARGET); - $this->execute('DROP SCHEMA IF EXISTS ' . self::SCHEMA_NAME . ' CASCADE'); + $this->pgsqlContext()->dropTableIfExists(self::TABLE_SOURCE); + $this->pgsqlContext()->dropTableIfExists(self::TABLE_TARGET); + $this->pgsqlContext()->dropSchemaIfExists(self::SCHEMA_NAME); parent::tearDown(); } @@ -94,15 +95,10 @@ public function test_merge_delete_matched() : void ->whenMatched() ->thenDelete(); - $result = $this->execute($query->toSql()); + self::assertSame(2, $this->pgsqlContext()->client()->execute($query->toSql())); - self::assertNotFalse($result); - self::assertSame(2, $this->affectedRows($result)); - - $rows = $this->fetchAll( - $this->execute( - select(star())->from(table(self::TABLE_TARGET))->toSql() - ) + $rows = $this->pgsqlContext()->client()->fetchAll( + select(star())->from(table(self::TABLE_TARGET))->toSql() ); self::assertCount(0, $rows); @@ -116,14 +112,10 @@ public function test_merge_do_nothing() : void ->whenMatched() ->thenDoNothing(); - $result = $this->execute($query->toSql()); - - self::assertNotFalse($result); + $this->pgsqlContext()->client()->execute($query->toSql()); - $rows = $this->fetchAll( - $this->execute( - select(star())->from(table(self::TABLE_TARGET))->orderBy(order_by(col('id')))->toSql() - ) + $rows = $this->pgsqlContext()->client()->fetchAll( + select(star())->from(table(self::TABLE_TARGET))->orderBy(order_by(col('id')))->toSql() ); self::assertCount(2, $rows); @@ -142,20 +134,15 @@ public function test_merge_insert_not_matched() : void 'value' => col('s.value'), ]); - $result = $this->execute($query->toSql()); - - self::assertNotFalse($result); - self::assertSame(1, $this->affectedRows($result)); + self::assertSame(1, $this->pgsqlContext()->client()->execute($query->toSql())); - $rows = $this->fetchAll( - $this->execute( - select(star())->from(table(self::TABLE_TARGET))->orderBy(order_by(col('id')))->toSql() - ) + $rows = $this->pgsqlContext()->client()->fetchAll( + select(star())->from(table(self::TABLE_TARGET))->orderBy(order_by(col('id')))->toSql() ); self::assertCount(3, $rows); self::assertSame('Charlie', $rows[2]['name']); - self::assertSame('300', $rows[2]['value']); + self::assertSame(300, $rows[2]['value']); } public function test_merge_update_and_insert() : void @@ -174,15 +161,10 @@ public function test_merge_update_and_insert() : void 'value' => col('s.value'), ]); - $result = $this->execute($query->toSql()); + self::assertSame(3, $this->pgsqlContext()->client()->execute($query->toSql())); - self::assertNotFalse($result); - self::assertSame(3, $this->affectedRows($result)); - - $rows = $this->fetchAll( - $this->execute( - select(star())->from(table(self::TABLE_TARGET))->orderBy(order_by(col('id')))->toSql() - ) + $rows = $this->pgsqlContext()->client()->fetchAll( + select(star())->from(table(self::TABLE_TARGET))->orderBy(order_by(col('id')))->toSql() ); self::assertCount(3, $rows); @@ -202,22 +184,17 @@ public function test_merge_update_matched() : void 'value' => col('s.value'), ]); - $result = $this->execute($query->toSql()); - - self::assertNotFalse($result); - self::assertSame(2, $this->affectedRows($result)); + self::assertSame(2, $this->pgsqlContext()->client()->execute($query->toSql())); - $rows = $this->fetchAll( - $this->execute( - select(star())->from(table(self::TABLE_TARGET))->orderBy(order_by(col('id')))->toSql() - ) + $rows = $this->pgsqlContext()->client()->fetchAll( + select(star())->from(table(self::TABLE_TARGET))->orderBy(order_by(col('id')))->toSql() ); self::assertCount(2, $rows); self::assertSame('Alice Updated', $rows[0]['name']); - self::assertSame('150', $rows[0]['value']); + self::assertSame(150, $rows[0]['value']); self::assertSame('Bob Updated', $rows[1]['name']); - self::assertSame('250', $rows[1]['value']); + self::assertSame(250, $rows[1]['value']); } public function test_merge_using_subquery() : void @@ -239,18 +216,14 @@ public function test_merge_using_subquery() : void 'value' => col('s.value'), ]); - $result = $this->execute($query->toSql()); + $this->pgsqlContext()->client()->execute($query->toSql()); - self::assertNotFalse($result); - - $rows = $this->fetchAll( - $this->execute( - select(star())->from(table(self::TABLE_TARGET))->orderBy(order_by(col('id')))->toSql() - ) + $rows = $this->pgsqlContext()->client()->fetchAll( + select(star())->from(table(self::TABLE_TARGET))->orderBy(order_by(col('id')))->toSql() ); self::assertCount(3, $rows); - self::assertSame('250', $rows[1]['value']); + self::assertSame(250, $rows[1]['value']); self::assertSame('Charlie', $rows[2]['name']); } @@ -264,45 +237,40 @@ public function test_merge_with_condition() : void 'value' => col('s.value'), ]); - $result = $this->execute($query->toSql()); - - self::assertNotFalse($result); - self::assertSame(1, $this->affectedRows($result)); + self::assertSame(1, $this->pgsqlContext()->client()->execute($query->toSql())); - $rows = $this->fetchAll( - $this->execute( - select(star())->from(table(self::TABLE_TARGET))->orderBy(order_by(col('id')))->toSql() - ) + $rows = $this->pgsqlContext()->client()->fetchAll( + select(star())->from(table(self::TABLE_TARGET))->orderBy(order_by(col('id')))->toSql() ); self::assertCount(2, $rows); - self::assertSame('100', $rows[0]['value']); - self::assertSame('250', $rows[1]['value']); + self::assertSame(100, $rows[0]['value']); + self::assertSame(250, $rows[1]['value']); } public function test_merge_with_schema_qualified_tables() : void { - $this->execute('CREATE SCHEMA IF NOT EXISTS ' . self::SCHEMA_NAME); + $this->pgsqlContext()->client()->execute('CREATE SCHEMA IF NOT EXISTS ' . self::SCHEMA_NAME); - $this->execute( + $this->pgsqlContext()->client()->execute( create()->table(self::SCHEMA_TARGET, self::SCHEMA_NAME) - ->column(column('id', data_type_serial())) - ->column(column('name', data_type_varchar(100))->notNull()) - ->column(column('value', data_type_integer())->default(0)) + ->column(column('id', column_type_serial())) + ->column(column('name', column_type_varchar(100))->notNull()) + ->column(column('value', column_type_integer())->default(0)) ->constraint(primary_key('id')) ->toSql() ); - $this->execute( + $this->pgsqlContext()->client()->execute( create()->table(self::SCHEMA_SOURCE, self::SCHEMA_NAME) - ->column(column('id', data_type_integer())->notNull()) - ->column(column('name', data_type_varchar(100))->notNull()) - ->column(column('value', data_type_integer())->default(0)) + ->column(column('id', column_type_integer())->notNull()) + ->column(column('name', column_type_varchar(100))->notNull()) + ->column(column('value', column_type_integer())->default(0)) ->constraint(primary_key('id')) ->toSql() ); - $this->execute( + $this->pgsqlContext()->client()->execute( insert() ->into(self::SCHEMA_NAME . '.' . self::SCHEMA_TARGET) ->columns('name', 'value') @@ -310,7 +278,7 @@ public function test_merge_with_schema_qualified_tables() : void ->toSql() ); - $this->execute( + $this->pgsqlContext()->client()->execute( insert() ->into(self::SCHEMA_NAME . '.' . self::SCHEMA_SOURCE) ->columns('id', 'name', 'value') @@ -333,24 +301,19 @@ public function test_merge_with_schema_qualified_tables() : void 'value' => col('s.value'), ]); - $result = $this->execute($query->toSql()); + self::assertSame(2, $this->pgsqlContext()->client()->execute($query->toSql())); - self::assertNotFalse($result); - self::assertSame(2, $this->affectedRows($result)); - - $rows = $this->fetchAll( - $this->execute( - select(star()) - ->from(table(self::SCHEMA_TARGET, self::SCHEMA_NAME)) - ->orderBy(order_by(col('id'))) - ->toSql() - ) + $rows = $this->pgsqlContext()->client()->fetchAll( + select(star()) + ->from(table(self::SCHEMA_TARGET, self::SCHEMA_NAME)) + ->orderBy(order_by(col('id'))) + ->toSql() ); self::assertCount(2, $rows); self::assertSame('Updated Row', $rows[0]['name']); - self::assertSame('200', $rows[0]['value']); + self::assertSame(200, $rows[0]['value']); self::assertSame('New Row', $rows[1]['name']); - self::assertSame('300', $rows[1]['value']); + self::assertSame(300, $rows[1]['value']); } } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/SchemaDatabaseTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/SchemaDatabaseTest.php index dcf7f921f6..1325da68e1 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/SchemaDatabaseTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/SchemaDatabaseTest.php @@ -7,9 +7,9 @@ use function Flow\PostgreSql\DSL\{ alter, column, + column_type_serial, + column_type_varchar, create, - data_type_serial, - data_type_varchar, drop, insert, literal, @@ -18,8 +18,9 @@ star, table }; +use Flow\PostgreSql\Tests\Integration\PostgreSqlTestCase; -final class SchemaDatabaseTest extends DatabaseTestCase +final class SchemaDatabaseTest extends PostgreSqlTestCase { private const SCHEMA_NAME = 'flow_postgres_test_schema'; @@ -31,109 +32,101 @@ protected function setUp() : void { parent::setUp(); - $this->dropSchemaIfExists(self::SCHEMA_NAME); - $this->dropSchemaIfExists(self::SCHEMA_NAME_RENAMED); + $this->pgsqlContext()->dropSchemaIfExists(self::SCHEMA_NAME); + $this->pgsqlContext()->dropSchemaIfExists(self::SCHEMA_NAME_RENAMED); } protected function tearDown() : void { - $this->dropSchemaIfExists(self::SCHEMA_NAME); - $this->dropSchemaIfExists(self::SCHEMA_NAME_RENAMED); + $this->pgsqlContext()->dropSchemaIfExists(self::SCHEMA_NAME); + $this->pgsqlContext()->dropSchemaIfExists(self::SCHEMA_NAME_RENAMED); parent::tearDown(); } public function test_alter_schema_owner() : void { - $this->execute( + $this->pgsqlContext()->client()->execute( create()->schema(self::SCHEMA_NAME)->toSql() ); - $currentUser = $this->fetchOne($this->execute('SELECT current_user AS username')); + $currentUser = $this->pgsqlContext()->client()->fetchOne('SELECT current_user AS username'); self::assertIsString($currentUser['username']); - $result = $this->execute( + $this->pgsqlContext()->client()->execute( alter()->schema(self::SCHEMA_NAME) ->ownerTo($currentUser['username']) ->toSql() ); - - self::assertNotFalse($result); } public function test_alter_schema_rename() : void { - $this->execute( + $this->pgsqlContext()->client()->execute( create()->schema(self::SCHEMA_NAME)->toSql() ); - $result = $this->execute( + $this->pgsqlContext()->client()->execute( alter()->schema(self::SCHEMA_NAME) ->renameTo(self::SCHEMA_NAME_RENAMED) ->toSql() ); - self::assertNotFalse($result); self::assertFalse($this->schemaExists(self::SCHEMA_NAME)); self::assertTrue($this->schemaExists(self::SCHEMA_NAME_RENAMED)); } public function test_create_schema() : void { - $result = $this->execute( + $this->pgsqlContext()->client()->execute( create()->schema(self::SCHEMA_NAME)->toSql() ); - self::assertNotFalse($result); self::assertTrue($this->schemaExists(self::SCHEMA_NAME)); } public function test_create_schema_if_not_exists() : void { - $this->execute( + $this->pgsqlContext()->client()->execute( create()->schema(self::SCHEMA_NAME)->toSql() ); - $result = $this->execute( + $this->pgsqlContext()->client()->execute( create()->schema(self::SCHEMA_NAME)->ifNotExists()->toSql() ); - self::assertNotFalse($result); self::assertTrue($this->schemaExists(self::SCHEMA_NAME)); } public function test_create_schema_with_authorization() : void { - $currentUser = $this->fetchOne($this->execute('SELECT current_user AS username')); + $currentUser = $this->pgsqlContext()->client()->fetchOne('SELECT current_user AS username'); self::assertIsString($currentUser['username']); - $result = $this->execute( + $this->pgsqlContext()->client()->execute( create()->schema(self::SCHEMA_NAME) ->authorization($currentUser['username']) ->toSql() ); - self::assertNotFalse($result); self::assertTrue($this->schemaExists(self::SCHEMA_NAME)); } public function test_create_table_in_schema() : void { - $this->execute( + $this->pgsqlContext()->client()->execute( create()->schema(self::SCHEMA_NAME)->toSql() ); - $result = $this->execute( + $this->pgsqlContext()->client()->execute( create()->table(self::TABLE_NAME, self::SCHEMA_NAME) - ->column(column('id', data_type_serial())) - ->column(column('name', data_type_varchar(100))->notNull()) + ->column(column('id', column_type_serial())) + ->column(column('name', column_type_varchar(100))->notNull()) ->constraint(primary_key('id')) ->toSql() ); - self::assertNotFalse($result); - - $this->execute( + $this->pgsqlContext()->client()->execute( insert() ->into(self::SCHEMA_NAME . '.' . self::TABLE_NAME) ->columns('name') @@ -141,10 +134,8 @@ public function test_create_table_in_schema() : void ->toSql() ); - $row = $this->fetchOne( - $this->execute( - select(star())->from(table(self::TABLE_NAME, self::SCHEMA_NAME))->toSql() - ) + $row = $this->pgsqlContext()->client()->fetchOne( + select(star())->from(table(self::TABLE_NAME, self::SCHEMA_NAME))->toSql() ); self::assertSame('Test', $row['name']); @@ -152,78 +143,70 @@ public function test_create_table_in_schema() : void public function test_drop_multiple_schemas() : void { - $this->execute(create()->schema(self::SCHEMA_NAME)->toSql()); - $this->execute(create()->schema(self::SCHEMA_NAME_RENAMED)->toSql()); + $this->pgsqlContext()->client()->execute(create()->schema(self::SCHEMA_NAME)->toSql()); + $this->pgsqlContext()->client()->execute(create()->schema(self::SCHEMA_NAME_RENAMED)->toSql()); self::assertTrue($this->schemaExists(self::SCHEMA_NAME)); self::assertTrue($this->schemaExists(self::SCHEMA_NAME_RENAMED)); - $result = $this->execute( + $this->pgsqlContext()->client()->execute( drop()->schema(self::SCHEMA_NAME, self::SCHEMA_NAME_RENAMED)->toSql() ); - self::assertNotFalse($result); self::assertFalse($this->schemaExists(self::SCHEMA_NAME)); self::assertFalse($this->schemaExists(self::SCHEMA_NAME_RENAMED)); } public function test_drop_schema() : void { - $this->execute( + $this->pgsqlContext()->client()->execute( create()->schema(self::SCHEMA_NAME)->toSql() ); self::assertTrue($this->schemaExists(self::SCHEMA_NAME)); - $result = $this->execute( + $this->pgsqlContext()->client()->execute( drop()->schema(self::SCHEMA_NAME)->toSql() ); - self::assertNotFalse($result); self::assertFalse($this->schemaExists(self::SCHEMA_NAME)); } public function test_drop_schema_cascade() : void { - $this->execute( + $this->pgsqlContext()->client()->execute( create()->schema(self::SCHEMA_NAME)->toSql() ); - $this->execute( + $this->pgsqlContext()->client()->execute( create()->table(self::TABLE_NAME, self::SCHEMA_NAME) - ->column(column('id', data_type_serial())) + ->column(column('id', column_type_serial())) ->constraint(primary_key('id')) ->toSql() ); - $result = $this->execute( + $this->pgsqlContext()->client()->execute( drop()->schema(self::SCHEMA_NAME)->cascade()->toSql() ); - self::assertNotFalse($result); self::assertFalse($this->schemaExists(self::SCHEMA_NAME)); } public function test_drop_schema_if_exists() : void { - $result = $this->execute( + $this->expectNotToPerformAssertions(); + + $this->pgsqlContext()->client()->execute( drop()->schema(self::SCHEMA_NAME)->ifExists()->toSql() ); - - self::assertNotFalse($result); - } - - protected function dropSchemaIfExists(string $name) : void - { - $this->execute("DROP SCHEMA IF EXISTS {$name} CASCADE"); } protected function schemaExists(string $name) : bool { - $row = $this->fetchOne( - $this->execute("SELECT EXISTS(SELECT 1 FROM pg_namespace WHERE nspname = '{$name}') AS schema_exists") + $row = $this->pgsqlContext()->client()->fetchOne( + "SELECT EXISTS(SELECT 1 FROM pg_namespace WHERE nspname = '{$name}') AS schema_exists" ); - return $row['schema_exists'] === 't'; + return $row['schema_exists'] === true; } } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/SelectDatabaseTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/SelectDatabaseTest.php index 127b838be1..497546ea1a 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/SelectDatabaseTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/SelectDatabaseTest.php @@ -6,15 +6,15 @@ use function Flow\PostgreSql\DSL\{ agg_sum, + and_, col, column, - cond_and, + column_type_decimal, + column_type_integer, + column_type_serial, + column_type_varchar, create, cte, - data_type_decimal, - data_type_integer, - data_type_serial, - data_type_varchar, desc, eq, gt, @@ -26,8 +26,9 @@ table, with }; +use Flow\PostgreSql\Tests\Integration\PostgreSqlTestCase; -final class SelectDatabaseTest extends DatabaseTestCase +final class SelectDatabaseTest extends PostgreSqlTestCase { private const SCHEMA_NAME = 'flow_postgres_test_select_schema'; @@ -41,27 +42,27 @@ protected function setUp() : void { parent::setUp(); - $this->execute( + $this->pgsqlContext()->client()->execute( create()->table(self::TABLE_USERS) - ->column(column('id', data_type_serial())) - ->column(column('name', data_type_varchar(100))->notNull()) - ->column(column('email', data_type_varchar(255))) - ->column(column('age', data_type_integer())->default(0)) + ->column(column('id', column_type_serial())) + ->column(column('name', column_type_varchar(100))->notNull()) + ->column(column('email', column_type_varchar(255))) + ->column(column('age', column_type_integer())->default(0)) ->constraint(primary_key('id')) ->toSql() ); - $this->execute( + $this->pgsqlContext()->client()->execute( create()->table(self::TABLE_ORDERS) - ->column(column('id', data_type_serial())) - ->column(column('user_id', data_type_integer())) - ->column(column('amount', data_type_decimal(10, 2))->notNull()) - ->column(column('status', data_type_varchar(50))->default('pending')) + ->column(column('id', column_type_serial())) + ->column(column('user_id', column_type_integer())) + ->column(column('amount', column_type_decimal(10, 2))->notNull()) + ->column(column('status', column_type_varchar(50))->default('pending')) ->constraint(primary_key('id')) ->toSql() ); - $this->execute( + $this->pgsqlContext()->client()->execute( insert() ->into(self::TABLE_USERS) ->columns('name', 'email', 'age') @@ -71,7 +72,7 @@ protected function setUp() : void ->toSql() ); - $this->execute( + $this->pgsqlContext()->client()->execute( insert() ->into(self::TABLE_ORDERS) ->columns('user_id', 'amount', 'status') @@ -85,9 +86,9 @@ protected function setUp() : void protected function tearDown() : void { - $this->dropTableIfExists(self::TABLE_ORDERS); - $this->dropTableIfExists(self::TABLE_USERS); - $this->execute('DROP SCHEMA IF EXISTS ' . self::SCHEMA_NAME . ' CASCADE'); + $this->pgsqlContext()->dropTableIfExists(self::TABLE_ORDERS); + $this->pgsqlContext()->dropTableIfExists(self::TABLE_USERS); + $this->pgsqlContext()->dropSchemaIfExists(self::SCHEMA_NAME); parent::tearDown(); } @@ -96,10 +97,8 @@ public function test_basic_select_all() : void { $query = select(star())->from(table(self::TABLE_USERS)); - $result = $this->execute($query->toSql()); + $rows = $this->pgsqlContext()->client()->fetchAll($query->toSql()); - self::assertNotFalse($result); - $rows = $this->fetchAll($result); self::assertCount(3, $rows); } @@ -109,10 +108,8 @@ public function test_select_distinct() : void ->selectDistinct(col('status')) ->from(table(self::TABLE_ORDERS)); - $result = $this->execute($query->toSql()); + $rows = $this->pgsqlContext()->client()->fetchAll($query->toSql()); - self::assertNotFalse($result); - $rows = $this->fetchAll($result); self::assertCount(2, $rows); } @@ -121,10 +118,8 @@ public function test_select_specific_columns() : void $query = select(col('name'), col('email')) ->from(table(self::TABLE_USERS)); - $result = $this->execute($query->toSql()); + $rows = $this->pgsqlContext()->client()->fetchAll($query->toSql()); - self::assertNotFalse($result); - $rows = $this->fetchAll($result); self::assertCount(3, $rows); self::assertArrayHasKey('name', $rows[0]); self::assertArrayHasKey('email', $rows[0]); @@ -143,10 +138,8 @@ public function test_select_with_cte() : void ->from(table('order_totals')) ->where(gt(col('total'), literal(200))); - $result = $this->execute($query->toSql()); + $rows = $this->pgsqlContext()->client()->fetchAll($query->toSql()); - self::assertNotFalse($result); - $rows = $this->fetchAll($result); self::assertGreaterThanOrEqual(1, \count($rows)); } @@ -156,10 +149,8 @@ public function test_select_with_group_by_and_aggregate() : void ->from(table(self::TABLE_ORDERS)) ->groupBy(col('user_id')); - $result = $this->execute($query->toSql()); + $rows = $this->pgsqlContext()->client()->fetchAll($query->toSql()); - self::assertNotFalse($result); - $rows = $this->fetchAll($result); self::assertCount(3, $rows); } @@ -172,10 +163,8 @@ public function test_select_with_join() : void eq(col('id', self::TABLE_USERS), col('user_id', self::TABLE_ORDERS)) ); - $result = $this->execute($query->toSql()); + $rows = $this->pgsqlContext()->client()->fetchAll($query->toSql()); - self::assertNotFalse($result); - $rows = $this->fetchAll($result); self::assertCount(4, $rows); } @@ -184,16 +173,14 @@ public function test_select_with_multiple_conditions() : void $query = select(star()) ->from(table(self::TABLE_USERS)) ->where( - cond_and( + and_( gt(col('age'), literal(20)), gt(col('age'), literal(25)) ) ); - $result = $this->execute($query->toSql()); + $rows = $this->pgsqlContext()->client()->fetchAll($query->toSql()); - self::assertNotFalse($result); - $rows = $this->fetchAll($result); self::assertCount(2, $rows); } @@ -204,10 +191,8 @@ public function test_select_with_order_by_and_limit() : void ->orderBy(desc(col('age'))) ->limit(2); - $result = $this->execute($query->toSql()); + $rows = $this->pgsqlContext()->client()->fetchAll($query->toSql()); - self::assertNotFalse($result); - $rows = $this->fetchAll($result); self::assertCount(2, $rows); self::assertSame('Bob Wilson', $rows[0]['name']); self::assertSame('John Doe', $rows[1]['name']); @@ -215,18 +200,20 @@ public function test_select_with_order_by_and_limit() : void public function test_select_with_schema_qualified_table() : void { - $this->execute('CREATE SCHEMA IF NOT EXISTS ' . self::SCHEMA_NAME); + $this->pgsqlContext()->client()->execute( + create()->schema(self::SCHEMA_NAME)->ifNotExists()->toSql() + ); - $this->execute( + $this->pgsqlContext()->client()->execute( create()->table(self::SCHEMA_TABLE, self::SCHEMA_NAME) - ->column(column('id', data_type_serial())) - ->column(column('name', data_type_varchar(100))->notNull()) - ->column(column('email', data_type_varchar(255))) + ->column(column('id', column_type_serial())) + ->column(column('name', column_type_varchar(100))->notNull()) + ->column(column('email', column_type_varchar(255))) ->constraint(primary_key('id')) ->toSql() ); - $this->execute( + $this->pgsqlContext()->client()->execute( insert() ->into(self::SCHEMA_NAME . '.' . self::SCHEMA_TABLE) ->columns('name', 'email') @@ -237,10 +224,8 @@ public function test_select_with_schema_qualified_table() : void $query = select(star()) ->from(table(self::SCHEMA_TABLE, self::SCHEMA_NAME)); - $result = $this->execute($query->toSql()); + $rows = $this->pgsqlContext()->client()->fetchAll($query->toSql()); - self::assertNotFalse($result); - $rows = $this->fetchAll($result); self::assertCount(1, $rows); self::assertSame('Schema User', $rows[0]['name']); self::assertSame('schema@example.com', $rows[0]['email']); @@ -252,10 +237,8 @@ public function test_select_with_where() : void ->from(table(self::TABLE_USERS)) ->where(eq(col('name'), literal('John Doe'))); - $result = $this->execute($query->toSql()); + $rows = $this->pgsqlContext()->client()->fetchAll($query->toSql()); - self::assertNotFalse($result); - $rows = $this->fetchAll($result); self::assertCount(1, $rows); self::assertSame('John Doe', $rows[0]['name']); } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/SequenceDatabaseTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/SequenceDatabaseTest.php index 8da77bc51d..1bd4deee82 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/SequenceDatabaseTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/SequenceDatabaseTest.php @@ -15,8 +15,9 @@ select, table }; +use Flow\PostgreSql\Tests\Integration\PostgreSqlTestCase; -final class SequenceDatabaseTest extends DatabaseTestCase +final class SequenceDatabaseTest extends PostgreSqlTestCase { private const SEQUENCE_COUNTER = 'flow_postgres_counter_seq'; @@ -24,8 +25,8 @@ final class SequenceDatabaseTest extends DatabaseTestCase protected function tearDown() : void { - $this->dropSequenceIfExists(self::SEQUENCE_TEST); - $this->dropSequenceIfExists(self::SEQUENCE_COUNTER); + $this->pgsqlContext()->dropSequenceIfExists(self::SEQUENCE_TEST); + $this->pgsqlContext()->dropSequenceIfExists(self::SEQUENCE_COUNTER); parent::tearDown(); } @@ -33,66 +34,57 @@ protected function tearDown() : void public function test_alter_sequence_increment() : void { $createQuery = create()->sequence(self::SEQUENCE_TEST)->startWith(1); - $this->execute($createQuery->toSql()); + $this->pgsqlContext()->client()->execute($createQuery->toSql()); $alterQuery = alter()->sequence(self::SEQUENCE_TEST) ->incrementBy(10); - $result = $this->execute($alterQuery->toSql()); + $this->pgsqlContext()->client()->execute($alterQuery->toSql()); - self::assertNotFalse($result); - - $this->execute( + $this->pgsqlContext()->client()->fetchOne( select(func('nextval', [literal(self::SEQUENCE_TEST)]))->toSql() ); - $secondVal = $this->execute( + $row = $this->pgsqlContext()->client()->fetchOne( select(func('nextval', [literal(self::SEQUENCE_TEST)])->as('val'))->toSql() ); - $row = $this->fetchOne($secondVal); - self::assertSame('11', $row['val']); + self::assertSame(11, $row['val']); } public function test_alter_sequence_restart() : void { $createQuery = create()->sequence(self::SEQUENCE_TEST)->startWith(1); - $this->execute($createQuery->toSql()); + $this->pgsqlContext()->client()->execute($createQuery->toSql()); - $this->execute( + $this->pgsqlContext()->client()->fetchOne( select(func('nextval', [literal(self::SEQUENCE_TEST)]))->toSql() ); - $this->execute( + $this->pgsqlContext()->client()->fetchOne( select(func('nextval', [literal(self::SEQUENCE_TEST)]))->toSql() ); $alterQuery = alter()->sequence(self::SEQUENCE_TEST) ->restartWith(1); - $result = $this->execute($alterQuery->toSql()); - - self::assertNotFalse($result); + $this->pgsqlContext()->client()->execute($alterQuery->toSql()); - $nextVal = $this->execute( + $row = $this->pgsqlContext()->client()->fetchOne( select(func('nextval', [literal(self::SEQUENCE_TEST)])->as('val'))->toSql() ); - $row = $this->fetchOne($nextVal); - self::assertSame('1', $row['val']); + self::assertSame(1, $row['val']); } public function test_create_sequence() : void { $query = create()->sequence(self::SEQUENCE_TEST); - $result = $this->execute($query->toSql()); - - self::assertNotFalse($result); + $this->pgsqlContext()->client()->execute($query->toSql()); - $check = $this->execute( + $sequences = $this->pgsqlContext()->client()->fetchAll( select(col('sequencename')) ->from(table('pg_sequences')) ->where(eq(col('sequencename'), literal(self::SEQUENCE_TEST))) ->toSql() ); - $sequences = $this->fetchAll($check); self::assertCount(1, $sequences); } @@ -102,18 +94,15 @@ public function test_create_sequence_with_increment() : void ->incrementBy(5) ->startWith(10); - $result = $this->execute($query->toSql()); + $this->pgsqlContext()->client()->execute($query->toSql()); - self::assertNotFalse($result); - - $this->execute( + $this->pgsqlContext()->client()->fetchOne( select(func('nextval', [literal(self::SEQUENCE_TEST)]))->toSql() ); - $secondVal = $this->execute( + $row = $this->pgsqlContext()->client()->fetchOne( select(func('nextval', [literal(self::SEQUENCE_TEST)])->as('val'))->toSql() ); - $row = $this->fetchOne($secondVal); - self::assertSame('15', $row['val']); + self::assertSame(15, $row['val']); } public function test_create_sequence_with_min_max() : void @@ -123,19 +112,16 @@ public function test_create_sequence_with_min_max() : void ->maxValue(1000) ->startWith(1); - $result = $this->execute($query->toSql()); - - self::assertNotFalse($result); + $this->pgsqlContext()->client()->execute($query->toSql()); - $check = $this->execute( + $row = $this->pgsqlContext()->client()->fetchOne( select(col('min_value'), col('max_value')) ->from(table('pg_sequences')) ->where(eq(col('sequencename'), literal(self::SEQUENCE_TEST))) ->toSql() ); - $row = $this->fetchOne($check); - self::assertSame('1', $row['min_value']); - self::assertSame('1000', $row['max_value']); + self::assertSame(1, $row['min_value']); + self::assertSame(1000, $row['max_value']); } public function test_create_sequence_with_start_value() : void @@ -143,64 +129,58 @@ public function test_create_sequence_with_start_value() : void $query = create()->sequence(self::SEQUENCE_TEST) ->startWith(100); - $result = $this->execute($query->toSql()); - - self::assertNotFalse($result); + $this->pgsqlContext()->client()->execute($query->toSql()); - $nextVal = $this->execute( + $row = $this->pgsqlContext()->client()->fetchOne( select(func('nextval', [literal(self::SEQUENCE_TEST)])->as('val'))->toSql() ); - $row = $this->fetchOne($nextVal); - self::assertSame('100', $row['val']); + self::assertSame(100, $row['val']); } public function test_drop_sequence() : void { $createQuery = create()->sequence(self::SEQUENCE_TEST); - $this->execute($createQuery->toSql()); + $this->pgsqlContext()->client()->execute($createQuery->toSql()); $dropQuery = drop()->sequence(self::SEQUENCE_TEST); - $result = $this->execute($dropQuery->toSql()); + $this->pgsqlContext()->client()->execute($dropQuery->toSql()); - self::assertNotFalse($result); - - $check = $this->execute( + $sequences = $this->pgsqlContext()->client()->fetchAll( select(col('sequencename')) ->from(table('pg_sequences')) ->where(eq(col('sequencename'), literal(self::SEQUENCE_TEST))) ->toSql() ); - $sequences = $this->fetchAll($check); self::assertCount(0, $sequences); } public function test_drop_sequence_if_exists() : void { - $dropQuery = drop()->sequence(self::SEQUENCE_TEST)->ifExists(); + $this->expectNotToPerformAssertions(); - $result = $this->execute($dropQuery->toSql()); + $dropQuery = drop()->sequence(self::SEQUENCE_TEST)->ifExists(); - self::assertNotFalse($result); + $this->pgsqlContext()->client()->execute($dropQuery->toSql()); } public function test_sequence_usage_with_nextval() : void { $createQuery = create()->sequence(self::SEQUENCE_COUNTER)->startWith(1); - $this->execute($createQuery->toSql()); + $this->pgsqlContext()->client()->execute($createQuery->toSql()); - $val1 = $this->fetchOne($this->execute( + $val1 = $this->pgsqlContext()->client()->fetchOne( select(func('nextval', [literal(self::SEQUENCE_COUNTER)])->as('val'))->toSql() - )); - $val2 = $this->fetchOne($this->execute( + ); + $val2 = $this->pgsqlContext()->client()->fetchOne( select(func('nextval', [literal(self::SEQUENCE_COUNTER)])->as('val'))->toSql() - )); - $val3 = $this->fetchOne($this->execute( + ); + $val3 = $this->pgsqlContext()->client()->fetchOne( select(func('nextval', [literal(self::SEQUENCE_COUNTER)])->as('val'))->toSql() - )); + ); - self::assertSame('1', $val1['val']); - self::assertSame('2', $val2['val']); - self::assertSame('3', $val3['val']); + self::assertSame(1, $val1['val']); + self::assertSame(2, $val2['val']); + self::assertSame(3, $val3['val']); } } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/TableDatabaseTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/TableDatabaseTest.php index af1af4ffe1..e9b7ffe4a7 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/TableDatabaseTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/TableDatabaseTest.php @@ -5,22 +5,34 @@ namespace Flow\PostgreSql\Tests\Integration\QueryBuilder\Database; use function Flow\PostgreSql\DSL\{ + agg_count, alter, + and_, + asc, check_constraint, + col, column, + column_type_integer, + column_type_serial, + column_type_text, + column_type_varchar, create, - data_type_integer, - data_type_serial, - data_type_text, - data_type_varchar, drop, + eq, foreign_key, + func, + ge, + insert, + literal, primary_key, + select, + table, truncate_table, unique_constraint }; +use Flow\PostgreSql\Tests\Integration\PostgreSqlTestCase; -final class TableDatabaseTest extends DatabaseTestCase +final class TableDatabaseTest extends PostgreSqlTestCase { private const TABLE_CHILD = 'flow_postgres_child_table'; @@ -30,9 +42,9 @@ final class TableDatabaseTest extends DatabaseTestCase protected function tearDown() : void { - $this->dropTableIfExists(self::TABLE_CHILD); - $this->dropTableIfExists(self::TABLE_TEST); - $this->dropTableIfExists(self::TABLE_PARENT); + $this->pgsqlContext()->dropTableIfExists(self::TABLE_CHILD); + $this->pgsqlContext()->dropTableIfExists(self::TABLE_TEST); + $this->pgsqlContext()->dropTableIfExists(self::TABLE_PARENT); parent::tearDown(); } @@ -40,60 +52,71 @@ protected function tearDown() : void public function test_alter_table_add_column() : void { $createQuery = create()->table(self::TABLE_TEST) - ->column(column('id', data_type_serial())) - ->column(column('name', data_type_varchar(100))); - $this->execute($createQuery->toSql()); + ->column(column('id', column_type_serial())) + ->column(column('name', column_type_varchar(100))); + $this->pgsqlContext()->client()->execute($createQuery->toSql()); $alterQuery = alter()->table(self::TABLE_TEST) - ->addColumn(column('email', data_type_varchar(255))); - - $result = $this->execute($alterQuery->toSql()); - - self::assertNotFalse($result); - - $check = $this->execute("SELECT column_name FROM information_schema.columns WHERE table_name = '" . self::TABLE_TEST . "' AND column_name = 'email'"); - $columns = $this->fetchAll($check); + ->addColumn(column('email', column_type_varchar(255))); + + $this->pgsqlContext()->client()->execute($alterQuery->toSql()); + + $columns = $this->pgsqlContext()->client()->fetchAll( + select(col('column_name')) + ->from(table('information_schema.columns')) + ->where(and_( + eq(col('table_name'), literal(self::TABLE_TEST)), + eq(col('column_name'), literal('email')) + )) + ->toSql() + ); self::assertCount(1, $columns); } public function test_alter_table_drop_column() : void { $createQuery = create()->table(self::TABLE_TEST) - ->column(column('id', data_type_serial())) - ->column(column('name', data_type_varchar(100))) - ->column(column('to_drop', data_type_text())); - $this->execute($createQuery->toSql()); + ->column(column('id', column_type_serial())) + ->column(column('name', column_type_varchar(100))) + ->column(column('to_drop', column_type_text())); + $this->pgsqlContext()->client()->execute($createQuery->toSql()); $alterQuery = alter()->table(self::TABLE_TEST) ->dropColumn('to_drop'); - $result = $this->execute($alterQuery->toSql()); - - self::assertNotFalse($result); - - $check = $this->execute("SELECT column_name FROM information_schema.columns WHERE table_name = '" . self::TABLE_TEST . "' AND column_name = 'to_drop'"); - $columns = $this->fetchAll($check); + $this->pgsqlContext()->client()->execute($alterQuery->toSql()); + + $columns = $this->pgsqlContext()->client()->fetchAll( + select(col('column_name')) + ->from(table('information_schema.columns')) + ->where(and_( + eq(col('table_name'), literal(self::TABLE_TEST)), + eq(col('column_name'), literal('to_drop')) + )) + ->toSql() + ); self::assertCount(0, $columns); } public function test_create_table_with_check_constraint() : void { $query = create()->table(self::TABLE_TEST) - ->column(column('id', data_type_serial())) - ->column(column('age', data_type_integer())) - ->constraint(check_constraint('age >= 0')); - - $result = $this->execute($query->toSql()); - - self::assertNotFalse($result); - - $check = $this->execute(" - SELECT pg_get_constraintdef(c.oid) as def - FROM pg_constraint c - JOIN pg_class t ON c.conrelid = t.oid - WHERE t.relname = '" . self::TABLE_TEST . "' AND c.contype = 'c' - "); - $constraints = $this->fetchAll($check); + ->column(column('id', column_type_serial())) + ->column(column('age', column_type_integer())) + ->constraint(check_constraint(ge(col('age'), literal(0)))); + + $this->pgsqlContext()->client()->execute($query->toSql()); + + $constraints = $this->pgsqlContext()->client()->fetchAll( + select(func('pg_get_constraintdef', [col('oid', 'c')])->as('def')) + ->from(table('pg_constraint')->as('c')) + ->join(table('pg_class')->as('t'), eq(col('conrelid', 'c'), col('oid', 't'))) + ->where(and_( + eq(col('relname', 't'), literal(self::TABLE_TEST)), + eq(col('contype', 'c'), literal('c')) + )) + ->toSql() + ); self::assertGreaterThanOrEqual(1, \count($constraints)); $hasAgeConstraint = false; @@ -111,16 +134,19 @@ public function test_create_table_with_check_constraint() : void public function test_create_table_with_columns() : void { $query = create()->table(self::TABLE_TEST) - ->column(column('id', data_type_serial())) - ->column(column('name', data_type_varchar(100))->notNull()) - ->column(column('description', data_type_text())); - - $result = $this->execute($query->toSql()); + ->column(column('id', column_type_serial())) + ->column(column('name', column_type_varchar(100))->notNull()) + ->column(column('description', column_type_text())); - self::assertNotFalse($result); + $this->pgsqlContext()->client()->execute($query->toSql()); - $check = $this->execute("SELECT column_name FROM information_schema.columns WHERE table_name = '" . self::TABLE_TEST . "' ORDER BY ordinal_position"); - $columns = $this->fetchAll($check); + $columns = $this->pgsqlContext()->client()->fetchAll( + select(col('column_name')) + ->from(table('information_schema.columns')) + ->where(eq(col('table_name'), literal(self::TABLE_TEST))) + ->orderBy(asc(col('ordinal_position'))) + ->toSql() + ); self::assertCount(3, $columns); self::assertSame('id', $columns[0]['column_name']); @@ -131,28 +157,31 @@ public function test_create_table_with_columns() : void public function test_create_table_with_foreign_key() : void { $parentQuery = create()->table(self::TABLE_PARENT) - ->column(column('id', data_type_serial())) - ->column(column('name', data_type_varchar(100))) + ->column(column('id', column_type_serial())) + ->column(column('name', column_type_varchar(100))) ->constraint(primary_key('id')); - $this->execute($parentQuery->toSql()); + $this->pgsqlContext()->client()->execute($parentQuery->toSql()); $childQuery = create()->table(self::TABLE_CHILD) - ->column(column('id', data_type_serial())) - ->column(column('parent_id', data_type_integer())->notNull()) + ->column(column('id', column_type_serial())) + ->column(column('parent_id', column_type_integer())->notNull()) ->constraint(foreign_key(['parent_id'], self::TABLE_PARENT, ['id'])); - $result = $this->execute($childQuery->toSql()); - - self::assertNotFalse($result); - - $check = $this->execute(" - SELECT tc.constraint_type, ccu.table_name AS foreign_table_name - FROM information_schema.table_constraints tc - JOIN information_schema.constraint_column_usage ccu - ON tc.constraint_name = ccu.constraint_name - WHERE tc.table_name = '" . self::TABLE_CHILD . "' AND tc.constraint_type = 'FOREIGN KEY' - "); - $constraints = $this->fetchAll($check); + $this->pgsqlContext()->client()->execute($childQuery->toSql()); + + $constraints = $this->pgsqlContext()->client()->fetchAll( + select(col('constraint_type', 'tc'), col('table_name', 'ccu')->as('foreign_table_name')) + ->from(table('information_schema.table_constraints')->as('tc')) + ->join( + table('information_schema.constraint_column_usage')->as('ccu'), + eq(col('constraint_name', 'tc'), col('constraint_name', 'ccu')) + ) + ->where(and_( + eq(col('table_name', 'tc'), literal(self::TABLE_CHILD)), + eq(col('constraint_type', 'tc'), literal('FOREIGN KEY')) + )) + ->toSql() + ); self::assertCount(1, $constraints); self::assertSame(self::TABLE_PARENT, $constraints[0]['foreign_table_name']); } @@ -160,75 +189,87 @@ public function test_create_table_with_foreign_key() : void public function test_create_table_with_primary_key() : void { $query = create()->table(self::TABLE_TEST) - ->column(column('id', data_type_integer())->notNull()) - ->column(column('name', data_type_varchar(100))) + ->column(column('id', column_type_integer())->notNull()) + ->column(column('name', column_type_varchar(100))) ->constraint(primary_key('id')); - $result = $this->execute($query->toSql()); - - self::assertNotFalse($result); - - $check = $this->execute(" - SELECT constraint_type FROM information_schema.table_constraints - WHERE table_name = '" . self::TABLE_TEST . "' AND constraint_type = 'PRIMARY KEY' - "); - $constraints = $this->fetchAll($check); + $this->pgsqlContext()->client()->execute($query->toSql()); + + $constraints = $this->pgsqlContext()->client()->fetchAll( + select(col('constraint_type')) + ->from(table('information_schema.table_constraints')) + ->where(and_( + eq(col('table_name'), literal(self::TABLE_TEST)), + eq(col('constraint_type'), literal('PRIMARY KEY')) + )) + ->toSql() + ); self::assertCount(1, $constraints); } public function test_create_table_with_unique_constraint() : void { $query = create()->table(self::TABLE_TEST) - ->column(column('id', data_type_serial())) - ->column(column('email', data_type_varchar(255))->notNull()) + ->column(column('id', column_type_serial())) + ->column(column('email', column_type_varchar(255))->notNull()) ->constraint(unique_constraint('email')); - $result = $this->execute($query->toSql()); - - self::assertNotFalse($result); - - $check = $this->execute(" - SELECT constraint_type FROM information_schema.table_constraints - WHERE table_name = '" . self::TABLE_TEST . "' AND constraint_type = 'UNIQUE' - "); - $constraints = $this->fetchAll($check); + $this->pgsqlContext()->client()->execute($query->toSql()); + + $constraints = $this->pgsqlContext()->client()->fetchAll( + select(col('constraint_type')) + ->from(table('information_schema.table_constraints')) + ->where(and_( + eq(col('table_name'), literal(self::TABLE_TEST)), + eq(col('constraint_type'), literal('UNIQUE')) + )) + ->toSql() + ); self::assertCount(1, $constraints); } public function test_drop_table() : void { $createQuery = create()->table(self::TABLE_TEST) - ->column(column('id', data_type_serial())); - $this->execute($createQuery->toSql()); + ->column(column('id', column_type_serial())); + $this->pgsqlContext()->client()->execute($createQuery->toSql()); $dropQuery = drop()->table(self::TABLE_TEST); - $result = $this->execute($dropQuery->toSql()); - - self::assertNotFalse($result); + $this->pgsqlContext()->client()->execute($dropQuery->toSql()); - $check = $this->execute("SELECT table_name FROM information_schema.tables WHERE table_name = '" . self::TABLE_TEST . "'"); - $tables = $this->fetchAll($check); + $tables = $this->pgsqlContext()->client()->fetchAll( + select(col('table_name')) + ->from(table('information_schema.tables')) + ->where(eq(col('table_name'), literal(self::TABLE_TEST))) + ->toSql() + ); self::assertCount(0, $tables); } public function test_truncate_table() : void { $createQuery = create()->table(self::TABLE_TEST) - ->column(column('id', data_type_serial())) - ->column(column('name', data_type_varchar(100))); - $this->execute($createQuery->toSql()); - - $this->execute('INSERT INTO ' . self::TABLE_TEST . " (name) VALUES ('test1'), ('test2')"); + ->column(column('id', column_type_serial())) + ->column(column('name', column_type_varchar(100))); + $this->pgsqlContext()->client()->execute($createQuery->toSql()); + + $this->pgsqlContext()->client()->execute( + insert() + ->into(self::TABLE_TEST) + ->columns('name') + ->values(literal('test1')) + ->values(literal('test2')) + ->toSql() + ); $truncateQuery = truncate_table(self::TABLE_TEST); - $result = $this->execute($truncateQuery->toSql()); - - self::assertNotFalse($result); + $this->pgsqlContext()->client()->execute($truncateQuery->toSql()); - $check = $this->execute('SELECT COUNT(*) as cnt FROM ' . self::TABLE_TEST); - $row = $this->fetchOne($check); - self::assertSame('0', $row['cnt']); + $row = $this->pgsqlContext()->client()->fetchOne( + select(agg_count()->as('cnt'))->from(table(self::TABLE_TEST))->toSql() + ); + self::assertSame(0, $row['cnt']); } } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/TransactionDatabaseTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/TransactionDatabaseTest.php index 3898f7c2bb..21a8a1d5cd 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/TransactionDatabaseTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/TransactionDatabaseTest.php @@ -8,11 +8,11 @@ begin, col, column, + column_type_decimal, + column_type_serial, + column_type_varchar, commit, create, - data_type_decimal, - data_type_serial, - data_type_varchar, eq, insert, literal, @@ -27,8 +27,9 @@ }; use Flow\PostgreSql\QueryBuilder\Transaction\IsolationLevel; +use Flow\PostgreSql\Tests\Integration\PostgreSqlTestCase; -final class TransactionDatabaseTest extends DatabaseTestCase +final class TransactionDatabaseTest extends PostgreSqlTestCase { private const TABLE_ACCOUNTS = 'flow_postgres_accounts'; @@ -36,16 +37,16 @@ protected function setUp() : void { parent::setUp(); - $this->execute( + $this->pgsqlContext()->client()->execute( create()->table(self::TABLE_ACCOUNTS) - ->column(column('id', data_type_serial())) - ->column(column('name', data_type_varchar(100))->notNull()) - ->column(column('balance', data_type_decimal(10, 2))->default(0)) + ->column(column('id', column_type_serial())) + ->column(column('name', column_type_varchar(100))->notNull()) + ->column(column('balance', column_type_decimal(10, 2))->default(0)) ->constraint(primary_key('id')) ->toSql() ); - $this->execute( + $this->pgsqlContext()->client()->execute( insert() ->into(self::TABLE_ACCOUNTS) ->columns('name', 'balance') @@ -57,163 +58,151 @@ protected function setUp() : void protected function tearDown() : void { - $this->execute(rollback()->toSql()); - $this->dropTableIfExists(self::TABLE_ACCOUNTS); + $this->pgsqlContext()->client()->execute(rollback()->toSql()); + $this->pgsqlContext()->dropTableIfExists(self::TABLE_ACCOUNTS); parent::tearDown(); } public function test_begin_and_commit() : void { - $this->execute(begin()->toSql()); + $this->pgsqlContext()->client()->execute(begin()->toSql()); $updateQuery = update() ->update(self::TABLE_ACCOUNTS) ->set('balance', literal(1500)) ->where(eq(col('name'), literal('Account A'))); - $this->execute($updateQuery->toSql()); + $this->pgsqlContext()->client()->execute($updateQuery->toSql()); - $this->execute(commit()->toSql()); + $this->pgsqlContext()->client()->execute(commit()->toSql()); - $check = $this->execute( + $row = $this->pgsqlContext()->client()->fetchOne( select(col('balance')) ->from(table(self::TABLE_ACCOUNTS)) ->where(eq(col('name'), literal('Account A'))) ->toSql() ); - $row = $this->fetchOne($check); self::assertSame('1500.00', $row['balance']); } public function test_begin_and_rollback() : void { - $checkBefore = $this->execute( + $beforeRow = $this->pgsqlContext()->client()->fetchOne( select(col('balance')) ->from(table(self::TABLE_ACCOUNTS)) ->where(eq(col('name'), literal('Account A'))) ->toSql() ); - $beforeRow = $this->fetchOne($checkBefore); $originalBalance = $beforeRow['balance']; - $this->execute(begin()->toSql()); + $this->pgsqlContext()->client()->execute(begin()->toSql()); $updateQuery = update() ->update(self::TABLE_ACCOUNTS) ->set('balance', literal(9999)) ->where(eq(col('name'), literal('Account A'))); - $this->execute($updateQuery->toSql()); + $this->pgsqlContext()->client()->execute($updateQuery->toSql()); - $this->execute(rollback()->toSql()); + $this->pgsqlContext()->client()->execute(rollback()->toSql()); - $check = $this->execute( + $row = $this->pgsqlContext()->client()->fetchOne( select(col('balance')) ->from(table(self::TABLE_ACCOUNTS)) ->where(eq(col('name'), literal('Account A'))) ->toSql() ); - $row = $this->fetchOne($check); self::assertSame($originalBalance, $row['balance']); } public function test_begin_with_isolation_level() : void { - $this->execute(begin()->isolationLevel(IsolationLevel::SERIALIZABLE)->toSql()); + $this->pgsqlContext()->client()->execute(begin()->isolationLevel(IsolationLevel::SERIALIZABLE)->toSql()); $selectQuery = select(star())->from(table(self::TABLE_ACCOUNTS)); - $result = $this->execute($selectQuery->toSql()); - - self::assertNotFalse($result); - $rows = $this->fetchAll($result); + $rows = $this->pgsqlContext()->client()->fetchAll($selectQuery->toSql()); self::assertCount(2, $rows); - $this->execute(commit()->toSql()); + $this->pgsqlContext()->client()->execute(commit()->toSql()); } public function test_begin_with_read_only() : void { - $this->execute(begin()->readOnly()->toSql()); + $this->pgsqlContext()->client()->execute(begin()->readOnly()->toSql()); $selectQuery = select(star())->from(table(self::TABLE_ACCOUNTS)); - $result = $this->execute($selectQuery->toSql()); - - self::assertNotFalse($result); - self::assertCount(2, $this->fetchAll($result)); + self::assertCount(2, $this->pgsqlContext()->client()->fetchAll($selectQuery->toSql())); - $this->execute(commit()->toSql()); + $this->pgsqlContext()->client()->execute(commit()->toSql()); } public function test_rollback_to_savepoint() : void { - $this->execute(begin()->toSql()); + $this->pgsqlContext()->client()->execute(begin()->toSql()); $updateQuery1 = update() ->update(self::TABLE_ACCOUNTS) ->set('balance', literal(750)) ->where(eq(col('name'), literal('Account A'))); - $this->execute($updateQuery1->toSql()); + $this->pgsqlContext()->client()->execute($updateQuery1->toSql()); - $this->execute(savepoint('sp_rollback')->toSql()); + $this->pgsqlContext()->client()->execute(savepoint('sp_rollback')->toSql()); $updateQuery2 = update() ->update(self::TABLE_ACCOUNTS) ->set('balance', literal(9999)) ->where(eq(col('name'), literal('Account A'))); - $this->execute($updateQuery2->toSql()); + $this->pgsqlContext()->client()->execute($updateQuery2->toSql()); - $this->execute(rollback()->toSavepoint('sp_rollback')->toSql()); + $this->pgsqlContext()->client()->execute(rollback()->toSavepoint('sp_rollback')->toSql()); - $check = $this->execute( + $row = $this->pgsqlContext()->client()->fetchOne( select(col('balance')) ->from(table(self::TABLE_ACCOUNTS)) ->where(eq(col('name'), literal('Account A'))) ->toSql() ); - $row = $this->fetchOne($check); self::assertSame('750.00', $row['balance']); - $this->execute(commit()->toSql()); + $this->pgsqlContext()->client()->execute(commit()->toSql()); } public function test_savepoint_and_release() : void { - $this->execute(begin()->toSql()); + $this->pgsqlContext()->client()->execute(begin()->toSql()); $updateQuery1 = update() ->update(self::TABLE_ACCOUNTS) ->set('balance', literal(800)) ->where(eq(col('name'), literal('Account A'))); - $this->execute($updateQuery1->toSql()); + $this->pgsqlContext()->client()->execute($updateQuery1->toSql()); - $this->execute(savepoint('sp1')->toSql()); + $this->pgsqlContext()->client()->execute(savepoint('sp1')->toSql()); $updateQuery2 = update() ->update(self::TABLE_ACCOUNTS) ->set('balance', literal(600)) ->where(eq(col('name'), literal('Account B'))); - $this->execute($updateQuery2->toSql()); + $this->pgsqlContext()->client()->execute($updateQuery2->toSql()); - $this->execute(release_savepoint('sp1')->toSql()); - $this->execute(commit()->toSql()); + $this->pgsqlContext()->client()->execute(release_savepoint('sp1')->toSql()); + $this->pgsqlContext()->client()->execute(commit()->toSql()); - $checkA = $this->execute( + $rowA = $this->pgsqlContext()->client()->fetchOne( select(col('balance')) ->from(table(self::TABLE_ACCOUNTS)) ->where(eq(col('name'), literal('Account A'))) ->toSql() ); - $rowA = $this->fetchOne($checkA); self::assertSame('800.00', $rowA['balance']); - $checkB = $this->execute( + $rowB = $this->pgsqlContext()->client()->fetchOne( select(col('balance')) ->from(table(self::TABLE_ACCOUNTS)) ->where(eq(col('name'), literal('Account B'))) ->toSql() ); - $rowB = $this->fetchOne($checkB); self::assertSame('600.00', $rowB['balance']); } } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/TriggerDatabaseTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/TriggerDatabaseTest.php index 013f31f650..6977bfb1ed 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/TriggerDatabaseTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/TriggerDatabaseTest.php @@ -6,25 +6,27 @@ use function Flow\PostgreSql\DSL\{ alter, + col, column, + column_type_integer, + column_type_serial, + column_type_varchar, create, - data_type_integer, - data_type_serial, - data_type_varchar, drop, insert, literal, + ne, primary_key, - raw_cond, select, star, table }; -use Flow\PostgreSql\QueryBuilder\Schema\DataType; +use Flow\PostgreSql\QueryBuilder\Schema\ColumnType; use Flow\PostgreSql\QueryBuilder\Schema\Trigger\TriggerEvent; +use Flow\PostgreSql\Tests\Integration\PostgreSqlTestCase; -final class TriggerDatabaseTest extends DatabaseTestCase +final class TriggerDatabaseTest extends PostgreSqlTestCase { private const FUNCTION_NAME = 'flow_postgres_trigger_func'; @@ -40,27 +42,27 @@ protected function setUp() : void { parent::setUp(); - $this->execute( + $this->pgsqlContext()->client()->execute( create()->table(self::TABLE_NAME) - ->column(column('id', data_type_serial())) - ->column(column('name', data_type_varchar(100))->notNull()) - ->column(column('value', data_type_integer())->default(0)) + ->column(column('id', column_type_serial())) + ->column(column('name', column_type_varchar(100))->notNull()) + ->column(column('value', column_type_integer())->default(0)) ->constraint(primary_key('id')) ->toSql() ); - $this->execute( + $this->pgsqlContext()->client()->execute( create()->table(self::TABLE_LOG) - ->column(column('id', data_type_serial())) - ->column(column('action', data_type_varchar(50))->notNull()) + ->column(column('id', column_type_serial())) + ->column(column('action', column_type_varchar(50))->notNull()) ->constraint(primary_key('id')) ->toSql() ); - $this->execute( + $this->pgsqlContext()->client()->execute( create()->function(self::FUNCTION_NAME) ->arguments() - ->returns(DataType::custom('trigger')) + ->returns(ColumnType::custom('trigger')) ->language('plpgsql') ->as('BEGIN INSERT INTO ' . self::TABLE_LOG . ' (action) VALUES (TG_OP); RETURN NEW; END;') ->toSql() @@ -69,18 +71,18 @@ protected function setUp() : void protected function tearDown() : void { - $this->dropTriggerIfExists(self::TRIGGER_NAME, self::TABLE_NAME); - $this->dropTriggerIfExists(self::TRIGGER_NAME_RENAMED, self::TABLE_NAME); - $this->dropFunctionIfExists(self::FUNCTION_NAME); - $this->dropTableIfExists(self::TABLE_LOG); - $this->dropTableIfExists(self::TABLE_NAME); + $this->pgsqlContext()->dropTriggerIfExists(self::TRIGGER_NAME, self::TABLE_NAME); + $this->pgsqlContext()->dropTriggerIfExists(self::TRIGGER_NAME_RENAMED, self::TABLE_NAME); + $this->pgsqlContext()->dropFunctionIfExists(self::FUNCTION_NAME); + $this->pgsqlContext()->dropTableIfExists(self::TABLE_LOG); + $this->pgsqlContext()->dropTableIfExists(self::TABLE_NAME); parent::tearDown(); } public function test_alter_trigger_rename() : void { - $this->execute( + $this->pgsqlContext()->client()->execute( create()->trigger(self::TRIGGER_NAME) ->before(TriggerEvent::INSERT) ->on(self::TABLE_NAME) @@ -89,21 +91,20 @@ public function test_alter_trigger_rename() : void ->toSql() ); - $result = $this->execute( + $this->pgsqlContext()->client()->execute( alter()->trigger(self::TRIGGER_NAME) ->on(self::TABLE_NAME) ->renameTo(self::TRIGGER_NAME_RENAMED) ->toSql() ); - self::assertNotFalse($result); self::assertFalse($this->triggerExists(self::TRIGGER_NAME, self::TABLE_NAME)); self::assertTrue($this->triggerExists(self::TRIGGER_NAME_RENAMED, self::TABLE_NAME)); } public function test_create_or_replace_trigger() : void { - $this->execute( + $this->pgsqlContext()->client()->execute( create()->trigger(self::TRIGGER_NAME) ->before(TriggerEvent::INSERT) ->on(self::TABLE_NAME) @@ -112,7 +113,7 @@ public function test_create_or_replace_trigger() : void ->toSql() ); - $result = $this->execute( + $this->pgsqlContext()->client()->execute( create()->trigger(self::TRIGGER_NAME) ->orReplace() ->after(TriggerEvent::INSERT) @@ -122,13 +123,12 @@ public function test_create_or_replace_trigger() : void ->toSql() ); - self::assertNotFalse($result); self::assertTrue($this->triggerExists(self::TRIGGER_NAME, self::TABLE_NAME)); } public function test_create_trigger_after_insert() : void { - $result = $this->execute( + $this->pgsqlContext()->client()->execute( create()->trigger(self::TRIGGER_NAME) ->after(TriggerEvent::INSERT) ->on(self::TABLE_NAME) @@ -137,13 +137,12 @@ public function test_create_trigger_after_insert() : void ->toSql() ); - self::assertNotFalse($result); self::assertTrue($this->triggerExists(self::TRIGGER_NAME, self::TABLE_NAME)); } public function test_create_trigger_after_multiple_events() : void { - $result = $this->execute( + $this->pgsqlContext()->client()->execute( create()->trigger(self::TRIGGER_NAME) ->after(TriggerEvent::INSERT, TriggerEvent::UPDATE) ->on(self::TABLE_NAME) @@ -152,13 +151,12 @@ public function test_create_trigger_after_multiple_events() : void ->toSql() ); - self::assertNotFalse($result); self::assertTrue($this->triggerExists(self::TRIGGER_NAME, self::TABLE_NAME)); } public function test_create_trigger_before_insert() : void { - $result = $this->execute( + $this->pgsqlContext()->client()->execute( create()->trigger(self::TRIGGER_NAME) ->before(TriggerEvent::INSERT) ->on(self::TABLE_NAME) @@ -167,10 +165,9 @@ public function test_create_trigger_before_insert() : void ->toSql() ); - self::assertNotFalse($result); self::assertTrue($this->triggerExists(self::TRIGGER_NAME, self::TABLE_NAME)); - $this->execute( + $this->pgsqlContext()->client()->execute( insert() ->into(self::TABLE_NAME) ->columns('name') @@ -178,11 +175,9 @@ public function test_create_trigger_before_insert() : void ->toSql() ); - $logs = $this->fetchAll( - $this->execute( - select(star())->from(table(self::TABLE_LOG)) - ->toSql() - ) + $logs = $this->pgsqlContext()->client()->fetchAll( + select(star())->from(table(self::TABLE_LOG)) + ->toSql() ); self::assertCount(1, $logs); @@ -191,20 +186,19 @@ public function test_create_trigger_before_insert() : void public function test_create_trigger_with_when_condition() : void { - $result = $this->execute( + $this->pgsqlContext()->client()->execute( create()->trigger(self::TRIGGER_NAME) ->before(TriggerEvent::INSERT) ->on(self::TABLE_NAME) ->forEachRow() - ->when(raw_cond('NEW.value <> 0')) + ->when(ne(col('value', 'new'), literal(0))) ->execute(self::FUNCTION_NAME) ->toSql() ); - self::assertNotFalse($result); self::assertTrue($this->triggerExists(self::TRIGGER_NAME, self::TABLE_NAME)); - $this->execute( + $this->pgsqlContext()->client()->execute( insert() ->into(self::TABLE_NAME) ->columns('name', 'value') @@ -212,15 +206,13 @@ public function test_create_trigger_with_when_condition() : void ->toSql() ); - $logs = $this->fetchAll( - $this->execute( - select(star())->from(table(self::TABLE_LOG)) - ->toSql() - ) + $logs = $this->pgsqlContext()->client()->fetchAll( + select(star())->from(table(self::TABLE_LOG)) + ->toSql() ); self::assertCount(0, $logs); - $this->execute( + $this->pgsqlContext()->client()->execute( insert() ->into(self::TABLE_NAME) ->columns('name', 'value') @@ -228,18 +220,16 @@ public function test_create_trigger_with_when_condition() : void ->toSql() ); - $logs = $this->fetchAll( - $this->execute( - select(star())->from(table(self::TABLE_LOG)) - ->toSql() - ) + $logs = $this->pgsqlContext()->client()->fetchAll( + select(star())->from(table(self::TABLE_LOG)) + ->toSql() ); self::assertCount(1, $logs); } public function test_drop_trigger() : void { - $this->execute( + $this->pgsqlContext()->client()->execute( create()->trigger(self::TRIGGER_NAME) ->before(TriggerEvent::INSERT) ->on(self::TABLE_NAME) @@ -250,18 +240,17 @@ public function test_drop_trigger() : void self::assertTrue($this->triggerExists(self::TRIGGER_NAME, self::TABLE_NAME)); - $result = $this->execute( + $this->pgsqlContext()->client()->execute( drop()->trigger(self::TRIGGER_NAME)->on(self::TABLE_NAME) ->toSql() ); - self::assertNotFalse($result); self::assertFalse($this->triggerExists(self::TRIGGER_NAME, self::TABLE_NAME)); } public function test_drop_trigger_cascade() : void { - $this->execute( + $this->pgsqlContext()->client()->execute( create()->trigger(self::TRIGGER_NAME) ->before(TriggerEvent::INSERT) ->on(self::TABLE_NAME) @@ -270,49 +259,36 @@ public function test_drop_trigger_cascade() : void ->toSql() ); - $result = $this->execute( + $this->pgsqlContext()->client()->execute( drop()->trigger(self::TRIGGER_NAME)->on(self::TABLE_NAME)->cascade() ->toSql() ); - self::assertNotFalse($result); self::assertFalse($this->triggerExists(self::TRIGGER_NAME, self::TABLE_NAME)); } public function test_drop_trigger_if_exists() : void { - $result = $this->execute( + $this->expectNotToPerformAssertions(); + + $this->pgsqlContext()->client()->execute( drop()->trigger(self::TRIGGER_NAME)->ifExists()->on(self::TABLE_NAME) ->toSql() ); - - self::assertNotFalse($result); - } - - protected function dropFunctionIfExists(string $name) : void - { - $this->execute("DROP FUNCTION IF EXISTS {$name} CASCADE"); - } - - protected function dropTriggerIfExists(string $triggerName, string $tableName) : void - { - $this->execute("DROP TRIGGER IF EXISTS {$triggerName} ON {$tableName} CASCADE"); } protected function triggerExists(string $triggerName, string $tableName) : bool { - $row = $this->fetchOne( - $this->execute( - "SELECT EXISTS( + $row = $this->pgsqlContext()->client()->fetchOne( + "SELECT EXISTS( SELECT 1 FROM pg_trigger t JOIN pg_class c ON t.tgrelid = c.oid WHERE t.tgname = '{$triggerName}' AND c.relname = '{$tableName}' AND NOT t.tgisinternal ) AS trigger_exists" - ) ); - return $row['trigger_exists'] === 't'; + return $row['trigger_exists'] === true; } } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/TruncateDatabaseTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/TruncateDatabaseTest.php index 545d603fce..502c7277ea 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/TruncateDatabaseTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/TruncateDatabaseTest.php @@ -7,9 +7,9 @@ use function Flow\PostgreSql\DSL\{ col, column, + column_type_serial, + column_type_varchar, create, - data_type_serial, - data_type_varchar, desc, insert, literal, @@ -19,8 +19,9 @@ table, truncate_table }; +use Flow\PostgreSql\Tests\Integration\PostgreSqlTestCase; -final class TruncateDatabaseTest extends DatabaseTestCase +final class TruncateDatabaseTest extends PostgreSqlTestCase { private const SCHEMA_NAME = 'flow_postgres_test_truncate_schema'; @@ -34,23 +35,23 @@ protected function setUp() : void { parent::setUp(); - $this->execute( + $this->pgsqlContext()->client()->execute( create()->table(self::TABLE_ONE) - ->column(column('id', data_type_serial())) - ->column(column('name', data_type_varchar(100))->notNull()) + ->column(column('id', column_type_serial())) + ->column(column('name', column_type_varchar(100))->notNull()) ->constraint(primary_key('id')) ->toSql() ); - $this->execute( + $this->pgsqlContext()->client()->execute( create()->table(self::TABLE_TWO) - ->column(column('id', data_type_serial())) - ->column(column('name', data_type_varchar(100))->notNull()) + ->column(column('id', column_type_serial())) + ->column(column('name', column_type_varchar(100))->notNull()) ->constraint(primary_key('id')) ->toSql() ); - $this->execute( + $this->pgsqlContext()->client()->execute( insert() ->into(self::TABLE_ONE) ->columns('name') @@ -60,7 +61,7 @@ protected function setUp() : void ->toSql() ); - $this->execute( + $this->pgsqlContext()->client()->execute( insert() ->into(self::TABLE_TWO) ->columns('name') @@ -72,43 +73,37 @@ protected function setUp() : void protected function tearDown() : void { - $this->dropTableIfExists(self::TABLE_TWO); - $this->dropTableIfExists(self::TABLE_ONE); - $this->execute('DROP SCHEMA IF EXISTS ' . self::SCHEMA_NAME . ' CASCADE'); + $this->pgsqlContext()->dropTableIfExists(self::TABLE_TWO); + $this->pgsqlContext()->dropTableIfExists(self::TABLE_ONE); + $this->pgsqlContext()->client()->execute('DROP SCHEMA IF EXISTS ' . self::SCHEMA_NAME . ' CASCADE'); parent::tearDown(); } public function test_truncate_cascade() : void { - $result = $this->execute( + $this->pgsqlContext()->client()->execute( truncate_table(self::TABLE_ONE)->cascade()->toSql() ); - self::assertNotFalse($result); - - $rows = $this->fetchAll( - $this->execute( - select(star())->from(table(self::TABLE_ONE))->toSql() - ) + $rows = $this->pgsqlContext()->client()->fetchAll( + select(star())->from(table(self::TABLE_ONE))->toSql() ); self::assertCount(0, $rows); } public function test_truncate_continue_identity() : void { - $lastRow = $this->fetchOne( - $this->execute( - select(col('id'))->from(table(self::TABLE_ONE))->orderBy(desc(col('id')))->limit(1)->toSql() - ) + $lastRow = $this->pgsqlContext()->client()->fetchOne( + select(col('id'))->from(table(self::TABLE_ONE))->orderBy(desc(col('id')))->limit(1)->toSql() ); $lastId = (int) $lastRow['id']; - $this->execute( + $this->pgsqlContext()->client()->execute( truncate_table(self::TABLE_ONE)->continueIdentity()->toSql() ); - $this->execute( + $this->pgsqlContext()->client()->execute( insert() ->into(self::TABLE_ONE) ->columns('name') @@ -116,45 +111,37 @@ public function test_truncate_continue_identity() : void ->toSql() ); - $row = $this->fetchOne( - $this->execute( - select(star())->from(table(self::TABLE_ONE))->toSql() - ) + $row = $this->pgsqlContext()->client()->fetchOne( + select(star())->from(table(self::TABLE_ONE))->toSql() ); - self::assertSame((string) ($lastId + 1), $row['id']); + self::assertSame($lastId + 1, $row['id']); } public function test_truncate_multiple_tables() : void { - $result = $this->execute( + $this->pgsqlContext()->client()->execute( truncate_table(self::TABLE_ONE, self::TABLE_TWO)->toSql() ); - self::assertNotFalse($result); - - $rowsOne = $this->fetchAll( - $this->execute( - select(star())->from(table(self::TABLE_ONE))->toSql() - ) + $rowsOne = $this->pgsqlContext()->client()->fetchAll( + select(star())->from(table(self::TABLE_ONE))->toSql() ); self::assertCount(0, $rowsOne); - $rowsTwo = $this->fetchAll( - $this->execute( - select(star())->from(table(self::TABLE_TWO))->toSql() - ) + $rowsTwo = $this->pgsqlContext()->client()->fetchAll( + select(star())->from(table(self::TABLE_TWO))->toSql() ); self::assertCount(0, $rowsTwo); } public function test_truncate_restart_identity() : void { - $this->execute( + $this->pgsqlContext()->client()->execute( truncate_table(self::TABLE_ONE)->restartIdentity()->toSql() ); - $this->execute( + $this->pgsqlContext()->client()->execute( insert() ->into(self::TABLE_ONE) ->columns('name') @@ -162,74 +149,58 @@ public function test_truncate_restart_identity() : void ->toSql() ); - $row = $this->fetchOne( - $this->execute( - select(star())->from(table(self::TABLE_ONE))->toSql() - ) + $row = $this->pgsqlContext()->client()->fetchOne( + select(star())->from(table(self::TABLE_ONE))->toSql() ); - self::assertSame('1', $row['id']); + self::assertSame(1, $row['id']); self::assertSame('NewRow', $row['name']); } public function test_truncate_restrict() : void { - $result = $this->execute( + $this->pgsqlContext()->client()->execute( truncate_table(self::TABLE_ONE)->restrict()->toSql() ); - self::assertNotFalse($result); - - $rows = $this->fetchAll( - $this->execute( - select(star())->from(table(self::TABLE_ONE))->toSql() - ) + $rows = $this->pgsqlContext()->client()->fetchAll( + select(star())->from(table(self::TABLE_ONE))->toSql() ); self::assertCount(0, $rows); } public function test_truncate_single_table() : void { - $rows = $this->fetchAll( - $this->execute( - select(star())->from(table(self::TABLE_ONE))->toSql() - ) + $rows = $this->pgsqlContext()->client()->fetchAll( + select(star())->from(table(self::TABLE_ONE))->toSql() ); self::assertCount(3, $rows); - $result = $this->execute( + $this->pgsqlContext()->client()->execute( truncate_table(self::TABLE_ONE)->toSql() ); - self::assertNotFalse($result); - - $rows = $this->fetchAll( - $this->execute( - select(star())->from(table(self::TABLE_ONE))->toSql() - ) + $rows = $this->pgsqlContext()->client()->fetchAll( + select(star())->from(table(self::TABLE_ONE))->toSql() ); self::assertCount(0, $rows); - $rowsTwo = $this->fetchAll( - $this->execute( - select(star())->from(table(self::TABLE_TWO))->toSql() - ) + $rowsTwo = $this->pgsqlContext()->client()->fetchAll( + select(star())->from(table(self::TABLE_TWO))->toSql() ); self::assertCount(2, $rowsTwo); } public function test_truncate_with_restart_identity_and_cascade() : void { - $result = $this->execute( + $this->pgsqlContext()->client()->execute( truncate_table(self::TABLE_ONE, self::TABLE_TWO) ->restartIdentity() ->cascade() ->toSql() ); - self::assertNotFalse($result); - - $this->execute( + $this->pgsqlContext()->client()->execute( insert() ->into(self::TABLE_ONE) ->columns('name') @@ -237,28 +208,26 @@ public function test_truncate_with_restart_identity_and_cascade() : void ->toSql() ); - $row = $this->fetchOne( - $this->execute( - select(star())->from(table(self::TABLE_ONE))->toSql() - ) + $row = $this->pgsqlContext()->client()->fetchOne( + select(star())->from(table(self::TABLE_ONE))->toSql() ); - self::assertSame('1', $row['id']); + self::assertSame(1, $row['id']); } public function test_truncate_with_schema_qualified_table() : void { - $this->execute('CREATE SCHEMA IF NOT EXISTS ' . self::SCHEMA_NAME); + $this->pgsqlContext()->client()->execute('CREATE SCHEMA IF NOT EXISTS ' . self::SCHEMA_NAME); - $this->execute( + $this->pgsqlContext()->client()->execute( create()->table(self::SCHEMA_TABLE, self::SCHEMA_NAME) - ->column(column('id', data_type_serial())) - ->column(column('name', data_type_varchar(100))->notNull()) + ->column(column('id', column_type_serial())) + ->column(column('name', column_type_varchar(100))->notNull()) ->constraint(primary_key('id')) ->toSql() ); - $this->execute( + $this->pgsqlContext()->client()->execute( insert() ->into(self::SCHEMA_NAME . '.' . self::SCHEMA_TABLE) ->columns('name') @@ -267,23 +236,17 @@ public function test_truncate_with_schema_qualified_table() : void ->toSql() ); - $rows = $this->fetchAll( - $this->execute( - select(star())->from(table(self::SCHEMA_TABLE, self::SCHEMA_NAME))->toSql() - ) + $rows = $this->pgsqlContext()->client()->fetchAll( + select(star())->from(table(self::SCHEMA_TABLE, self::SCHEMA_NAME))->toSql() ); self::assertCount(2, $rows); - $result = $this->execute( + $this->pgsqlContext()->client()->execute( truncate_table(self::SCHEMA_NAME . '.' . self::SCHEMA_TABLE)->toSql() ); - self::assertNotFalse($result); - - $rows = $this->fetchAll( - $this->execute( - select(star())->from(table(self::SCHEMA_TABLE, self::SCHEMA_NAME))->toSql() - ) + $rows = $this->pgsqlContext()->client()->fetchAll( + select(star())->from(table(self::SCHEMA_TABLE, self::SCHEMA_NAME))->toSql() ); self::assertCount(0, $rows); } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/TypeDatabaseTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/TypeDatabaseTest.php index 905c6b2abe..425077a5c5 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/TypeDatabaseTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/TypeDatabaseTest.php @@ -7,9 +7,9 @@ use function Flow\PostgreSql\DSL\{ alter, column, + column_type_serial, + column_type_varchar, create, - data_type_serial, - data_type_varchar, drop, insert, literal, @@ -18,11 +18,11 @@ star, table }; -use Flow\PostgreSql\QueryBuilder\Schema\DataType; - +use Flow\PostgreSql\QueryBuilder\Schema\ColumnType; use Flow\PostgreSql\QueryBuilder\Schema\Type\TypeAttribute; +use Flow\PostgreSql\Tests\Integration\PostgreSqlTestCase; -final class TypeDatabaseTest extends DatabaseTestCase +final class TypeDatabaseTest extends PostgreSqlTestCase { private const COMPOSITE_TYPE = 'flow_postgres_address_type'; @@ -34,32 +34,30 @@ final class TypeDatabaseTest extends DatabaseTestCase protected function tearDown() : void { - $this->dropTableIfExists(self::TABLE_NAME); - $this->dropTypeIfExists(self::ENUM_TYPE); - $this->dropTypeIfExists(self::COMPOSITE_TYPE); - $this->dropTypeIfExists(self::RANGE_TYPE); + $this->pgsqlContext()->dropTableIfExists(self::TABLE_NAME); + $this->pgsqlContext()->dropTypeIfExists(self::ENUM_TYPE); + $this->pgsqlContext()->dropTypeIfExists(self::COMPOSITE_TYPE); + $this->pgsqlContext()->dropTypeIfExists(self::RANGE_TYPE); parent::tearDown(); } public function test_alter_enum_add_value() : void { - $this->execute( + $this->pgsqlContext()->client()->execute( create()->enumType(self::ENUM_TYPE) ->labels('pending', 'active') ->toSql() ); - $result = $this->execute( + $this->pgsqlContext()->client()->execute( alter()->enumType(self::ENUM_TYPE) ->addValue('completed') ->toSql() ); - self::assertNotFalse($result); - - $values = $this->fetchAll( - $this->execute('SELECT unnest(enum_range(NULL::' . self::ENUM_TYPE . ')) AS val') + $values = $this->pgsqlContext()->client()->fetchAll( + 'SELECT unnest(enum_range(NULL::' . self::ENUM_TYPE . ')) AS val' ); $enumValues = \array_column($values, 'val'); @@ -68,22 +66,20 @@ public function test_alter_enum_add_value() : void public function test_alter_enum_add_value_after() : void { - $this->execute( + $this->pgsqlContext()->client()->execute( create()->enumType(self::ENUM_TYPE) ->labels('first', 'last') ->toSql() ); - $result = $this->execute( + $this->pgsqlContext()->client()->execute( alter()->enumType(self::ENUM_TYPE) ->addValueAfter('middle', 'first') ->toSql() ); - self::assertNotFalse($result); - - $values = $this->fetchAll( - $this->execute('SELECT unnest(enum_range(NULL::' . self::ENUM_TYPE . ')) AS val') + $values = $this->pgsqlContext()->client()->fetchAll( + 'SELECT unnest(enum_range(NULL::' . self::ENUM_TYPE . ')) AS val' ); self::assertSame('first', $values[0]['val']); @@ -93,22 +89,20 @@ public function test_alter_enum_add_value_after() : void public function test_alter_enum_add_value_before() : void { - $this->execute( + $this->pgsqlContext()->client()->execute( create()->enumType(self::ENUM_TYPE) ->labels('first', 'last') ->toSql() ); - $result = $this->execute( + $this->pgsqlContext()->client()->execute( alter()->enumType(self::ENUM_TYPE) ->addValueBefore('middle', 'last') ->toSql() ); - self::assertNotFalse($result); - - $values = $this->fetchAll( - $this->execute('SELECT unnest(enum_range(NULL::' . self::ENUM_TYPE . ')) AS val') + $values = $this->pgsqlContext()->client()->fetchAll( + 'SELECT unnest(enum_range(NULL::' . self::ENUM_TYPE . ')) AS val' ); self::assertSame('first', $values[0]['val']); @@ -118,40 +112,38 @@ public function test_alter_enum_add_value_before() : void public function test_alter_enum_add_value_if_not_exists() : void { - $this->execute( + $this->expectNotToPerformAssertions(); + + $this->pgsqlContext()->client()->execute( create()->enumType(self::ENUM_TYPE) ->labels('pending', 'active') ->toSql() ); - $result = $this->execute( + $this->pgsqlContext()->client()->execute( alter()->enumType(self::ENUM_TYPE) ->addValue('active') ->ifNotExists() ->toSql() ); - - self::assertNotFalse($result); } public function test_alter_enum_rename_value() : void { - $this->execute( + $this->pgsqlContext()->client()->execute( create()->enumType(self::ENUM_TYPE) ->labels('old_name', 'other') ->toSql() ); - $result = $this->execute( + $this->pgsqlContext()->client()->execute( alter()->enumType(self::ENUM_TYPE) ->renameValue('old_name', 'new_name') ->toSql() ); - self::assertNotFalse($result); - - $values = $this->fetchAll( - $this->execute('SELECT unnest(enum_range(NULL::' . self::ENUM_TYPE . ')) AS val') + $values = $this->pgsqlContext()->client()->fetchAll( + 'SELECT unnest(enum_range(NULL::' . self::ENUM_TYPE . ')) AS val' ); $enumValues = \array_column($values, 'val'); @@ -161,48 +153,45 @@ public function test_alter_enum_rename_value() : void public function test_create_composite_type() : void { - $result = $this->execute( + $this->pgsqlContext()->client()->execute( create()->compositeType(self::COMPOSITE_TYPE) ->attributes( - TypeAttribute::of('street', data_type_varchar(100)), - TypeAttribute::of('city', data_type_varchar(50)), - TypeAttribute::of('postal_code', data_type_varchar(20)) + TypeAttribute::of('street', column_type_varchar(100)), + TypeAttribute::of('city', column_type_varchar(50)), + TypeAttribute::of('postal_code', column_type_varchar(20)) ) ->toSql() ); - self::assertNotFalse($result); self::assertTrue($this->typeExists(self::COMPOSITE_TYPE)); } public function test_create_composite_type_and_use_in_table() : void { - $this->execute( + $this->pgsqlContext()->client()->execute( create()->compositeType(self::COMPOSITE_TYPE) ->attributes( - TypeAttribute::of('street', data_type_varchar(100)), - TypeAttribute::of('city', data_type_varchar(50)) + TypeAttribute::of('street', column_type_varchar(100)), + TypeAttribute::of('city', column_type_varchar(50)) ) ->toSql() ); - $this->execute( + $this->pgsqlContext()->client()->execute( create()->table(self::TABLE_NAME) - ->column(column('id', data_type_serial())) - ->column(column('name', data_type_varchar(100))) - ->column(column('address', DataType::custom(self::COMPOSITE_TYPE))) + ->column(column('id', column_type_serial())) + ->column(column('name', column_type_varchar(100))) + ->column(column('address', ColumnType::custom(self::COMPOSITE_TYPE))) ->constraint(primary_key('id')) ->toSql() ); - $this->execute( + $this->pgsqlContext()->client()->execute( 'INSERT INTO ' . self::TABLE_NAME . " (name, address) VALUES ('John', ROW('123 Main St', 'NYC'))" ); - $row = $this->fetchOne( - $this->execute( - 'SELECT name, (address).street, (address).city FROM ' . self::TABLE_NAME - ) + $row = $this->pgsqlContext()->client()->fetchOne( + 'SELECT name, (address).street, (address).city FROM ' . self::TABLE_NAME ); self::assertSame('John', $row['name']); @@ -212,33 +201,32 @@ public function test_create_composite_type_and_use_in_table() : void public function test_create_enum_type() : void { - $result = $this->execute( + $this->pgsqlContext()->client()->execute( create()->enumType(self::ENUM_TYPE) ->labels('pending', 'active', 'completed', 'cancelled') ->toSql() ); - self::assertNotFalse($result); self::assertTrue($this->typeExists(self::ENUM_TYPE)); } public function test_create_enum_type_and_use_in_table() : void { - $this->execute( + $this->pgsqlContext()->client()->execute( create()->enumType(self::ENUM_TYPE) ->labels('pending', 'active', 'completed') ->toSql() ); - $this->execute( + $this->pgsqlContext()->client()->execute( create()->table(self::TABLE_NAME) - ->column(column('id', data_type_serial())) - ->column(column('status', DataType::custom(self::ENUM_TYPE))->notNull()) + ->column(column('id', column_type_serial())) + ->column(column('status', ColumnType::custom(self::ENUM_TYPE))->notNull()) ->constraint(primary_key('id')) ->toSql() ); - $this->execute( + $this->pgsqlContext()->client()->execute( insert() ->into(self::TABLE_NAME) ->columns('status') @@ -246,10 +234,8 @@ public function test_create_enum_type_and_use_in_table() : void ->toSql() ); - $row = $this->fetchOne( - $this->execute( - select(star())->from(table(self::TABLE_NAME))->toSql() - ) + $row = $this->pgsqlContext()->client()->fetchOne( + select(star())->from(table(self::TABLE_NAME))->toSql() ); self::assertSame('active', $row['status']); @@ -257,19 +243,18 @@ public function test_create_enum_type_and_use_in_table() : void public function test_create_range_type() : void { - $result = $this->execute( + $this->pgsqlContext()->client()->execute( create()->rangeType(self::RANGE_TYPE) ->subtype('float8') ->toSql() ); - self::assertNotFalse($result); self::assertTrue($this->typeExists(self::RANGE_TYPE)); } public function test_drop_type() : void { - $this->execute( + $this->pgsqlContext()->client()->execute( create()->enumType(self::ENUM_TYPE) ->labels('a', 'b') ->toSql() @@ -277,58 +262,51 @@ public function test_drop_type() : void self::assertTrue($this->typeExists(self::ENUM_TYPE)); - $result = $this->execute( + $this->pgsqlContext()->client()->execute( drop()->type(self::ENUM_TYPE)->toSql() ); - self::assertNotFalse($result); self::assertFalse($this->typeExists(self::ENUM_TYPE)); } public function test_drop_type_cascade() : void { - $this->execute( + $this->pgsqlContext()->client()->execute( create()->enumType(self::ENUM_TYPE) ->labels('a', 'b') ->toSql() ); - $this->execute( + $this->pgsqlContext()->client()->execute( create()->table(self::TABLE_NAME) - ->column(column('id', data_type_serial())) - ->column(column('status', DataType::custom(self::ENUM_TYPE))) + ->column(column('id', column_type_serial())) + ->column(column('status', ColumnType::custom(self::ENUM_TYPE))) ->constraint(primary_key('id')) ->toSql() ); - $result = $this->execute( + $this->pgsqlContext()->client()->execute( drop()->type(self::ENUM_TYPE)->cascade()->toSql() ); - self::assertNotFalse($result); self::assertFalse($this->typeExists(self::ENUM_TYPE)); } public function test_drop_type_if_exists() : void { - $result = $this->execute( + $this->expectNotToPerformAssertions(); + + $this->pgsqlContext()->client()->execute( drop()->type(self::ENUM_TYPE)->ifExists()->toSql() ); - - self::assertNotFalse($result); - } - - protected function dropTypeIfExists(string $name) : void - { - $this->execute("DROP TYPE IF EXISTS {$name} CASCADE"); } protected function typeExists(string $name) : bool { - $row = $this->fetchOne( - $this->execute("SELECT EXISTS(SELECT 1 FROM pg_type WHERE typname = '{$name}') AS type_exists") + $row = $this->pgsqlContext()->client()->fetchOne( + "SELECT EXISTS(SELECT 1 FROM pg_type WHERE typname = '{$name}') AS type_exists" ); - return $row['type_exists'] === 't'; + return $row['type_exists'] === true; } } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/UpdateDatabaseTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/UpdateDatabaseTest.php index 1e8b938c88..da9976e5cf 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/UpdateDatabaseTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/UpdateDatabaseTest.php @@ -6,14 +6,14 @@ use function Flow\PostgreSql\DSL\{ agg_count, + and_, col, column, - cond_and, + column_type_decimal, + column_type_integer, + column_type_serial, + column_type_varchar, create, - data_type_decimal, - data_type_integer, - data_type_serial, - data_type_varchar, eq, gt, insert, @@ -24,8 +24,9 @@ table, update }; +use Flow\PostgreSql\Tests\Integration\PostgreSqlTestCase; -final class UpdateDatabaseTest extends DatabaseTestCase +final class UpdateDatabaseTest extends PostgreSqlTestCase { private const SCHEMA_NAME = 'flow_postgres_test_update_schema'; @@ -39,27 +40,27 @@ protected function setUp() : void { parent::setUp(); - $this->execute( + $this->pgsqlContext()->client()->execute( create()->table(self::TABLE_DEPARTMENTS) - ->column(column('id', data_type_serial())) - ->column(column('name', data_type_varchar(100))->notNull()) - ->column(column('bonus_rate', data_type_decimal(3, 2))->default(1)) + ->column(column('id', column_type_serial())) + ->column(column('name', column_type_varchar(100))->notNull()) + ->column(column('bonus_rate', column_type_decimal(3, 2))->default(1)) ->constraint(primary_key('id')) ->toSql() ); - $this->execute( + $this->pgsqlContext()->client()->execute( create()->table(self::TABLE_EMPLOYEES) - ->column(column('id', data_type_serial())) - ->column(column('name', data_type_varchar(100))->notNull()) - ->column(column('salary', data_type_decimal(10, 2))->default(0)) - ->column(column('department_id', data_type_integer())) - ->column(column('status', data_type_varchar(50))->default('active')) + ->column(column('id', column_type_serial())) + ->column(column('name', column_type_varchar(100))->notNull()) + ->column(column('salary', column_type_decimal(10, 2))->default(0)) + ->column(column('department_id', column_type_integer())) + ->column(column('status', column_type_varchar(50))->default('active')) ->constraint(primary_key('id')) ->toSql() ); - $this->execute( + $this->pgsqlContext()->client()->execute( insert() ->into(self::TABLE_DEPARTMENTS) ->columns('name', 'bonus_rate') @@ -69,7 +70,7 @@ protected function setUp() : void ->toSql() ); - $this->execute( + $this->pgsqlContext()->client()->execute( insert() ->into(self::TABLE_EMPLOYEES) ->columns('name', 'salary', 'department_id', 'status') @@ -83,9 +84,9 @@ protected function setUp() : void protected function tearDown() : void { - $this->dropTableIfExists(self::TABLE_EMPLOYEES); - $this->dropTableIfExists(self::TABLE_DEPARTMENTS); - $this->execute('DROP SCHEMA IF EXISTS ' . self::SCHEMA_NAME . ' CASCADE'); + $this->pgsqlContext()->dropTableIfExists(self::TABLE_EMPLOYEES); + $this->pgsqlContext()->dropTableIfExists(self::TABLE_DEPARTMENTS); + $this->pgsqlContext()->dropSchemaIfExists(self::SCHEMA_NAME); parent::tearDown(); } @@ -96,19 +97,15 @@ public function test_basic_update() : void ->update(self::TABLE_EMPLOYEES) ->set('status', literal('updated')); - $result = $this->execute($query->toSql()); + self::assertSame(4, $this->pgsqlContext()->client()->execute($query->toSql())); - self::assertNotFalse($result); - self::assertSame(4, $this->affectedRows($result)); - - $check = $this->execute( + $row = $this->pgsqlContext()->client()->fetchOne( select(agg_count(star())->as('cnt')) ->from(table(self::TABLE_EMPLOYEES)) ->where(eq(col('status'), literal('updated'))) ->toSql() ); - $row = $this->fetchOne($check); - self::assertSame('4', $row['cnt']); + self::assertSame(4, $row['cnt']); } public function test_update_multiple_columns() : void @@ -119,17 +116,14 @@ public function test_update_multiple_columns() : void ->set('status', literal('promoted')) ->where(eq(col('name'), literal('Bob'))); - $result = $this->execute($query->toSql()); - - self::assertNotFalse($result); + $this->pgsqlContext()->client()->execute($query->toSql()); - $check = $this->execute( + $row = $this->pgsqlContext()->client()->fetchOne( select(col('salary'), col('status')) ->from(table(self::TABLE_EMPLOYEES)) ->where(eq(col('name'), literal('Bob'))) ->toSql() ); - $row = $this->fetchOne($check); self::assertSame('75000.00', $row['salary']); self::assertSame('promoted', $row['status']); } @@ -141,7 +135,7 @@ public function test_update_with_from_clause() : void ->set('status', literal('bonus_applied')) ->from(table(self::TABLE_DEPARTMENTS)) ->where( - cond_and( + and_( eq( col('department_id', self::TABLE_EMPLOYEES), col('id', self::TABLE_DEPARTMENTS) @@ -150,10 +144,7 @@ public function test_update_with_from_clause() : void ) ); - $result = $this->execute($query->toSql()); - - self::assertNotFalse($result); - self::assertGreaterThanOrEqual(1, $this->affectedRows($result)); + self::assertGreaterThanOrEqual(1, $this->pgsqlContext()->client()->execute($query->toSql())); } public function test_update_with_returning() : void @@ -164,10 +155,8 @@ public function test_update_with_returning() : void ->where(eq(col('name'), literal('Charlie'))) ->returning(col('id'), col('name'), col('salary')); - $result = $this->execute($query->toSql()); + $row = $this->pgsqlContext()->client()->fetchOne($query->toSql()); - self::assertNotFalse($result); - $row = $this->fetchOne($result); self::assertSame('Charlie', $row['name']); self::assertSame('80000.00', $row['salary']); } @@ -180,10 +169,8 @@ public function test_update_with_returning_all() : void ->where(eq(col('name'), literal('Diana'))) ->returningAll(); - $result = $this->execute($query->toSql()); + $row = $this->pgsqlContext()->client()->fetchOne($query->toSql()); - self::assertNotFalse($result); - $row = $this->fetchOne($result); self::assertArrayHasKey('id', $row); self::assertArrayHasKey('name', $row); self::assertArrayHasKey('salary', $row); @@ -194,18 +181,20 @@ public function test_update_with_returning_all() : void public function test_update_with_schema_qualified_table() : void { - $this->execute('CREATE SCHEMA IF NOT EXISTS ' . self::SCHEMA_NAME); + $this->pgsqlContext()->client()->execute( + create()->schema(self::SCHEMA_NAME)->ifNotExists()->toSql() + ); - $this->execute( + $this->pgsqlContext()->client()->execute( create()->table(self::SCHEMA_TABLE, self::SCHEMA_NAME) - ->column(column('id', data_type_serial())) - ->column(column('name', data_type_varchar(100))->notNull()) - ->column(column('status', data_type_varchar(50))->default('active')) + ->column(column('id', column_type_serial())) + ->column(column('name', column_type_varchar(100))->notNull()) + ->column(column('status', column_type_varchar(50))->default('active')) ->constraint(primary_key('id')) ->toSql() ); - $this->execute( + $this->pgsqlContext()->client()->execute( insert() ->into(self::SCHEMA_NAME . '.' . self::SCHEMA_TABLE) ->columns('name', 'status') @@ -218,18 +207,14 @@ public function test_update_with_schema_qualified_table() : void ->set('status', literal('updated')) ->where(eq(col('name'), literal('Alice'))); - $result = $this->execute($query->toSql()); - - self::assertNotFalse($result); - self::assertSame(1, $this->affectedRows($result)); + self::assertSame(1, $this->pgsqlContext()->client()->execute($query->toSql())); - $check = $this->execute( + $row = $this->pgsqlContext()->client()->fetchOne( select(col('status')) ->from(table(self::SCHEMA_TABLE, self::SCHEMA_NAME)) ->where(eq(col('name'), literal('Alice'))) ->toSql() ); - $row = $this->fetchOne($check); self::assertSame('updated', $row['status']); } @@ -240,18 +225,14 @@ public function test_update_with_where() : void ->set('salary', literal(70000)) ->where(eq(col('name'), literal('Alice'))); - $result = $this->execute($query->toSql()); - - self::assertNotFalse($result); - self::assertSame(1, $this->affectedRows($result)); + self::assertSame(1, $this->pgsqlContext()->client()->execute($query->toSql())); - $check = $this->execute( + $row = $this->pgsqlContext()->client()->fetchOne( select(col('salary')) ->from(table(self::TABLE_EMPLOYEES)) ->where(eq(col('name'), literal('Alice'))) ->toSql() ); - $row = $this->fetchOne($check); self::assertSame('70000.00', $row['salary']); } } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/UtilityDatabaseTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/UtilityDatabaseTest.php index 846f6095e3..18d64ea87c 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/UtilityDatabaseTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/UtilityDatabaseTest.php @@ -8,11 +8,11 @@ analyze, cluster, column, + column_type_integer, + column_type_serial, + column_type_varchar, comment, create, - data_type_integer, - data_type_serial, - data_type_varchar, explain, insert, literal, @@ -24,8 +24,9 @@ vacuum }; use Flow\PostgreSql\QueryBuilder\Utility\{CommentTarget, LockMode}; +use Flow\PostgreSql\Tests\Integration\PostgreSqlTestCase; -final class UtilityDatabaseTest extends DatabaseTestCase +final class UtilityDatabaseTest extends PostgreSqlTestCase { private const INDEX_NAME = 'flow_postgres_utility_idx'; @@ -35,16 +36,16 @@ protected function setUp() : void { parent::setUp(); - $this->execute( + $this->pgsqlContext()->client()->execute( create()->table(self::TABLE_NAME) - ->column(column('id', data_type_serial())) - ->column(column('name', data_type_varchar(100))->notNull()) - ->column(column('value', data_type_integer())->default(0)) + ->column(column('id', column_type_serial())) + ->column(column('name', column_type_varchar(100))->notNull()) + ->column(column('value', column_type_integer())->default(0)) ->constraint(primary_key('id')) ->toSql() ); - $this->execute( + $this->pgsqlContext()->client()->execute( insert() ->into(self::TABLE_NAME) ->columns('name', 'value') @@ -56,106 +57,102 @@ protected function setUp() : void protected function tearDown() : void { - $this->dropIndexIfExists(self::INDEX_NAME); - $this->dropTableIfExists(self::TABLE_NAME); + $this->pgsqlContext()->dropIndexIfExists(self::INDEX_NAME); + $this->pgsqlContext()->dropTableIfExists(self::TABLE_NAME); parent::tearDown(); } public function test_analyze_specific_columns() : void { - $result = $this->execute( + $this->expectNotToPerformAssertions(); + + $this->pgsqlContext()->client()->execute( analyze()->table(self::TABLE_NAME, 'name', 'value') ->toSql() ); - - self::assertNotFalse($result); } public function test_analyze_table() : void { - $result = $this->execute( + $this->expectNotToPerformAssertions(); + + $this->pgsqlContext()->client()->execute( analyze()->tables(self::TABLE_NAME) ->toSql() ); - - self::assertNotFalse($result); } public function test_analyze_verbose() : void { - $result = $this->execute( + $this->expectNotToPerformAssertions(); + + $this->pgsqlContext()->client()->execute( analyze()->verbose()->tables(self::TABLE_NAME) ->toSql() ); - - self::assertNotFalse($result); } public function test_cluster_table_on_index() : void { - $this->execute( + $this->expectNotToPerformAssertions(); + + $this->pgsqlContext()->client()->execute( create()->index(self::INDEX_NAME) ->on(self::TABLE_NAME) ->columns('name') ->toSql() ); - $result = $this->execute( + $this->pgsqlContext()->client()->execute( cluster()->table(self::TABLE_NAME)->using(self::INDEX_NAME) ->toSql() ); - - self::assertNotFalse($result); } public function test_cluster_verbose() : void { - $this->execute( + $this->expectNotToPerformAssertions(); + + $this->pgsqlContext()->client()->execute( create()->index(self::INDEX_NAME) ->on(self::TABLE_NAME) ->columns('name') ->toSql() ); - $this->execute( + $this->pgsqlContext()->client()->execute( cluster()->table(self::TABLE_NAME)->using(self::INDEX_NAME) ->toSql() ); - $result = $this->execute( + $this->pgsqlContext()->client()->execute( cluster()->verbose()->table(self::TABLE_NAME) ->toSql() ); - - self::assertNotFalse($result); } public function test_comment_on_column() : void { - $result = $this->execute( + $this->expectNotToPerformAssertions(); + + $this->pgsqlContext()->client()->execute( comment(CommentTarget::COLUMN, self::TABLE_NAME . '.name') ->is('Name of the entity') ->toSql() ); - - self::assertNotFalse($result); } public function test_comment_on_table() : void { - $result = $this->execute( + $this->pgsqlContext()->client()->execute( comment(CommentTarget::TABLE, self::TABLE_NAME) ->is('This is a test table for utility tests') ->toSql() ); - self::assertNotFalse($result); - - $row = $this->fetchOne( - $this->execute( - "SELECT obj_description('" . self::TABLE_NAME . "'::regclass, 'pg_class') AS comment" - ) + $row = $this->pgsqlContext()->client()->fetchOne( + "SELECT obj_description('" . self::TABLE_NAME . "'::regclass, 'pg_class') AS comment" ); self::assertSame('This is a test table for utility tests', $row['comment']); @@ -163,24 +160,20 @@ public function test_comment_on_table() : void public function test_comment_remove() : void { - $this->execute( + $this->pgsqlContext()->client()->execute( comment(CommentTarget::TABLE, self::TABLE_NAME) ->is('Some comment') ->toSql() ); - $result = $this->execute( + $this->pgsqlContext()->client()->execute( comment(CommentTarget::TABLE, self::TABLE_NAME) ->isNull() ->toSql() ); - self::assertNotFalse($result); - - $row = $this->fetchOne( - $this->execute( - "SELECT obj_description('" . self::TABLE_NAME . "'::regclass, 'pg_class') AS comment" - ) + $row = $this->pgsqlContext()->client()->fetchOne( + "SELECT obj_description('" . self::TABLE_NAME . "'::regclass, 'pg_class') AS comment" ); self::assertNull($row['comment']); @@ -190,14 +183,10 @@ public function test_explain_analyze() : void { $selectQuery = select(star())->from(table(self::TABLE_NAME)); - $result = $this->execute( + $rows = $this->pgsqlContext()->client()->fetchAll( explain($selectQuery)->analyze() ->toSql() ); - - self::assertNotFalse($result); - - $rows = $this->fetchAll($result); self::assertNotEmpty($rows); } @@ -205,14 +194,10 @@ public function test_explain_select() : void { $selectQuery = select(star())->from(table(self::TABLE_NAME)); - $result = $this->execute( + $rows = $this->pgsqlContext()->client()->fetchAll( explain($selectQuery) ->toSql() ); - - self::assertNotFalse($result); - - $rows = $this->fetchAll($result); self::assertNotEmpty($rows); self::assertArrayHasKey('QUERY PLAN', $rows[0]); } @@ -221,86 +206,82 @@ public function test_explain_verbose() : void { $selectQuery = select(star())->from(table(self::TABLE_NAME)); - $result = $this->execute( + $rows = $this->pgsqlContext()->client()->fetchAll( explain($selectQuery)->verbose() ->toSql() ); - - self::assertNotFalse($result); - - $rows = $this->fetchAll($result); self::assertNotEmpty($rows); } public function test_lock_table() : void { - $this->execute('BEGIN'); + $this->expectNotToPerformAssertions(); - $result = $this->execute( + $this->pgsqlContext()->client()->execute('BEGIN'); + + $this->pgsqlContext()->client()->execute( lock_table(self::TABLE_NAME) ->toSql() ); - self::assertNotFalse($result); - - $this->execute('COMMIT'); + $this->pgsqlContext()->client()->execute('COMMIT'); } public function test_lock_table_nowait() : void { - $this->execute('BEGIN'); + $this->expectNotToPerformAssertions(); - $result = $this->execute( + $this->pgsqlContext()->client()->execute('BEGIN'); + + $this->pgsqlContext()->client()->execute( lock_table(self::TABLE_NAME)->noWait() ->toSql() ); - self::assertNotFalse($result); - - $this->execute('COMMIT'); + $this->pgsqlContext()->client()->execute('COMMIT'); } public function test_lock_table_with_mode() : void { - $this->execute('BEGIN'); + $this->expectNotToPerformAssertions(); - $result = $this->execute( + $this->pgsqlContext()->client()->execute('BEGIN'); + + $this->pgsqlContext()->client()->execute( lock_table(self::TABLE_NAME)->inMode(LockMode::SHARE) ->toSql() ); - self::assertNotFalse($result); - - $this->execute('COMMIT'); + $this->pgsqlContext()->client()->execute('COMMIT'); } public function test_vacuum_analyze_table() : void { - $result = $this->execute( + $this->expectNotToPerformAssertions(); + + $this->pgsqlContext()->client()->execute( vacuum()->analyze()->tables(self::TABLE_NAME) ->toSql() ); - - self::assertNotFalse($result); } public function test_vacuum_full() : void { - $result = $this->execute( + $this->expectNotToPerformAssertions(); + + $this->pgsqlContext()->client()->execute( vacuum()->full()->tables(self::TABLE_NAME) ->toSql() ); - - self::assertNotFalse($result); } public function test_vacuum_table() : void { - $result = $this->execute( + $this->expectNotToPerformAssertions(); + + $this->pgsqlContext()->client()->execute( vacuum()->tables(self::TABLE_NAME) ->toSql() ); - - self::assertNotFalse($result); } } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/ViewDatabaseTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/ViewDatabaseTest.php index bf855f8dc9..aca17c8f19 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/ViewDatabaseTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/ViewDatabaseTest.php @@ -5,12 +5,13 @@ namespace Flow\PostgreSql\Tests\Integration\QueryBuilder\Database; use function Flow\PostgreSql\DSL\{ + agg_count, col, column, + column_type_integer, + column_type_serial, + column_type_varchar, create, - data_type_integer, - data_type_serial, - data_type_varchar, drop, eq, gt, @@ -21,8 +22,9 @@ star, table }; +use Flow\PostgreSql\Tests\Integration\PostgreSqlTestCase; -final class ViewDatabaseTest extends DatabaseTestCase +final class ViewDatabaseTest extends PostgreSqlTestCase { private const MATVIEW_SIMPLE = 'flow_postgres_simple_matview'; @@ -37,13 +39,13 @@ protected function setUp() : void parent::setUp(); $query = create()->table(self::TABLE_SOURCE) - ->column(column('id', data_type_serial())) - ->column(column('name', data_type_varchar(100))) - ->column(column('value', data_type_integer())); + ->column(column('id', column_type_serial())) + ->column(column('name', column_type_varchar(100))) + ->column(column('value', column_type_integer())); - $this->execute($query->toSql()); + $this->pgsqlContext()->client()->execute($query->toSql()); - $this->execute( + $this->pgsqlContext()->client()->execute( insert() ->into(self::TABLE_SOURCE) ->columns('name', 'value') @@ -57,10 +59,10 @@ protected function setUp() : void protected function tearDown() : void { - $this->dropViewIfExists(self::VIEW_SIMPLE); - $this->dropViewIfExists(self::VIEW_FILTERED); - $this->dropMaterializedViewIfExists(self::MATVIEW_SIMPLE); - $this->dropTableIfExists(self::TABLE_SOURCE); + $this->pgsqlContext()->dropViewIfExists(self::VIEW_SIMPLE); + $this->pgsqlContext()->dropViewIfExists(self::VIEW_FILTERED); + $this->pgsqlContext()->dropMaterializedViewIfExists(self::MATVIEW_SIMPLE); + $this->pgsqlContext()->dropTableIfExists(self::TABLE_SOURCE); parent::tearDown(); } @@ -72,12 +74,14 @@ public function test_create_materialized_view() : void $query = create()->materializedView(self::MATVIEW_SIMPLE) ->as($selectQuery); - $result = $this->execute($query->toSql()); + $this->pgsqlContext()->client()->execute($query->toSql()); - self::assertNotFalse($result); - - $check = $this->execute("SELECT matviewname FROM pg_matviews WHERE matviewname = '" . self::MATVIEW_SIMPLE . "'"); - $views = $this->fetchAll($check); + $views = $this->pgsqlContext()->client()->fetchAll( + select(col('matviewname')) + ->from(table('pg_matviews')) + ->where(eq(col('matviewname'), literal(self::MATVIEW_SIMPLE))) + ->toSql() + ); self::assertCount(1, $views); } @@ -85,22 +89,22 @@ public function test_create_or_replace_view() : void { $selectQuery1 = select(col('id'), col('name'))->from(table(self::TABLE_SOURCE)); $createQuery1 = create()->view(self::VIEW_SIMPLE)->as($selectQuery1); - $this->execute($createQuery1->toSql()); + $this->pgsqlContext()->client()->execute($createQuery1->toSql()); $selectQuery2 = select(col('id'), col('name'), col('value'))->from(table(self::TABLE_SOURCE)); $replaceQuery = create()->view(self::VIEW_SIMPLE) ->orReplace() ->as($selectQuery2); - $result = $this->execute($replaceQuery->toSql()); - - self::assertNotFalse($result); + $this->pgsqlContext()->client()->execute($replaceQuery->toSql()); - $check = $this->execute('SELECT * FROM ' . self::VIEW_SIMPLE); - $row = $this->fetchOne($check); - self::assertArrayHasKey('id', $row); - self::assertArrayHasKey('name', $row); - self::assertArrayHasKey('value', $row); + $rows = $this->pgsqlContext()->client()->fetchAll( + select(star())->from(table(self::VIEW_SIMPLE))->toSql() + ); + self::assertNotEmpty($rows); + self::assertArrayHasKey('id', $rows[0]); + self::assertArrayHasKey('name', $rows[0]); + self::assertArrayHasKey('value', $rows[0]); } public function test_create_view() : void @@ -110,17 +114,14 @@ public function test_create_view() : void $query = create()->view(self::VIEW_SIMPLE) ->as($selectQuery); - $result = $this->execute($query->toSql()); + $this->pgsqlContext()->client()->execute($query->toSql()); - self::assertNotFalse($result); - - $check = $this->execute( + $views = $this->pgsqlContext()->client()->fetchAll( select(col('table_name')) ->from(table('information_schema.views')) ->where(eq(col('table_name'), literal(self::VIEW_SIMPLE))) ->toSql() ); - $views = $this->fetchAll($check); self::assertCount(1, $views); } @@ -133,12 +134,11 @@ public function test_create_view_with_filter() : void $query = create()->view(self::VIEW_FILTERED) ->as($selectQuery); - $this->execute($query->toSql()); - - $result = $this->execute('SELECT * FROM ' . self::VIEW_FILTERED); + $this->pgsqlContext()->client()->execute($query->toSql()); - self::assertNotFalse($result); - $rows = $this->fetchAll($result); + $rows = $this->pgsqlContext()->client()->fetchAll( + select(star())->from(table(self::VIEW_FILTERED))->toSql() + ); self::assertCount(2, $rows); } @@ -146,16 +146,18 @@ public function test_drop_materialized_view() : void { $selectQuery = select(star())->from(table(self::TABLE_SOURCE)); $createQuery = create()->materializedView(self::MATVIEW_SIMPLE)->as($selectQuery); - $this->execute($createQuery->toSql()); + $this->pgsqlContext()->client()->execute($createQuery->toSql()); $dropQuery = drop()->materializedView(self::MATVIEW_SIMPLE); - $result = $this->execute($dropQuery->toSql()); - - self::assertNotFalse($result); + $this->pgsqlContext()->client()->execute($dropQuery->toSql()); - $check = $this->execute("SELECT matviewname FROM pg_matviews WHERE matviewname = '" . self::MATVIEW_SIMPLE . "'"); - $views = $this->fetchAll($check); + $views = $this->pgsqlContext()->client()->fetchAll( + select(col('matviewname')) + ->from(table('pg_matviews')) + ->where(eq(col('matviewname'), literal(self::MATVIEW_SIMPLE))) + ->toSql() + ); self::assertCount(0, $views); } @@ -163,26 +165,28 @@ public function test_drop_view() : void { $selectQuery = select(star())->from(table(self::TABLE_SOURCE)); $createQuery = create()->view(self::VIEW_SIMPLE)->as($selectQuery); - $this->execute($createQuery->toSql()); + $this->pgsqlContext()->client()->execute($createQuery->toSql()); $dropQuery = drop()->view(self::VIEW_SIMPLE); - $result = $this->execute($dropQuery->toSql()); + $this->pgsqlContext()->client()->execute($dropQuery->toSql()); - self::assertNotFalse($result); - - $check = $this->execute("SELECT table_name FROM information_schema.views WHERE table_name = '" . self::VIEW_SIMPLE . "'"); - $views = $this->fetchAll($check); + $views = $this->pgsqlContext()->client()->fetchAll( + select(col('table_name')) + ->from(table('information_schema.views')) + ->where(eq(col('table_name'), literal(self::VIEW_SIMPLE))) + ->toSql() + ); self::assertCount(0, $views); } public function test_drop_view_if_exists() : void { - $dropQuery = drop()->view(self::VIEW_SIMPLE)->ifExists(); + $this->expectNotToPerformAssertions(); - $result = $this->execute($dropQuery->toSql()); + $dropQuery = drop()->view(self::VIEW_SIMPLE)->ifExists(); - self::assertNotFalse($result); + $this->pgsqlContext()->client()->execute($dropQuery->toSql()); } public function test_materialized_view_returns_data() : void @@ -191,12 +195,11 @@ public function test_materialized_view_returns_data() : void $createQuery = create()->materializedView(self::MATVIEW_SIMPLE) ->as($selectQuery); - $this->execute($createQuery->toSql()); - - $result = $this->execute('SELECT * FROM ' . self::MATVIEW_SIMPLE); + $this->pgsqlContext()->client()->execute($createQuery->toSql()); - self::assertNotFalse($result); - $rows = $this->fetchAll($result); + $rows = $this->pgsqlContext()->client()->fetchAll( + select(star())->from(table(self::MATVIEW_SIMPLE))->toSql() + ); self::assertCount(4, $rows); } @@ -206,20 +209,28 @@ public function test_refresh_materialized_view() : void $createQuery = create()->materializedView(self::MATVIEW_SIMPLE) ->as($selectQuery); - $this->execute($createQuery->toSql()); + $this->pgsqlContext()->client()->execute($createQuery->toSql()); - $this->execute('INSERT INTO ' . self::TABLE_SOURCE . " (name, value) VALUES ('Item E', 500)"); + $this->pgsqlContext()->client()->execute( + insert() + ->into(self::TABLE_SOURCE) + ->columns('name', 'value') + ->values(literal('Item E'), literal(500)) + ->toSql() + ); - $beforeRefresh = $this->execute('SELECT COUNT(*) as cnt FROM ' . self::MATVIEW_SIMPLE); - $beforeRow = $this->fetchOne($beforeRefresh); - self::assertSame('4', $beforeRow['cnt']); + $beforeRow = $this->pgsqlContext()->client()->fetchOne( + select(agg_count()->as('cnt'))->from(table(self::MATVIEW_SIMPLE))->toSql() + ); + self::assertSame(4, $beforeRow['cnt']); $refreshQuery = refresh_materialized_view(self::MATVIEW_SIMPLE); - $this->execute($refreshQuery->toSql()); + $this->pgsqlContext()->client()->execute($refreshQuery->toSql()); - $afterRefresh = $this->execute('SELECT COUNT(*) as cnt FROM ' . self::MATVIEW_SIMPLE); - $afterRow = $this->fetchOne($afterRefresh); - self::assertSame('5', $afterRow['cnt']); + $afterRow = $this->pgsqlContext()->client()->fetchOne( + select(agg_count()->as('cnt'))->from(table(self::MATVIEW_SIMPLE))->toSql() + ); + self::assertSame(5, $afterRow['cnt']); } public function test_view_returns_data() : void @@ -228,14 +239,11 @@ public function test_view_returns_data() : void $createQuery = create()->view(self::VIEW_SIMPLE) ->as($selectQuery); - $this->execute($createQuery->toSql()); + $this->pgsqlContext()->client()->execute($createQuery->toSql()); - $result = $this->execute( + $rows = $this->pgsqlContext()->client()->fetchAll( select(star())->from(table(self::VIEW_SIMPLE))->toSql() ); - - self::assertNotFalse($result); - $rows = $this->fetchAll($result); self::assertCount(4, $rows); } } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/DeleteBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/DeleteBuilderTest.php deleted file mode 100644 index 3f4fbd6a82..0000000000 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/DeleteBuilderTest.php +++ /dev/null @@ -1,103 +0,0 @@ -from('users', 'u') - ->where(eq(col('id', 'u'), literal(1))); - - $this->assertDeleteQueryRoundTrip( - $query, - 'DELETE FROM users u WHERE u.id = 1' - ); - } - - public function test_delete_with_parameters() : void - { - $query = delete() - ->from('users') - ->where(eq(col('id'), param(1))); - - $this->assertDeleteQueryRoundTrip( - $query, - 'DELETE FROM users WHERE id = $1' - ); - } - - public function test_delete_with_returning() : void - { - $query = delete() - ->from('users') - ->where(eq(col('id'), literal(1))) - ->returning(col('id'), col('name')); - - $this->assertDeleteQueryRoundTrip( - $query, - 'DELETE FROM users WHERE id = 1 RETURNING id, name' - ); - } - - public function test_delete_with_returning_all() : void - { - $query = delete() - ->from('users') - ->where(eq(col('id'), literal(1))) - ->returningAll(); - - $this->assertDeleteQueryRoundTrip( - $query, - 'DELETE FROM users WHERE id = 1 RETURNING *' - ); - } - - public function test_delete_with_subquery_in_where() : void - { - $subquery = select() - ->select(col('user_id')) - ->from(table('inactive_users')); - - $query = delete() - ->from('users') - ->where(any_sub_select(col('id'), ComparisonOperator::EQ, $subquery)); - - $this->assertDeleteQueryRoundTrip( - $query, - 'DELETE FROM users WHERE id = ANY (SELECT user_id FROM inactive_users)' - ); - } - - public function test_delete_with_using() : void - { - $query = delete() - ->from('orders') - ->using(table('users')) - ->where(eq(col('orders.user_id'), col('users.id'))); - - $this->assertDeleteQueryRoundTrip( - $query, - 'DELETE FROM orders USING users WHERE orders.user_id = users.id' - ); - } - - public function test_simple_delete() : void - { - $query = delete() - ->from('users') - ->where(eq(col('id'), literal(1))); - - $this->assertDeleteQueryRoundTrip( - $query, - 'DELETE FROM users WHERE id = 1' - ); - } -} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/DomainBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/DomainBuilderTest.php deleted file mode 100644 index 48b093172e..0000000000 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/DomainBuilderTest.php +++ /dev/null @@ -1,274 +0,0 @@ -domain('email') - ->addConstraint('valid_email', "VALUE ~ '^.+@.+$'"); - - $this->assertAlterDomainQuery( - $builder, - "ALTER DOMAIN email ADD CONSTRAINT valid_email CHECK (value ~ '^.+@.+$')" - ); - } - - public function test_alter_domain_drop_constraint() : void - { - $builder = alter()->domain('email') - ->dropConstraint('valid_email'); - - $this->assertAlterDomainQuery( - $builder, - 'ALTER DOMAIN email DROP CONSTRAINT valid_email' - ); - } - - public function test_alter_domain_drop_constraint_cascade() : void - { - $builder = alter()->domain('email') - ->dropConstraint('valid_email') - ->cascade(); - - $this->assertAlterDomainQuery( - $builder, - 'ALTER DOMAIN email DROP CONSTRAINT valid_email CASCADE' - ); - } - - public function test_alter_domain_drop_default() : void - { - $builder = alter()->domain('email') - ->dropDefault(); - - $this->assertAlterDomainQuery( - $builder, - 'ALTER DOMAIN email DROP DEFAULT' - ); - } - - public function test_alter_domain_drop_not_null() : void - { - $builder = alter()->domain('email') - ->dropNotNull(); - - $this->assertAlterDomainQuery( - $builder, - 'ALTER DOMAIN email DROP NOT NULL' - ); - } - - public function test_alter_domain_set_default() : void - { - $builder = alter()->domain('email') - ->setDefault("'default@example.com'"); - - $this->assertAlterDomainQuery( - $builder, - "ALTER DOMAIN email SET DEFAULT 'default@example.com'" - ); - } - - public function test_alter_domain_set_not_null() : void - { - $builder = alter()->domain('email') - ->setNotNull(); - - $this->assertAlterDomainQuery( - $builder, - 'ALTER DOMAIN email SET NOT NULL' - ); - } - - public function test_alter_domain_validate_constraint() : void - { - $builder = alter()->domain('email') - ->validateConstraint('valid_email'); - - $this->assertAlterDomainQuery( - $builder, - 'ALTER DOMAIN email VALIDATE CONSTRAINT valid_email' - ); - } - - public function test_create_domain_simple() : void - { - $builder = create()->domain('email') - ->as(DataType::text()); - - $this->assertCreateDomainQuery( - $builder, - 'CREATE DOMAIN email AS pg_catalog.text' - ); - } - - public function test_create_domain_with_check() : void - { - $builder = create()->domain('positive_int') - ->as(DataType::integer()) - ->check('VALUE > 0'); - - $this->assertCreateDomainQuery( - $builder, - 'CREATE DOMAIN positive_int AS int CHECK (value > 0)' - ); - } - - public function test_create_domain_with_collation() : void - { - $builder = create()->domain('email') - ->as(DataType::text()) - ->collate('en_US'); - - $this->assertCreateDomainQuery( - $builder, - 'CREATE DOMAIN email AS pg_catalog.text COLLATE "en_US"' - ); - } - - public function test_create_domain_with_default() : void - { - $builder = create()->domain('email') - ->as(DataType::text()) - ->default("'default@example.com'"); - - $this->assertCreateDomainQuery( - $builder, - "CREATE DOMAIN email AS pg_catalog.text DEFAULT 'default@example.com'" - ); - } - - public function test_create_domain_with_multiple_constraints() : void - { - $builder = create()->domain('email') - ->as(DataType::text()) - ->notNull() - ->check("VALUE ~ '^.+@.+\$'"); - - $this->assertCreateDomainQuery( - $builder, - "CREATE DOMAIN email AS pg_catalog.text NOT NULL CHECK (value ~ '^.+@.+\$')" - ); - } - - public function test_create_domain_with_named_constraint() : void - { - $builder = create()->domain('positive_int') - ->as(DataType::integer()) - ->constraint('positive_check') - ->check('VALUE > 0'); - - $this->assertCreateDomainQuery( - $builder, - 'CREATE DOMAIN positive_int AS int CONSTRAINT positive_check CHECK (value > 0)' - ); - } - - public function test_create_domain_with_not_null() : void - { - $builder = create()->domain('email') - ->as(DataType::text()) - ->notNull(); - - $this->assertCreateDomainQuery( - $builder, - 'CREATE DOMAIN email AS pg_catalog.text NOT NULL' - ); - } - - public function test_create_domain_with_null() : void - { - $builder = create()->domain('email') - ->as(DataType::text()) - ->null(); - - $this->assertCreateDomainQuery( - $builder, - 'CREATE DOMAIN email AS pg_catalog.text NULL' - ); - } - - public function test_create_domain_with_schema() : void - { - $builder = create()->domain('public.email') - ->as(DataType::text()); - - $this->assertCreateDomainQuery( - $builder, - 'CREATE DOMAIN public.email AS pg_catalog.text' - ); - } - - public function test_drop_domain_cascade() : void - { - $builder = drop()->domain('email') - ->cascade(); - - $this->assertDropDomainQuery( - $builder, - 'DROP DOMAIN email CASCADE' - ); - } - - public function test_drop_domain_if_exists() : void - { - $builder = drop()->domain('email') - ->ifExists(); - - $this->assertDropDomainQuery( - $builder, - 'DROP DOMAIN IF EXISTS email' - ); - } - - public function test_drop_domain_if_exists_cascade() : void - { - $builder = drop()->domain('email') - ->ifExists() - ->cascade(); - - $this->assertDropDomainQuery( - $builder, - 'DROP DOMAIN IF EXISTS email CASCADE' - ); - } - - public function test_drop_domain_multiple() : void - { - $builder = drop()->domain('email', 'phone', 'url'); - - $this->assertDropDomainQuery( - $builder, - 'DROP DOMAIN email, phone, url' - ); - } - - public function test_drop_domain_restrict() : void - { - $builder = drop()->domain('email') - ->restrict(); - - $this->assertDropDomainQuery( - $builder, - 'DROP DOMAIN email' - ); - } - - public function test_drop_domain_simple() : void - { - $builder = drop()->domain('email'); - - $this->assertDropDomainQuery( - $builder, - 'DROP DOMAIN email' - ); - } -} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/ExtensionBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/ExtensionBuilderTest.php deleted file mode 100644 index 724effa096..0000000000 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/ExtensionBuilderTest.php +++ /dev/null @@ -1,209 +0,0 @@ -extension('postgis') - ->addFunction('st_distance'); - - $this->assertAlterExtensionQuery( - $builder, - 'ALTER EXTENSION postgis ADD FUNCTION st_distance' - ); - } - - public function test_alter_extension_add_table() : void - { - $builder = alter()->extension('postgis') - ->addTable('spatial_ref_sys'); - - $this->assertAlterExtensionQuery( - $builder, - 'ALTER EXTENSION postgis ADD TABLE spatial_ref_sys' - ); - } - - public function test_alter_extension_drop_function() : void - { - $builder = alter()->extension('postgis') - ->dropFunction('st_distance'); - - $this->assertAlterExtensionQuery( - $builder, - 'ALTER EXTENSION postgis DROP FUNCTION st_distance' - ); - } - - public function test_alter_extension_drop_table() : void - { - $builder = alter()->extension('postgis') - ->dropTable('spatial_ref_sys'); - - $this->assertAlterExtensionQuery( - $builder, - 'ALTER EXTENSION postgis DROP TABLE spatial_ref_sys' - ); - } - - public function test_alter_extension_update() : void - { - $builder = alter()->extension('postgis') - ->update(); - - $this->assertAlterExtensionQuery( - $builder, - 'ALTER EXTENSION postgis UPDATE' - ); - } - - public function test_alter_extension_update_to() : void - { - $builder = alter()->extension('postgis') - ->updateTo('3.1'); - - $this->assertAlterExtensionQuery( - $builder, - 'ALTER EXTENSION postgis UPDATE TO "3.1"' - ); - } - - public function test_create_extension_full() : void - { - $builder = create()->extension('postgis') - ->ifNotExists() - ->schema('public') - ->version('3.0') - ->cascade(); - - $this->assertCreateExtensionQuery( - $builder, - 'CREATE EXTENSION IF NOT EXISTS postgis SCHEMA public VERSION "3.0" CASCADE' - ); - } - - public function test_create_extension_if_not_exists() : void - { - $builder = create()->extension('postgis') - ->ifNotExists(); - - $this->assertCreateExtensionQuery( - $builder, - 'CREATE EXTENSION IF NOT EXISTS postgis' - ); - } - - public function test_create_extension_simple() : void - { - $builder = create()->extension('uuid-ossp'); - - $this->assertCreateExtensionQuery( - $builder, - 'CREATE EXTENSION "uuid-ossp"' - ); - } - - public function test_create_extension_with_cascade() : void - { - $builder = create()->extension('postgis') - ->cascade(); - - $this->assertCreateExtensionQuery( - $builder, - 'CREATE EXTENSION postgis CASCADE' - ); - } - - public function test_create_extension_with_schema() : void - { - $builder = create()->extension('postgis') - ->schema('public'); - - $this->assertCreateExtensionQuery( - $builder, - 'CREATE EXTENSION postgis SCHEMA public' - ); - } - - public function test_create_extension_with_version() : void - { - $builder = create()->extension('postgis') - ->version('3.0'); - - $this->assertCreateExtensionQuery( - $builder, - 'CREATE EXTENSION postgis VERSION "3.0"' - ); - } - - public function test_drop_extension_cascade() : void - { - $builder = drop()->extension('postgis') - ->cascade(); - - $this->assertDropExtensionQuery( - $builder, - 'DROP EXTENSION postgis CASCADE' - ); - } - - public function test_drop_extension_if_exists() : void - { - $builder = drop()->extension('postgis') - ->ifExists(); - - $this->assertDropExtensionQuery( - $builder, - 'DROP EXTENSION IF EXISTS postgis' - ); - } - - public function test_drop_extension_if_exists_cascade() : void - { - $builder = drop()->extension('postgis') - ->ifExists() - ->cascade(); - - $this->assertDropExtensionQuery( - $builder, - 'DROP EXTENSION IF EXISTS postgis CASCADE' - ); - } - - public function test_drop_extension_multiple() : void - { - $builder = drop()->extension('postgis', 'pg_trgm', 'uuid-ossp'); - - $this->assertDropExtensionQuery( - $builder, - 'DROP EXTENSION postgis, pg_trgm, "uuid-ossp"' - ); - } - - public function test_drop_extension_restrict() : void - { - $builder = drop()->extension('postgis') - ->restrict(); - - $this->assertDropExtensionQuery( - $builder, - 'DROP EXTENSION postgis' - ); - } - - public function test_drop_extension_simple() : void - { - $builder = drop()->extension('postgis'); - - $this->assertDropExtensionQuery( - $builder, - 'DROP EXTENSION postgis' - ); - } -} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/InsertBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/InsertBuilderTest.php deleted file mode 100644 index f6b613f0a4..0000000000 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/InsertBuilderTest.php +++ /dev/null @@ -1,207 +0,0 @@ -into('users') - ->columns('email', 'name', 'active') - ->values(literal('john@example.com'), literal('John'), literal(true)) - ->onConflictDoUpdate( - conflict_columns(['email']), - ['name' => literal('Updated John')] - ) - ->where(eq(col('users.active'), literal(true))); - - $this->assertInsertQueryRoundTrip( - $query, - "INSERT INTO users (email, name, active) VALUES ('john@example.com', 'John', true) ON CONFLICT (email) DO UPDATE SET name = 'Updated John' WHERE users.active = true" - ); - } - - public function test_insert_on_conflict_on_constraint() : void - { - $query = insert() - ->into('users') - ->columns('name', 'email') - ->values(literal('John'), literal('john@example.com')) - ->onConflictDoNothing(conflict_constraint('users_pkey')); - - $this->assertInsertQueryRoundTrip( - $query, - "INSERT INTO users (name, email) VALUES ('John', 'john@example.com') ON CONFLICT ON CONSTRAINT users_pkey DO NOTHING" - ); - } - - public function test_insert_select() : void - { - $selectQuery = select() - ->select(col('name'), col('email')) - ->from(table('archived_users')); - - $query = insert() - ->into('users') - ->columns('name', 'email') - ->select($selectQuery); - - $this->assertInsertQueryRoundTrip( - $query, - 'INSERT INTO users (name, email) SELECT name, email FROM archived_users' - ); - } - - public function test_insert_with_default_values() : void - { - $query = insert() - ->into('users') - ->defaultValues(); - - $this->assertInsertQueryRoundTrip( - $query, - 'INSERT INTO users DEFAULT VALUES' - ); - } - - public function test_insert_with_multiple_rows() : void - { - $query = insert() - ->into('users') - ->columns('name', 'email') - ->values(literal('John'), literal('john@example.com')) - ->values(literal('Jane'), literal('jane@example.com')); - - $this->assertInsertQueryRoundTrip( - $query, - "INSERT INTO users (name, email) VALUES ('John', 'john@example.com'), ('Jane', 'jane@example.com')" - ); - } - - public function test_insert_with_on_conflict_do_nothing() : void - { - $query = insert() - ->into('users') - ->columns('name', 'email') - ->values(literal('John'), literal('john@example.com')) - ->onConflictDoNothing(); - - $this->assertInsertQueryRoundTrip( - $query, - "INSERT INTO users (name, email) VALUES ('John', 'john@example.com') ON CONFLICT DO NOTHING" - ); - } - - public function test_insert_with_on_conflict_do_update() : void - { - $query = insert() - ->into('users') - ->columns('email', 'name') - ->values(literal('john@example.com'), literal('John')) - ->onConflictDoUpdate( - conflict_columns(['email']), - ['name' => literal('Updated John')] - ); - - $this->assertInsertQueryRoundTrip( - $query, - "INSERT INTO users (email, name) VALUES ('john@example.com', 'John') ON CONFLICT (email) DO UPDATE SET name = 'Updated John'" - ); - } - - public function test_insert_with_on_conflict_on_columns_do_nothing() : void - { - $query = insert() - ->into('users') - ->columns('name', 'email') - ->values(literal('John'), literal('john@example.com')) - ->onConflictDoNothing(conflict_columns(['email'])); - - $this->assertInsertQueryRoundTrip( - $query, - "INSERT INTO users (name, email) VALUES ('John', 'john@example.com') ON CONFLICT (email) DO NOTHING" - ); - } - - public function test_insert_with_parameters() : void - { - $query = insert() - ->into('users') - ->columns('name', 'email') - ->values(param(1), param(2)); - - $this->assertInsertQueryRoundTrip( - $query, - 'INSERT INTO users (name, email) VALUES ($1, $2)' - ); - } - - public function test_insert_with_returning() : void - { - $query = insert() - ->into('users') - ->columns('name') - ->values(literal('John')) - ->returning(col('id')); - - $this->assertInsertQueryRoundTrip( - $query, - "INSERT INTO users (name) VALUES ('John') RETURNING id" - ); - } - - public function test_insert_with_returning_all() : void - { - $query = insert() - ->into('users') - ->columns('name') - ->values(literal('John')) - ->returningAll(); - - $this->assertInsertQueryRoundTrip( - $query, - "INSERT INTO users (name) VALUES ('John') RETURNING *" - ); - } - - public function test_insert_with_schema_qualified_table() : void - { - $query = insert() - ->into('public.users') - ->columns('name') - ->values(literal('John')); - - $this->assertInsertQueryRoundTrip( - $query, - "INSERT INTO public.users (name) VALUES ('John')" - ); - } - - public function test_simple_insert_with_values() : void - { - $query = insert() - ->into('users') - ->columns('name', 'email') - ->values(literal('John'), literal('john@example.com')); - - $this->assertInsertQueryRoundTrip( - $query, - "INSERT INTO users (name, email) VALUES ('John', 'john@example.com')" - ); - } -} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/MergeBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/MergeBuilderTest.php deleted file mode 100644 index 446dc01c24..0000000000 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/MergeBuilderTest.php +++ /dev/null @@ -1,234 +0,0 @@ -using('source', 's') - ->on(eq(col('target.id'), col('s.id'))) - ->whenMatched() - ->thenUpdate([ - 'value' => col('s.value'), - ]); - - $this->assertMergeQueryEquals( - $query, - 'MERGE INTO target USING source s ON target.id = s.id WHEN MATCHED THEN UPDATE SET value = s.value' - ); - } - - public function test_merge_using_subquery() : void - { - $sourceQuery = select() - ->select(col('id'), col('name'), col('email')) - ->from(table('staged_data')); - - $query = merge('users') - ->using($sourceQuery, 'src') - ->on(eq(col('users.id'), col('src.id'))) - ->whenMatched() - ->thenUpdate([ - 'name' => col('src.name'), - 'email' => col('src.email'), - ]); - - $this->assertMergeQueryEquals( - $query, - 'MERGE INTO users USING (SELECT id, name, email FROM staged_data) src ON users.id = src.id WHEN MATCHED THEN UPDATE SET name = src.name, email = src.email' - ); - } - - public function test_merge_when_not_matched_do_nothing() : void - { - $query = merge('target') - ->using('source', 's') - ->on(eq(col('target.id'), col('s.id'))) - ->whenNotMatched() - ->thenDoNothing(); - - $this->assertMergeQueryEquals( - $query, - 'MERGE INTO target USING source s ON target.id = s.id WHEN NOT MATCHED THEN DO NOTHING' - ); - } - - public function test_merge_with_conditional_when_matched() : void - { - $query = merge('products', 'p') - ->using('price_updates', 'pu') - ->on(eq(col('p.id'), col('pu.product_id'))) - ->whenMatchedAnd(gt(col('pu.price'), literal(0))) - ->thenUpdate([ - 'price' => col('pu.price'), - ]); - - $this->assertMergeQueryEquals( - $query, - 'MERGE INTO products p USING price_updates pu ON p.id = pu.product_id WHEN MATCHED AND pu.price > 0 THEN UPDATE SET price = pu.price' - ); - } - - public function test_merge_with_cte() : void - { - $stagedData = select() - ->select(col('id'), col('name')) - ->from(table('raw_input')); - - $query = with(cte('staged_data', $stagedData))->merge('users') - ->using('staged_data', 's') - ->on(eq(col('users.id'), col('s.id'))) - ->whenMatched() - ->thenUpdate([ - 'name' => col('s.name'), - ]); - - $this->assertMergeQueryEquals( - $query, - 'WITH staged_data AS (SELECT id, name FROM raw_input) MERGE INTO users USING staged_data s ON users.id = s.id WHEN MATCHED THEN UPDATE SET name = s.name' - ); - } - - public function test_merge_with_delete() : void - { - $query = merge('target_table', 't') - ->using('source_table', 's') - ->on(eq(col('t.id'), col('s.id'))) - ->whenMatched() - ->thenDelete(); - - $this->assertMergeQueryEquals( - $query, - 'MERGE INTO target_table t USING source_table s ON t.id = s.id WHEN MATCHED THEN DELETE' - ); - } - - public function test_merge_with_do_nothing() : void - { - $query = merge('products') - ->using('updates', 'u') - ->on(eq(col('products.id'), col('u.id'))) - ->whenMatched() - ->thenDoNothing(); - - $this->assertMergeQueryEquals( - $query, - 'MERGE INTO products USING updates u ON products.id = u.id WHEN MATCHED THEN DO NOTHING' - ); - } - - public function test_merge_with_insert() : void - { - $query = merge('customers') - ->using('new_customers', 'nc') - ->on(eq(col('customers.id'), col('nc.id'))) - ->whenNotMatched() - ->thenInsert( - ['id', 'name', 'email'], - [col('nc.id'), col('nc.name'), col('nc.email')] - ); - - $this->assertMergeQueryEquals( - $query, - 'MERGE INTO customers USING new_customers nc ON customers.id = nc.id WHEN NOT MATCHED THEN INSERT (id, name, email) VALUES (nc.id, nc.name, nc.email)' - ); - } - - public function test_merge_with_insert_values() : void - { - $query = merge('users') - ->using('new_users', 'n') - ->on(eq(col('users.id'), col('n.id'))) - ->whenNotMatched() - ->thenInsertValues([ - 'id' => col('n.id'), - 'name' => col('n.name'), - 'status' => literal('active'), - ]); - - $this->assertMergeQueryEquals( - $query, - "MERGE INTO users USING new_users n ON users.id = n.id WHEN NOT MATCHED THEN INSERT (id, name, status) VALUES (n.id, n.name, 'active')" - ); - } - - public function test_merge_with_multiple_when_clauses() : void - { - $query = merge('inventory', 'i') - ->using('updates', 'u') - ->on(eq(col('i.product_id'), col('u.product_id'))) - ->whenMatched() - ->thenUpdate([ - 'quantity' => col('u.quantity'), - 'updated_at' => col('u.updated_at'), - ]) - ->whenNotMatched() - ->thenInsert( - ['product_id', 'quantity'], - [col('u.product_id'), col('u.quantity')] - ); - - $this->assertMergeQueryEquals( - $query, - 'MERGE INTO inventory i USING updates u ON i.product_id = u.product_id WHEN MATCHED THEN UPDATE SET quantity = u.quantity, updated_at = u.updated_at WHEN NOT MATCHED THEN INSERT (product_id, quantity) VALUES (u.product_id, u.quantity)' - ); - } - - public function test_merge_with_parameters() : void - { - $query = merge('accounts') - ->using('transactions', 't') - ->on(eq(col('accounts.id'), col('t.account_id'))) - ->whenMatched() - ->thenUpdate([ - 'balance' => param(1), - ]); - - $this->assertMergeQueryEquals( - $query, - 'MERGE INTO accounts USING transactions t ON accounts.id = t.account_id WHEN MATCHED THEN UPDATE SET balance = $1' - ); - } - - protected function assertMergeQueryEquals(MergeFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseMergeStmt($builder->toAst()); - - self::assertSame($expectedSql, $sql); - } - - protected function deparseMergeStmt(MergeStmt $mergeStmt) : string - { - $node = new Node(); - $node->setMergeStmt($mergeStmt); - - $parser = new Parser(); - $rawStmt = new RawStmt(['stmt' => $node]); - $parsed = $parser->parse('SELECT 1'); - $parseResult = $parsed->raw(); - $parseResult->setStmts([$rawStmt]); - - return (new ParsedQuery($parseResult))->deparse(); - } -} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/PGQueryTestCase.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/PGQueryTestCase.php deleted file mode 100644 index f7c7d72bab..0000000000 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/PGQueryTestCase.php +++ /dev/null @@ -1,20 +0,0 @@ -role('old_name') - ->renameTo('new_name'); - - $this->assertAlterRoleRenameQuery( - $builder, - 'ALTER ROLE old_name RENAME TO new_name' - ); - } - - public function test_alter_role_set_options() : void - { - $builder = alter()->role('admin') - ->superuser(); - - $this->assertAlterRoleQuery( - $builder, - 'ALTER ROLE admin WITH SUPERUSER' - ); - } - - public function test_alter_role_with_multiple_options() : void - { - $builder = alter()->role('admin') - ->noSuperuser() - ->createDb(); - - $this->assertAlterRoleQuery( - $builder, - 'ALTER ROLE admin WITH NOSUPERUSER CREATEDB' - ); - } - - public function test_create_role_simple() : void - { - $builder = create()->role('admin'); - - $this->assertCreateRoleQuery( - $builder, - 'CREATE ROLE admin' - ); - } - - public function test_create_role_with_login() : void - { - $builder = create()->role('app_user') - ->login(); - - $this->assertCreateRoleQuery( - $builder, - 'CREATE ROLE app_user WITH LOGIN' - ); - } - - public function test_create_role_with_options() : void - { - $builder = create()->role('admin') - ->superuser() - ->login(); - - $this->assertCreateRoleQuery( - $builder, - 'CREATE ROLE admin WITH SUPERUSER LOGIN' - ); - } - - public function test_create_user_with_password() : void - { - $builder = create()->role('app_user') - ->login() - ->withPassword('secret'); - - $this->assertCreateRoleQuery( - $builder, - "CREATE ROLE app_user WITH LOGIN PASSWORD 'secret'" - ); - } - - public function test_drop_owned_by() : void - { - $builder = drop()->owned('role1'); - - $this->assertDropOwnedQuery( - $builder, - 'DROP OWNED BY role1' - ); - } - - public function test_drop_owned_by_cascade() : void - { - $builder = drop()->owned('role1') - ->cascade(); - - $this->assertDropOwnedQuery( - $builder, - 'DROP OWNED BY role1 CASCADE' - ); - } - - public function test_drop_role_if_exists() : void - { - $builder = drop()->role('admin') - ->ifExists(); - - $this->assertDropRoleQuery( - $builder, - 'DROP ROLE IF EXISTS admin' - ); - } - - public function test_drop_role_multiple() : void - { - $builder = drop()->role('role1', 'role2'); - - $this->assertDropRoleQuery( - $builder, - 'DROP ROLE role1, role2' - ); - } - - public function test_drop_role_simple() : void - { - $builder = drop()->role('admin'); - - $this->assertDropRoleQuery( - $builder, - 'DROP ROLE admin' - ); - } - - public function test_grant_all_on_table() : void - { - $builder = grant(TablePrivilege::ALL) - ->onTable('users') - ->to('admin'); - - $this->assertGrantQuery( - $builder, - 'GRANT ALL ON users TO admin' - ); - } - - public function test_grant_on_all_tables_in_schema() : void - { - $builder = grant(TablePrivilege::SELECT) - ->onAllTablesInSchema('public') - ->to('admin'); - - $this->assertGrantQuery( - $builder, - 'GRANT select ON ALL TABLES IN SCHEMA public TO admin' - ); - } - - public function test_grant_role_to_role() : void - { - $builder = grant_role('admin') - ->to('user1'); - - $this->assertGrantRoleQuery( - $builder, - 'GRANT admin TO user1' - ); - } - - public function test_grant_role_with_admin_option() : void - { - $builder = grant_role('admin') - ->to('user1') - ->withAdminOption(); - - $this->assertGrantRoleQuery( - $builder, - 'GRANT admin TO user1 WITH ADMIN OPTION' - ); - } - - public function test_grant_select_on_table() : void - { - $builder = grant(TablePrivilege::SELECT) - ->onTable('users') - ->to('app_user'); - - $this->assertGrantQuery( - $builder, - 'GRANT select ON users TO app_user' - ); - } - - public function test_grant_with_grant_option() : void - { - $builder = grant(TablePrivilege::SELECT) - ->onTable('users') - ->to('app_user') - ->withGrantOption(); - - $this->assertGrantQuery( - $builder, - 'GRANT select ON users TO app_user WITH GRANT OPTION' - ); - } - - public function test_reassign_owned_by() : void - { - $builder = reassign_owned('old_role') - ->to('new_role'); - - $this->assertReassignOwnedQuery( - $builder, - 'REASSIGN OWNED BY old_role TO new_role' - ); - } - - public function test_reset_role() : void - { - $builder = reset_role(); - - $this->assertResetRoleQuery( - $builder, - 'RESET role' - ); - } - - public function test_revoke_role_cascade() : void - { - $builder = revoke_role('admin') - ->from('user1') - ->cascade(); - - $this->assertRevokeRoleQuery( - $builder, - 'REVOKE admin FROM user1 CASCADE' - ); - } - - public function test_revoke_role_from_role() : void - { - $builder = revoke_role('admin') - ->from('user1'); - - $this->assertRevokeRoleQuery( - $builder, - 'REVOKE admin FROM user1' - ); - } - - public function test_revoke_select_on_table() : void - { - $builder = revoke(TablePrivilege::SELECT) - ->onTable('users') - ->from('app_user'); - - $this->assertRevokeQuery( - $builder, - 'REVOKE select ON users FROM app_user' - ); - } - - public function test_revoke_with_cascade() : void - { - $builder = revoke(TablePrivilege::SELECT) - ->onTable('users') - ->from('app_user') - ->cascade(); - - $this->assertRevokeQuery( - $builder, - 'REVOKE select ON users FROM app_user CASCADE' - ); - } - - public function test_set_role() : void - { - $builder = set_role('admin'); - - $this->assertSetRoleQuery( - $builder, - 'SET role TO admin' - ); - } -} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/SchemaBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/SchemaBuilderTest.php deleted file mode 100644 index 974ec2e416..0000000000 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/SchemaBuilderTest.php +++ /dev/null @@ -1,141 +0,0 @@ -schema('my_schema') - ->ownerTo('new_owner'); - - $this->assertAlterSchemaOwnerQuery( - $builder, - 'ALTER SCHEMA my_schema OWNER TO new_owner' - ); - } - - public function test_alter_schema_rename() : void - { - $builder = alter()->schema('old_schema') - ->renameTo('new_schema'); - - $this->assertAlterSchemaRenameQuery( - $builder, - 'ALTER SCHEMA old_schema RENAME TO new_schema' - ); - } - - public function test_create_schema_if_not_exists() : void - { - $builder = create()->schema('my_schema') - ->ifNotExists(); - - $this->assertCreateSchemaQuery( - $builder, - 'CREATE SCHEMA IF NOT EXISTS my_schema' - ); - } - - public function test_create_schema_if_not_exists_with_authorization() : void - { - $builder = create()->schema('my_schema') - ->ifNotExists() - ->authorization('admin_user'); - - $this->assertCreateSchemaQuery( - $builder, - 'CREATE SCHEMA IF NOT EXISTS my_schema AUTHORIZATION admin_user' - ); - } - - public function test_create_schema_simple() : void - { - $builder = create()->schema('my_schema'); - - $this->assertCreateSchemaQuery( - $builder, - 'CREATE SCHEMA my_schema' - ); - } - - public function test_create_schema_with_authorization() : void - { - $builder = create()->schema('my_schema') - ->authorization('admin_user'); - - $this->assertCreateSchemaQuery( - $builder, - 'CREATE SCHEMA my_schema AUTHORIZATION admin_user' - ); - } - - public function test_drop_schema_cascade() : void - { - $builder = drop()->schema('my_schema') - ->cascade(); - - $this->assertDropSchemaQuery( - $builder, - 'DROP SCHEMA my_schema CASCADE' - ); - } - - public function test_drop_schema_if_exists() : void - { - $builder = drop()->schema('my_schema') - ->ifExists(); - - $this->assertDropSchemaQuery( - $builder, - 'DROP SCHEMA IF EXISTS my_schema' - ); - } - - public function test_drop_schema_if_exists_cascade() : void - { - $builder = drop()->schema('my_schema') - ->ifExists() - ->cascade(); - - $this->assertDropSchemaQuery( - $builder, - 'DROP SCHEMA IF EXISTS my_schema CASCADE' - ); - } - - public function test_drop_schema_multiple() : void - { - $builder = drop()->schema('schema1', 'schema2'); - - $this->assertDropSchemaQuery( - $builder, - 'DROP SCHEMA schema1, schema2' - ); - } - - public function test_drop_schema_restrict() : void - { - $builder = drop()->schema('my_schema') - ->restrict(); - - $this->assertDropSchemaQuery( - $builder, - 'DROP SCHEMA my_schema' - ); - } - - public function test_drop_schema_simple() : void - { - $builder = drop()->schema('my_schema'); - - $this->assertDropSchemaQuery( - $builder, - 'DROP SCHEMA my_schema' - ); - } -} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/SelectBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/SelectBuilderTest.php deleted file mode 100644 index e13c98620f..0000000000 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/SelectBuilderTest.php +++ /dev/null @@ -1,1280 +0,0 @@ -selectDistinctOn( - [col('department')], - col('name'), - col('salary') - ) - ->from(table('employees')) - ->orderBy(asc(col('department')), desc(col('salary'))); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT DISTINCT ON (department) name, salary FROM employees ORDER BY department ASC, salary DESC' - ); - } - - public function test_select_except_all() : void - { - $query1 = select() - ->select(col('id')) - ->from(table('all_users')); - - $query2 = select() - ->select(col('id')) - ->from(table('banned_users')); - - $query = $query1->exceptAll($query2); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT id FROM all_users EXCEPT ALL SELECT id FROM banned_users' - ); - } - - public function test_select_intersect_all() : void - { - $query1 = select() - ->select(col('id')) - ->from(table('users')); - - $query2 = select() - ->select(col('id')) - ->from(table('admins')); - - $query = $query1->intersectAll($query2); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT id FROM users INTERSECT ALL SELECT id FROM admins' - ); - } - - public function test_select_with_aggregates() : void - { - $query = select() - ->select( - col('category'), - agg_count(), - agg_sum(col('amount')), - agg_avg(col('price')), - agg_min(col('created_at')), - agg_max(col('updated_at')) - ) - ->from(table('orders')) - ->groupBy(col('category')); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT category, count(*), sum(amount), avg(price), min(created_at), max(updated_at) FROM orders GROUP BY category' - ); - } - - public function test_select_with_aliased_columns() : void - { - $query = select() - ->select( - col('first_name')->as('fname'), - col('last_name')->as('lname') - ) - ->from(table('users')); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT first_name AS fname, last_name AS lname FROM users' - ); - } - - public function test_select_with_all() : void - { - $subquery = select() - ->select(col('price')) - ->from(table('budget_products')); - - $query = select() - ->select(star()) - ->from(table('products')) - ->where(all_sub_select(col('price'), ComparisonOperator::GT, $subquery)); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT * FROM products WHERE price > ALL (SELECT price FROM budget_products)' - ); - } - - public function test_select_with_any() : void - { - $subquery = select() - ->select(col('price')) - ->from(table('discounted_products')); - - $query = select() - ->select(star()) - ->from(table('products')) - ->where(any_sub_select(col('price'), ComparisonOperator::GT, $subquery)); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT * FROM products WHERE price > ANY (SELECT price FROM discounted_products)' - ); - } - - public function test_select_with_array_constructor() : void - { - $query = select() - ->select(array_expr([literal(1), literal(2), literal(3)])->as('numbers')) - ->from(table('users')); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT ARRAY[1, 2, 3] AS numbers FROM users' - ); - } - - public function test_select_with_array_expression() : void - { - $query = select() - ->select(star()) - ->from(table('users')) - ->where(is_in(col('id'), [literal(1), literal(2), literal(3)])); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT * FROM users WHERE id IN (1, 2, 3)' - ); - } - - public function test_select_with_between_condition() : void - { - $query = select() - ->select(star()) - ->from(table('products')) - ->where(between(col('price'), literal(10), literal(100))); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT * FROM products WHERE price BETWEEN 10 AND 100' - ); - } - - public function test_select_with_case_expression() : void - { - $query = select() - ->select( - col('name'), - case_when([ - when(binary_expr(col('price'), '>', literal(100)), literal('expensive')), - when(binary_expr(col('price'), '>', literal(50)), literal('moderate')), - ], literal('cheap'))->as('price_category') - ) - ->from(table('products')); - - $this->assertSelectQueryRoundTrip( - $query, - "SELECT name, CASE WHEN price > 100 THEN 'expensive' WHEN price > 50 THEN 'moderate' ELSE 'cheap' END AS price_category FROM products" - ); - } - - public function test_select_with_coalesce() : void - { - $query = select() - ->select( - col('id'), - coalesce( - col('nickname'), - col('name'), - literal('Anonymous') - )->as('display_name') - ) - ->from(table('users')); - - $this->assertSelectQueryRoundTrip( - $query, - "SELECT id, COALESCE(nickname, name, 'Anonymous') AS display_name FROM users" - ); - } - - public function test_select_with_complex_and_or_conditions() : void - { - $query = select() - ->select(star()) - ->from(table('users')) - ->where( - cond_and( - eq(col('status'), literal('active')), - cond_or( - gte(col('age'), literal(18)), - eq(col('guardian_approved'), literal(true)) - ) - ) - ); - - $this->assertSelectQueryRoundTrip( - $query, - "SELECT * FROM users WHERE status = 'active' AND (age >= 18 OR guardian_approved = true)" - ); - } - - public function test_select_with_cross_join() : void - { - $query = select() - ->select(star()) - ->from(table('colors')) - ->crossJoin(table('sizes')); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT * FROM colors CROSS JOIN sizes' - ); - } - - public function test_select_with_cte() : void - { - $query = with( - cte( - 'active_users', - select() - ->select(col('id'), col('name')) - ->from(table('users')) - ->where(eq(col('active'), literal(true))) - ) - ) - ->select(star()) - ->from(table('active_users')); - - $this->assertSelectQueryRoundTrip( - $query, - 'WITH active_users AS (SELECT id, name FROM users WHERE active = true) SELECT * FROM active_users' - ); - } - - public function test_select_with_cte_materialized() : void - { - $cteQuery = select() - ->select(col('id'), col('name')) - ->from(table('users')) - ->where(eq(col('active'), literal(true))); - - $query = with(cte('active_users', $cteQuery, [], CTEMaterialization::MATERIALIZED)) - ->select(star()) - ->from(table('active_users')); - - $this->assertSelectQueryRoundTrip( - $query, - 'WITH active_users AS MATERIALIZED (SELECT id, name FROM users WHERE active = true) SELECT * FROM active_users' - ); - } - - public function test_select_with_cte_not_materialized() : void - { - $cteQuery = select() - ->select(col('id'), col('name')) - ->from(table('users')) - ->where(eq(col('active'), literal(true))); - - $query = with(cte('active_users', $cteQuery, [], CTEMaterialization::NOT_MATERIALIZED)) - ->select(star()) - ->from(table('active_users')); - - $this->assertSelectQueryRoundTrip( - $query, - 'WITH active_users AS NOT MATERIALIZED (SELECT id, name FROM users WHERE active = true) SELECT * FROM active_users' - ); - } - - public function test_select_with_derived_table() : void - { - $subquery = select() - ->select(col('user_id'), agg_sum(col('amount'))->as('total')) - ->from(table('orders')) - ->groupBy(col('user_id')); - - $query = select() - ->select(col('u.name'), col('o.total')) - ->from(table('users')->as('u')) - ->leftJoin( - derived($subquery, 'o'), - eq(col('u.id'), col('o.user_id')) - ); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT u.name, o.total FROM users u LEFT JOIN (SELECT user_id, sum(amount) AS total FROM orders GROUP BY user_id) o ON u.id = o.user_id' - ); - } - - public function test_select_with_derived_table_join() : void - { - $subquery = select() - ->select(col('user_id'), agg_count()->as('order_count')) - ->from(table('orders')) - ->groupBy(col('user_id')); - - $query = select() - ->select(col('users.name'), col('order_stats.order_count')) - ->from(table('users')) - ->join( - derived($subquery, 'order_stats'), - eq(col('users.id'), col('order_stats.user_id')) - ); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT users.name, order_stats.order_count FROM users JOIN (SELECT user_id, count(*) AS order_count FROM orders GROUP BY user_id) order_stats ON users.id = order_stats.user_id' - ); - } - - public function test_select_with_distinct() : void - { - $query = select() - ->selectDistinct(col('city')) - ->from(table('users')); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT DISTINCT city FROM users' - ); - } - - public function test_select_with_distinct_count() : void - { - $query = select() - ->select(agg_count(col('user_id'), true)->as('unique_users')) - ->from(table('orders')); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT count(DISTINCT user_id) AS unique_users FROM orders' - ); - } - - public function test_select_with_except() : void - { - $query1 = select() - ->select(col('id')) - ->from(table('all_users')); - - $query2 = select() - ->select(col('id')) - ->from(table('banned_users')); - - $query = $query1->except($query2); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT id FROM all_users EXCEPT SELECT id FROM banned_users' - ); - } - - public function test_select_with_exists() : void - { - $subquery = select() - ->select(literal(1)) - ->from(table('orders')) - ->where(eq(col('orders.user_id'), col('users.id'))); - - $query = select() - ->select(star()) - ->from(table('users')) - ->where(exists($subquery)); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT * FROM users WHERE EXISTS (SELECT 1 FROM orders WHERE orders.user_id = users.id)' - ); - } - - public function test_select_with_for_key_share() : void - { - $query = select() - ->select(star()) - ->from(table('accounts')) - ->where(eq(col('id'), literal(1))) - ->forKeyShare(); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT * FROM accounts WHERE id = 1 FOR KEY SHARE' - ); - } - - public function test_select_with_for_no_key_update() : void - { - $query = select() - ->select(star()) - ->from(table('accounts')) - ->where(eq(col('id'), literal(1))) - ->forNoKeyUpdate(); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT * FROM accounts WHERE id = 1 FOR NO KEY UPDATE' - ); - } - - public function test_select_with_for_share() : void - { - $query = select() - ->select(star()) - ->from(table('accounts')) - ->where(eq(col('id'), literal(1))) - ->forShare(); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT * FROM accounts WHERE id = 1 FOR SHARE' - ); - } - - public function test_select_with_for_update() : void - { - $query = select() - ->select(star()) - ->from(table('accounts')) - ->where(eq(col('id'), literal(1))) - ->forUpdate(); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT * FROM accounts WHERE id = 1 FOR UPDATE' - ); - } - - public function test_select_with_full_join() : void - { - $query = select() - ->select(star()) - ->from(table('table_a')->as('a')) - ->fullJoin( - table('table_b')->as('b'), - eq(col('a.key'), col('b.key')) - ); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT * FROM table_a a FULL JOIN table_b b ON a.key = b.key' - ); - } - - public function test_select_with_function_call() : void - { - $query = select() - ->select( - col('name'), - func('upper', [col('name')])->as('upper_name'), - func('length', [col('name')])->as('name_length') - ) - ->from(table('users')); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT name, upper(name) AS upper_name, length(name) AS name_length FROM users' - ); - } - - public function test_select_with_greatest() : void - { - $query = select() - ->select( - col('id'), - greatest(col('a'), col('b'), col('c'))->as('max_value') - ) - ->from(table('numbers')); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT id, GREATEST(a, b, c) AS max_value FROM numbers' - ); - } - - public function test_select_with_group_by_having() : void - { - $query = select() - ->select(col('category'), agg_count()->as('cnt')) - ->from(table('products')) - ->groupBy(col('category')) - ->having(gt(agg_count(), literal(5))); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT category, count(*) AS cnt FROM products GROUP BY category HAVING count(*) > 5' - ); - } - - public function test_select_with_in_condition() : void - { - $query = select() - ->select(star()) - ->from(table('users')) - ->where(is_in( - col('status'), - [literal('active'), literal('pending'), literal('verified')] - )); - - $this->assertSelectQueryRoundTrip( - $query, - "SELECT * FROM users WHERE status IN ('active', 'pending', 'verified')" - ); - } - - public function test_select_with_inner_join() : void - { - $query = select() - ->select(col('u.name'), col('o.total')) - ->from(table('users')->as('u')) - ->join( - table('orders')->as('o'), - eq(col('u.id'), col('o.user_id')) - ); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT u.name, o.total FROM users u JOIN orders o ON u.id = o.user_id' - ); - } - - public function test_select_with_intersect() : void - { - $query1 = select() - ->select(col('id')) - ->from(table('premium_users')); - - $query2 = select() - ->select(col('id')) - ->from(table('active_users')); - - $query = $query1->intersect($query2); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT id FROM premium_users INTERSECT SELECT id FROM active_users' - ); - } - - public function test_select_with_is_distinct_from() : void - { - $query = select() - ->select(star()) - ->from(table('users')) - ->where(is_distinct_from(col('status'), literal(null))); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT * FROM users WHERE status IS DISTINCT FROM NULL' - ); - } - - public function test_select_with_is_not_distinct_from() : void - { - $query = select() - ->select(star()) - ->from(table('users')) - ->where(is_distinct_from(col('status'), literal('active'), true)); - - $this->assertSelectQueryRoundTrip( - $query, - "SELECT * FROM users WHERE status IS NOT DISTINCT FROM 'active'" - ); - } - - public function test_select_with_is_null_condition() : void - { - $query = select() - ->select(star()) - ->from(table('users')) - ->where(is_null(col('deleted_at'))); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT * FROM users WHERE deleted_at IS NULL' - ); - } - - public function test_select_with_lateral_join() : void - { - $lateralQuery = select() - ->select(star()) - ->from(table('orders')) - ->where(eq(col('orders.user_id'), col('u.id'))) - ->orderBy(desc(col('created_at'))) - ->limit(3); - - $query = select() - ->select(col('u.name'), col('recent.id')) - ->from(table('users')->as('u')) - ->leftJoin( - lateral(derived($lateralQuery, 'recent')), - raw_cond('true') - ); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT u.name, recent.id FROM users u LEFT JOIN LATERAL (SELECT * FROM orders WHERE orders.user_id = u.id ORDER BY created_at DESC LIMIT 3) recent ON true' - ); - } - - public function test_select_with_lateral_subquery() : void - { - $subquery = select() - ->select(col('order_id')) - ->from(table('orders')) - ->where(eq(col('orders.user_id'), col('users.id'))) - ->orderBy(desc(col('created_at'))) - ->limit(5); - - $query = select() - ->select(col('users.name'), col('recent_orders.order_id')) - ->from(table('users')) - ->crossJoin(lateral(derived($subquery, 'recent_orders'))); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT users.name, recent_orders.order_id FROM users CROSS JOIN LATERAL (SELECT order_id FROM orders WHERE orders.user_id = users.id ORDER BY created_at DESC LIMIT 5) recent_orders' - ); - } - - public function test_select_with_least() : void - { - $query = select() - ->select( - col('id'), - least(col('a'), col('b'), col('c'))->as('min_value') - ) - ->from(table('numbers')); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT id, LEAST(a, b, c) AS min_value FROM numbers' - ); - } - - public function test_select_with_left_join() : void - { - $query = select() - ->select(col('u.name'), col('o.total')) - ->from(table('users')->as('u')) - ->leftJoin( - table('orders')->as('o'), - eq(col('u.id'), col('o.user_id')) - ); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT u.name, o.total FROM users u LEFT JOIN orders o ON u.id = o.user_id' - ); - } - - public function test_select_with_like_condition() : void - { - $query = select() - ->select(star()) - ->from(table('users')) - ->where(like(col('email'), literal('%@example.com'))); - - $this->assertSelectQueryRoundTrip( - $query, - "SELECT * FROM users WHERE email LIKE '%@example.com'" - ); - } - - public function test_select_with_limit_offset() : void - { - $query = select() - ->select(star()) - ->from(table('users')) - ->orderBy(asc(col('id'))) - ->limit(10) - ->offset(20); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT * FROM users ORDER BY id ASC LIMIT 10 OFFSET 20' - ); - } - - public function test_select_with_multiple_conditions() : void - { - $query = select() - ->select(star()) - ->from(table('users')) - ->where( - cond_and( - eq(col('active'), literal(true)), - gte(col('age'), literal(18)), - neq(col('status'), literal('banned')) - ) - ); - - $this->assertSelectQueryRoundTrip( - $query, - "SELECT * FROM users WHERE active = true AND age >= 18 AND status <> 'banned'" - ); - } - - public function test_select_with_not_condition() : void - { - $query = select() - ->select(star()) - ->from(table('users')) - ->where(cond_not(eq(col('status'), literal('banned')))); - - $this->assertSelectQueryRoundTrip( - $query, - "SELECT * FROM users WHERE NOT status = 'banned'" - ); - } - - public function test_select_with_nullif() : void - { - $query = select() - ->select( - col('id'), - nullif(col('value'), literal(0))->as('safe_value') - ) - ->from(table('data')); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT id, NULLIF(value, 0) AS safe_value FROM data' - ); - } - - public function test_select_with_order_by_asc_desc() : void - { - $query = select() - ->select(star()) - ->from(table('users')) - ->orderBy( - asc(col('last_name')), - desc(col('first_name')) - ); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT * FROM users ORDER BY last_name ASC, first_name DESC' - ); - } - - public function test_select_with_order_by_nulls_first_last() : void - { - $query = select() - ->select(star()) - ->from(table('products')) - ->orderBy( - order_by(col('price'), SortDirection::ASC, NullsPosition::FIRST), - order_by(col('name'), SortDirection::DESC, NullsPosition::LAST) - ); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT * FROM products ORDER BY price ASC NULLS FIRST, name DESC NULLS LAST' - ); - } - - public function test_select_with_parameter() : void - { - $query = select() - ->select(star()) - ->from(table('users')) - ->where(eq(col('id'), param(1))); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT * FROM users WHERE id = $1' - ); - } - - public function test_select_with_raw_expression() : void - { - $query = select() - ->select( - star(), - binary_expr(literal(1), '+', literal(1))->as('calculated') - ) - ->from(table('users')); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT *, 1 + 1 AS calculated FROM users' - ); - } - - public function test_select_with_raw_expression_in_select() : void - { - $query = select() - ->select( - col('id'), - raw_expr('1 + 1')->as('two') - ) - ->from(table('users')); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT id, 1 + 1 AS two FROM users' - ); - } - - public function test_select_with_recursive_cte_window_functions_and_case_expression() : void - { - $orgTreeAnchor = select() - ->select( - col('id'), - col('name'), - col('manager_id'), - literal(0)->as('level'), - cast(col('name'), data_type_text())->as('path') - ) - ->from(table('employees')) - ->where(is_null(col('manager_id'))); - - $orgTreeRecursive = select() - ->select( - col('e.id'), - col('e.name'), - col('e.manager_id'), - binary_expr(col('org_tree.level'), '+', literal(1)), - binary_expr( - binary_expr(col('org_tree.path'), '||', literal(' -> ')), - '||', - col('e.name') - ) - ) - ->from(table('employees')->as('e')) - ->join(table('org_tree'), eq(col('e.manager_id'), col('org_tree.id'))); - - $orgTreeQuery = $orgTreeAnchor->unionAll($orgTreeRecursive); - - $deptStats = select() - ->select( - col('department_id'), - agg_avg(col('salary')), - agg_max(col('salary')), - agg_count() - ) - ->from(table('employees')) - ->groupBy(col('department_id')); - - $rankedEmployees = select() - ->select( - col('e.id'), - col('e.name'), - col('e.department_id'), - col('e.salary'), - window_func( - 'row_number', - [], - [col('e.department_id')], - [desc(col('e.salary'))] - ), - func('round', [ - binary_expr( - binary_expr(col('e.salary'), '/', col('ds.max_salary')), - '*', - literal(100) - ), - literal(2), - ]) - ) - ->from(table('employees')->as('e')) - ->join( - table('dept_stats')->as('ds'), - eq(col('e.department_id'), col('ds.department_id')) - ); - - $query = with( - cte('org_tree', $orgTreeQuery, ['id', 'name', 'manager_id', 'level', 'path']), - cte('dept_stats', $deptStats, ['department_id', 'avg_salary', 'max_salary', 'employee_count']), - cte( - 'ranked_employees', - $rankedEmployees, - ['id', 'name', 'department_id', 'salary', 'salary_rank', 'pct_of_max'] - ) - ) - ->recursive() - ->select( - col('org_tree.name')->as('employee'), - col('org_tree.level'), - col('org_tree.path')->as('reporting_chain'), - col('d.name')->as('department'), - col('re.salary'), - col('re.salary_rank'), - col('re.pct_of_max'), - col('ds.avg_salary')->as('dept_avg'), - case_when([ - when( - binary_expr(col('re.salary'), '>', col('ds.avg_salary')), - literal('Above Average') - ), - ], literal('At/Below Average'))->as('salary_status') - ) - ->from(table('org_tree')) - ->join(table('ranked_employees')->as('re'), eq(col('org_tree.id'), col('re.id'))) - ->join( - table('dept_stats')->as('ds'), - eq(col('re.department_id'), col('ds.department_id')) - ) - ->join(table('departments')->as('d'), eq(col('re.department_id'), col('d.id'))) - ->where(cond_and( - lte(col('org_tree.level'), literal(3)), - lte(col('re.salary_rank'), literal(5)) - )) - ->orderBy( - asc(col('org_tree.level')), - asc(col('d.name')), - desc(col('re.salary')) - ); - - $expectedSql = <<<'SQL' - WITH RECURSIVE org_tree(id, name, manager_id, level, path) AS (SELECT id, name, manager_id, 0 AS level, name::pg_catalog.text AS path FROM employees WHERE manager_id IS NULL UNION ALL SELECT e.id, e.name, e.manager_id, org_tree.level + 1, (org_tree.path || ' -> ') || e.name FROM employees e JOIN org_tree ON e.manager_id = org_tree.id), dept_stats(department_id, avg_salary, max_salary, employee_count) AS (SELECT department_id, avg(salary), max(salary), count(*) FROM employees GROUP BY department_id), ranked_employees(id, name, department_id, salary, salary_rank, pct_of_max) AS (SELECT e.id, e.name, e.department_id, e.salary, row_number() OVER (PARTITION BY e.department_id ORDER BY e.salary DESC), round((e.salary / ds.max_salary) * 100, 2) FROM employees e JOIN dept_stats ds ON e.department_id = ds.department_id) SELECT org_tree.name AS employee, org_tree.level, org_tree.path AS reporting_chain, d.name AS department, re.salary, re.salary_rank, re.pct_of_max, ds.avg_salary AS dept_avg, CASE WHEN re.salary > ds.avg_salary THEN 'Above Average' ELSE 'At/Below Average' END AS salary_status FROM org_tree JOIN ranked_employees re ON org_tree.id = re.id JOIN dept_stats ds ON re.department_id = ds.department_id JOIN departments d ON re.department_id = d.id WHERE org_tree.level <= 3 AND re.salary_rank <= 5 ORDER BY org_tree.level ASC, d.name ASC, re.salary DESC - SQL; - - $this->assertSelectQueryRoundTrip($query, $expectedSql); - } - - public function test_select_with_right_join() : void - { - $query = select() - ->select(star()) - ->from(table('orders')->as('o')) - ->rightJoin( - table('users')->as('u'), - eq(col('o.user_id'), col('u.id')) - ); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT * FROM orders o RIGHT JOIN users u ON o.user_id = u.id' - ); - } - - public function test_select_with_row_expression() : void - { - $query = select() - ->select(star()) - ->from(table('users')) - ->where( - eq( - row_expr([col('first_name'), col('last_name')]), - row_expr([literal('John'), literal('Doe')]) - ) - ); - - $this->assertSelectQueryRoundTrip( - $query, - "SELECT * FROM users WHERE (first_name, last_name) = ('John', 'Doe')" - ); - } - - public function test_select_with_scalar_subquery() : void - { - $subquery = select() - ->select(agg_count()) - ->from(table('orders')) - ->where(eq(col('orders.user_id'), col('users.id'))); - - $query = select() - ->select( - col('name'), - sub_select($subquery)->as('order_count') - ) - ->from(table('users')); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT name, (SELECT count(*) FROM orders WHERE orders.user_id = users.id) AS order_count FROM users' - ); - } - - public function test_select_with_schema_qualified_table() : void - { - $query = select() - ->select(star()) - ->from(table('users', 'public')); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT * FROM public.users' - ); - } - - public function test_select_with_similar_to() : void - { - $query = select() - ->select(star()) - ->from(table('users')) - ->where(similar_to(col('name'), literal('%John%'))); - - $this->assertSelectQueryRoundTrip( - $query, - "SELECT * FROM users WHERE name SIMILAR TO '%John%'" - ); - } - - public function test_select_with_table_function() : void - { - $query = select() - ->select(col('value')) - ->from(table_func(func('generate_series', [literal(1), literal(10)]))->as('value')); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT value FROM generate_series(1, 10) value' - ); - } - - public function test_select_with_type_cast() : void - { - $query = select() - ->select( - col('id'), - cast(col('price'), data_type_integer())->as('price_int') - ) - ->from(table('products')); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT id, price::int AS price_int FROM products' - ); - } - - public function test_select_with_union() : void - { - $query1 = select() - ->select(col('name')) - ->from(table('users')); - - $query2 = select() - ->select(col('name')) - ->from(table('admins')); - - $query = $query1->union($query2); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT name FROM users UNION SELECT name FROM admins' - ); - } - - public function test_select_with_union_all() : void - { - $query1 = select() - ->select(col('id')) - ->from(table('table1')); - - $query2 = select() - ->select(col('id')) - ->from(table('table2')); - - $query = $query1->unionAll($query2); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT id FROM table1 UNION ALL SELECT id FROM table2' - ); - } - - public function test_select_with_where_comparison_operators() : void - { - $query = select() - ->select(star()) - ->from(table('products')) - ->where( - cond_and( - gt(col('price'), literal(10)), - lt(col('price'), literal(100)), - gte(col('quantity'), literal(1)), - lte(col('weight'), literal(50)) - ) - ); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT * FROM products WHERE price > 10 AND price < 100 AND quantity >= 1 AND weight <= 50' - ); - } - - public function test_select_with_window_definition() : void - { - $query = select() - ->select( - col('department'), - col('salary'), - window_func( - 'row_number', - [], - [], - [order_by(col('salary'), SortDirection::DESC)] - )->as('rank') - ) - ->from(table('employees')) - ->window(window_def( - 'w', - [col('department')], - [order_by(col('salary'), SortDirection::DESC)] - )); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT department, salary, row_number() OVER (ORDER BY salary DESC) AS rank FROM employees WINDOW w AS (PARTITION BY department ORDER BY salary DESC)' - ); - } - - public function test_simple_select() : void - { - $query = select() - ->select(col('id'), col('name')) - ->from(table('users')); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT id, name FROM users' - ); - } - - public function test_simple_select_star() : void - { - $query = select() - ->select(star()) - ->from(table('users')); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT * FROM users' - ); - } - - public function test_simple_select_with_where() : void - { - $query = select() - ->select(star()) - ->from(table('users')) - ->where(eq(col('active'), literal(true))); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT * FROM users WHERE active = true' - ); - } - - public function test_sql_value_function_current_date() : void - { - $query = select() - ->select(current_date()->as('today')); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT current_date AS today' - ); - } - - public function test_sql_value_function_current_time() : void - { - $query = select() - ->select(current_time()->as('now_time')); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT current_time AS now_time' - ); - } - - public function test_sql_value_function_current_timestamp() : void - { - $query = select() - ->select(current_timestamp()->as('now')); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT current_timestamp AS now' - ); - } - - public function test_sql_value_functions_with_other_columns() : void - { - $query = select() - ->select( - col('id'), - col('name'), - current_timestamp()->as('created_at') - ) - ->from(table('users')); - - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT id, name, current_timestamp AS created_at FROM users' - ); - } -} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/TypeBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/TypeBuilderTest.php deleted file mode 100644 index 9c94ef7450..0000000000 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/TypeBuilderTest.php +++ /dev/null @@ -1,240 +0,0 @@ -enumType('status') - ->addValue('archived'); - - $this->assertAlterEnumTypeQuery( - $builder, - "ALTER TYPE status ADD VALUE 'archived'" - ); - } - - public function test_alter_enum_type_add_value_after() : void - { - $builder = alter()->enumType('status') - ->addValueAfter('archived', 'closed'); - - $this->assertAlterEnumTypeQuery( - $builder, - "ALTER TYPE status ADD VALUE 'archived' AFTER 'closed'" - ); - } - - public function test_alter_enum_type_add_value_before() : void - { - $builder = alter()->enumType('status') - ->addValueBefore('pending', 'active'); - - $this->assertAlterEnumTypeQuery( - $builder, - "ALTER TYPE status ADD VALUE 'pending' BEFORE 'active'" - ); - } - - public function test_alter_enum_type_add_value_if_not_exists() : void - { - $builder = alter()->enumType('status') - ->addValue('archived') - ->ifNotExists(); - - $this->assertAlterEnumTypeQuery( - $builder, - "ALTER TYPE status ADD VALUE IF NOT EXISTS 'archived'" - ); - } - - public function test_alter_enum_type_rename_value() : void - { - $builder = alter()->enumType('status') - ->renameValue('old_name', 'new_name'); - - $this->assertAlterEnumTypeQuery( - $builder, - "ALTER TYPE status RENAME VALUE 'old_name' TO 'new_name'" - ); - } - - public function test_create_composite_type_simple() : void - { - $builder = create()->compositeType('address') - ->attributes( - type_attr('street', data_type_text()), - type_attr('city', data_type_text()), - type_attr('zip', data_type_text()) - ); - - $this->assertCreateCompositeTypeQuery( - $builder, - 'CREATE TYPE address AS (street pg_catalog.text, city pg_catalog.text, zip pg_catalog.text)' - ); - } - - public function test_create_composite_type_with_collation() : void - { - $builder = create()->compositeType('person') - ->attributes( - type_attr('name', data_type_text())->collate('en_US') - ); - - $this->assertCreateCompositeTypeQuery( - $builder, - 'CREATE TYPE person AS (name pg_catalog.text COLLATE "en_US")' - ); - } - - public function test_create_composite_type_with_schema() : void - { - $builder = create()->compositeType('public.address') - ->attributes( - type_attr('street', data_type_text()) - ); - - $this->assertCreateCompositeTypeQuery( - $builder, - 'CREATE TYPE public.address AS (street pg_catalog.text)' - ); - } - - public function test_create_enum_type_simple() : void - { - $builder = create()->enumType('status') - ->labels('pending', 'active', 'closed'); - - $this->assertCreateEnumTypeQuery( - $builder, - "CREATE TYPE status AS ENUM ('pending', 'active', 'closed')" - ); - } - - public function test_create_enum_type_with_schema() : void - { - $builder = create()->enumType('public.status') - ->labels('pending', 'active'); - - $this->assertCreateEnumTypeQuery( - $builder, - "CREATE TYPE public.status AS ENUM ('pending', 'active')" - ); - } - - public function test_create_range_type_simple() : void - { - $builder = create()->rangeType('floatrange') - ->subtype('float8'); - - $this->assertCreateRangeTypeQuery( - $builder, - 'CREATE TYPE floatrange AS RANGE (subtype = float8)' - ); - } - - public function test_create_range_type_with_collation() : void - { - $builder = create()->rangeType('textrange') - ->subtype('text') - ->collation('en_US'); - - $this->assertCreateRangeTypeQuery( - $builder, - "CREATE TYPE textrange AS RANGE (subtype = text, \"collation\" = 'en_US')" - ); - } - - public function test_create_range_type_with_options() : void - { - $builder = create()->rangeType('floatrange') - ->subtype('float8') - ->subtypeOpclass('float8_ops'); - - $this->assertCreateRangeTypeQuery( - $builder, - "CREATE TYPE floatrange AS RANGE (subtype = float8, subtype_opclass = 'float8_ops')" - ); - } - - public function test_create_range_type_with_schema() : void - { - $builder = create()->rangeType('public.floatrange') - ->subtype('float8'); - - $this->assertCreateRangeTypeQuery( - $builder, - 'CREATE TYPE public.floatrange AS RANGE (subtype = float8)' - ); - } - - public function test_drop_type_cascade() : void - { - $builder = drop()->type('address') - ->cascade(); - - $this->assertDropTypeQuery( - $builder, - 'DROP TYPE address CASCADE' - ); - } - - public function test_drop_type_if_exists() : void - { - $builder = drop()->type('address') - ->ifExists(); - - $this->assertDropTypeQuery( - $builder, - 'DROP TYPE IF EXISTS address' - ); - } - - public function test_drop_type_if_exists_cascade() : void - { - $builder = drop()->type('address') - ->ifExists() - ->cascade(); - - $this->assertDropTypeQuery( - $builder, - 'DROP TYPE IF EXISTS address CASCADE' - ); - } - - public function test_drop_type_multiple() : void - { - $builder = drop()->type('address', 'status', 'floatrange'); - - $this->assertDropTypeQuery( - $builder, - 'DROP TYPE address, status, floatrange' - ); - } - - public function test_drop_type_restrict() : void - { - $builder = drop()->type('address') - ->restrict(); - - $this->assertDropTypeQuery( - $builder, - 'DROP TYPE address' - ); - } - - public function test_drop_type_simple() : void - { - $builder = drop()->type('address'); - - $this->assertDropTypeQuery( - $builder, - 'DROP TYPE address' - ); - } -} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/UpdateBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/UpdateBuilderTest.php deleted file mode 100644 index 2cf4303b8f..0000000000 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/UpdateBuilderTest.php +++ /dev/null @@ -1,161 +0,0 @@ -update('users') - ->set('name', literal('John')) - ->where(eq(col('id'), literal(1))); - - $this->assertUpdateQueryRoundTrip( - $query, - "UPDATE users SET name = 'John' WHERE id = 1" - ); - } - - public function test_update_with_alias() : void - { - $query = update() - ->update('users', 'u') - ->set('name', literal('John')) - ->where(eq(col('u.id'), literal(1))); - - $this->assertUpdateQueryRoundTrip( - $query, - "UPDATE users u SET name = 'John' WHERE u.id = 1" - ); - } - - public function test_update_with_column_expression() : void - { - $query = update() - ->update('products') - ->set('price', col('price')) - ->where(eq(col('id'), literal(1))); - - $this->assertUpdateQueryRoundTrip( - $query, - 'UPDATE products SET price = price WHERE id = 1' - ); - } - - public function test_update_with_from() : void - { - $query = update() - ->update('orders') - ->set('status', literal('completed')) - ->from(table('users')) - ->where(eq(col('orders.user_id'), col('users.id'))); - - $this->assertUpdateQueryRoundTrip( - $query, - "UPDATE orders SET status = 'completed' FROM users WHERE orders.user_id = users.id" - ); - } - - public function test_update_with_multiple_set() : void - { - $query = update() - ->update('users') - ->set('name', literal('John')) - ->set('email', literal('john@example.com')) - ->where(eq(col('id'), literal(1))); - - $this->assertUpdateQueryRoundTrip( - $query, - "UPDATE users SET name = 'John', email = 'john@example.com' WHERE id = 1" - ); - } - - public function test_update_with_parameters() : void - { - $query = update() - ->update('users') - ->set('name', param(1)) - ->where(eq(col('id'), param(2))); - - $this->assertUpdateQueryRoundTrip( - $query, - 'UPDATE users SET name = $1 WHERE id = $2' - ); - } - - public function test_update_with_returning() : void - { - $query = update() - ->update('users') - ->set('name', literal('John')) - ->where(eq(col('id'), literal(1))) - ->returning(col('id'), col('name')); - - $this->assertUpdateQueryRoundTrip( - $query, - "UPDATE users SET name = 'John' WHERE id = 1 RETURNING id, name" - ); - } - - public function test_update_with_returning_all() : void - { - $query = update() - ->update('users') - ->set('name', literal('John')) - ->where(eq(col('id'), literal(1))) - ->returningAll(); - - $this->assertUpdateQueryRoundTrip( - $query, - "UPDATE users SET name = 'John' WHERE id = 1 RETURNING *" - ); - } - - public function test_update_with_set_all() : void - { - $query = update() - ->update('users') - ->setAll([ - 'name' => literal('John'), - 'email' => literal('john@example.com'), - ]) - ->where(eq(col('id'), literal(1))); - - $this->assertUpdateQueryRoundTrip( - $query, - "UPDATE users SET name = 'John', email = 'john@example.com' WHERE id = 1" - ); - } - - public function test_update_with_subquery_in_set() : void - { - $subquery = select() - ->select(col('avg_price')) - ->from(table('price_stats')) - ->where(eq(col('category'), col('products.category'))); - - $query = update() - ->update('products') - ->set('price', sub_select($subquery)) - ->where(eq(col('id'), literal(1))); - - $this->assertUpdateQueryRoundTrip( - $query, - 'UPDATE products SET price = (SELECT avg_price FROM price_stats WHERE category = products.category) WHERE id = 1' - ); - } -} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/ViewBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/ViewBuilderTest.php deleted file mode 100644 index 53b9018159..0000000000 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/ViewBuilderTest.php +++ /dev/null @@ -1,504 +0,0 @@ -materializedView('my_matview') - ->ownerTo('new_owner'); - - $this->assertAlterMaterializedViewOwnerQuery( - $builder, - 'ALTER MATERIALIZED VIEW my_matview OWNER TO new_owner' - ); - } - - public function test_alter_materialized_view_rename() : void - { - $builder = alter()->materializedView('old_matview') - ->renameTo('new_matview'); - - $this->assertAlterMaterializedViewRenameQuery( - $builder, - 'ALTER MATERIALIZED VIEW old_matview RENAME TO new_matview' - ); - } - - public function test_alter_materialized_view_rename_if_exists() : void - { - $builder = alter()->materializedView('old_matview') - ->ifExists() - ->renameTo('new_matview'); - - $this->assertAlterMaterializedViewRenameQuery( - $builder, - 'ALTER MATERIALIZED VIEW IF EXISTS old_matview RENAME TO new_matview' - ); - } - - public function test_alter_materialized_view_set_schema() : void - { - $builder = alter()->materializedView('my_matview') - ->setSchema('archive'); - - $this->assertAlterMaterializedViewSchemaQuery( - $builder, - 'ALTER MATERIALIZED VIEW my_matview SET SCHEMA archive' - ); - } - - public function test_alter_materialized_view_set_tablespace() : void - { - $builder = alter()->materializedView('my_matview') - ->setTablespace('fast_storage'); - - $this->assertAlterMaterializedViewTablespaceQuery( - $builder, - 'ALTER MATERIALIZED VIEW my_matview SET TABLESPACE fast_storage' - ); - } - - public function test_alter_materialized_view_set_tablespace_if_exists() : void - { - $builder = alter()->materializedView('my_matview') - ->ifExists() - ->setTablespace('fast_storage'); - - $this->assertAlterMaterializedViewTablespaceQuery( - $builder, - 'ALTER MATERIALIZED VIEW IF EXISTS my_matview SET TABLESPACE fast_storage' - ); - } - - public function test_alter_view_owner_to() : void - { - $builder = alter()->view('my_view') - ->ownerTo('new_owner'); - - $this->assertAlterViewOwnerQuery( - $builder, - 'ALTER VIEW my_view OWNER TO new_owner' - ); - } - - public function test_alter_view_rename() : void - { - $builder = alter()->view('old_view') - ->renameTo('new_view'); - - $this->assertAlterViewRenameQuery( - $builder, - 'ALTER VIEW old_view RENAME TO new_view' - ); - } - - public function test_alter_view_rename_if_exists() : void - { - $builder = alter()->view('old_view') - ->ifExists() - ->renameTo('new_view'); - - $this->assertAlterViewRenameQuery( - $builder, - 'ALTER VIEW IF EXISTS old_view RENAME TO new_view' - ); - } - - public function test_alter_view_rename_with_schema() : void - { - $builder = alter()->view('public.old_view') - ->renameTo('new_view'); - - $this->assertAlterViewRenameQuery( - $builder, - 'ALTER VIEW public.old_view RENAME TO new_view' - ); - } - - public function test_alter_view_set_schema() : void - { - $builder = alter()->view('my_view') - ->setSchema('archive'); - - $this->assertAlterViewSchemaQuery( - $builder, - 'ALTER VIEW my_view SET SCHEMA archive' - ); - } - - public function test_alter_view_set_schema_if_exists() : void - { - $builder = alter()->view('my_view') - ->ifExists() - ->setSchema('archive'); - - $this->assertAlterViewSchemaQuery( - $builder, - 'ALTER VIEW IF EXISTS my_view SET SCHEMA archive' - ); - } - - public function test_create_materialized_view() : void - { - $builder = create()->materializedView('user_stats') - ->as(select(star())->from(table('users'))); - - $this->assertCreateMaterializedViewQuery( - $builder, - 'CREATE MATERIALIZED VIEW user_stats AS SELECT * FROM users' - ); - } - - public function test_create_materialized_view_if_not_exists() : void - { - $builder = create()->materializedView('user_stats') - ->ifNotExists() - ->as(select(star())->from(table('users'))); - - $this->assertCreateMaterializedViewQuery( - $builder, - 'CREATE MATERIALIZED VIEW IF NOT EXISTS user_stats AS SELECT * FROM users' - ); - } - - public function test_create_materialized_view_using_access_method() : void - { - $builder = create()->materializedView('user_stats') - ->using('heap') - ->as(select(star())->from(table('users'))); - - $this->assertCreateMaterializedViewQuery( - $builder, - 'CREATE MATERIALIZED VIEW user_stats USING heap AS SELECT * FROM users' - ); - } - - public function test_create_materialized_view_with_columns() : void - { - $builder = create()->materializedView('user_stats') - ->columns('user_id', 'order_count') - ->as(select(col('id'), agg_count())->from(table('users'))); - - $this->assertCreateMaterializedViewQuery( - $builder, - 'CREATE MATERIALIZED VIEW user_stats(user_id, order_count) AS SELECT id, count(*) FROM users' - ); - } - - public function test_create_materialized_view_with_data() : void - { - $builder = create()->materializedView('user_stats') - ->as(select()->select(star())->from(table('users'))) - ->withData(); - - $this->assertCreateMaterializedViewQuery( - $builder, - 'CREATE MATERIALIZED VIEW user_stats AS SELECT * FROM users' - ); - } - - public function test_create_materialized_view_with_no_data() : void - { - $builder = create()->materializedView('user_stats') - ->as(select()->select(star())->from(table('users'))) - ->withNoData(); - - $this->assertCreateMaterializedViewQuery( - $builder, - 'CREATE MATERIALIZED VIEW user_stats AS SELECT * FROM users WITH NO DATA' - ); - } - - public function test_create_materialized_view_with_schema() : void - { - $builder = create()->materializedView('analytics.user_stats') - ->as(select(star())->from(table('users'))); - - $this->assertCreateMaterializedViewQuery( - $builder, - 'CREATE MATERIALIZED VIEW analytics.user_stats AS SELECT * FROM users' - ); - } - - public function test_create_materialized_view_with_tablespace() : void - { - $builder = create()->materializedView('user_stats') - ->as(select()->select(star())->from(table('users'))) - ->tablespace('fast_storage'); - - $this->assertCreateMaterializedViewQuery( - $builder, - 'CREATE MATERIALIZED VIEW user_stats TABLESPACE fast_storage AS SELECT * FROM users' - ); - } - - public function test_create_or_replace_view() : void - { - $builder = create()->view('active_users') - ->orReplace() - ->as(select(star())->from(table('users'))); - - $this->assertCreateViewQuery( - $builder, - 'CREATE OR REPLACE VIEW active_users AS SELECT * FROM users' - ); - } - - /** - * Note: CREATE RECURSIVE VIEW is syntactic sugar that PostgreSQL internally transforms - * into a CTE-based query structure. The pg_query deparser has issues handling this - * transformed AST (segfaults), so this feature is not fully supported in the query builder. - * Use a regular view with a CTE instead for recursive queries. - */ - public function test_create_recursive_view_outputs_as_regular_view() : void - { - $builder = create()->view('subordinates') - ->recursive() - ->columns('id', 'name', 'manager_id') - ->as(select(col('id'), col('name'), col('manager_id'))->from(table('employees'))); - - $this->assertCreateViewQuery( - $builder, - 'CREATE VIEW subordinates (id, name, manager_id) AS SELECT id, name, manager_id FROM employees' - ); - } - - public function test_create_temporary_view() : void - { - $builder = create()->view('temp_users') - ->temporary() - ->as(select(star())->from(table('users'))); - - $this->assertCreateViewQuery( - $builder, - 'CREATE TEMPORARY VIEW temp_users AS SELECT * FROM users' - ); - } - - public function test_create_view_simple() : void - { - $builder = create()->view('active_users') - ->as(select(star())->from(table('users'))); - - $this->assertCreateViewQuery( - $builder, - 'CREATE VIEW active_users AS SELECT * FROM users' - ); - } - - public function test_create_view_with_cascaded_check_option() : void - { - $builder = create()->view('active_users') - ->as(select()->select(star())->from(table('users'))) - ->withCascadedCheckOption(); - - $this->assertCreateViewQuery( - $builder, - 'CREATE VIEW active_users AS SELECT * FROM users WITH CHECK OPTION' - ); - } - - public function test_create_view_with_check_option() : void - { - $builder = create()->view('active_users') - ->as(select(star())->from(table('users'))->where(eq(col('active'), literal(true)))) - ->withCheckOption(); - - $this->assertCreateViewQuery( - $builder, - 'CREATE VIEW active_users AS SELECT * FROM users WHERE active = true WITH CHECK OPTION' - ); - } - - public function test_create_view_with_columns() : void - { - $builder = create()->view('user_info') - ->columns('user_id', 'user_name', 'email_address') - ->as(select(col('id'), col('name'), col('email'))->from(table('users'))); - - $this->assertCreateViewQuery( - $builder, - 'CREATE VIEW user_info (user_id, user_name, email_address) AS SELECT id, name, email FROM users' - ); - } - - public function test_create_view_with_local_check_option() : void - { - $builder = create()->view('active_users') - ->as(select()->select(star())->from(table('users'))) - ->withLocalCheckOption(); - - $this->assertCreateViewQuery( - $builder, - 'CREATE VIEW active_users AS SELECT * FROM users WITH LOCAL CHECK OPTION' - ); - } - - public function test_create_view_with_schema() : void - { - $builder = create()->view('public.active_users') - ->as(select(star())->from(table('users'))); - - $this->assertCreateViewQuery( - $builder, - 'CREATE VIEW public.active_users AS SELECT * FROM users' - ); - } - - public function test_drop_materialized_view_if_exists_cascade() : void - { - $builder = drop()->materializedView('user_stats') - ->ifExists() - ->cascade(); - - $this->assertDropMaterializedViewQuery( - $builder, - 'DROP MATERIALIZED VIEW IF EXISTS user_stats CASCADE' - ); - } - - public function test_drop_materialized_view_simple() : void - { - $builder = drop()->materializedView('user_stats'); - - $this->assertDropMaterializedViewQuery( - $builder, - 'DROP MATERIALIZED VIEW user_stats' - ); - } - - public function test_drop_view_cascade() : void - { - $builder = drop()->view('active_users')->cascade(); - - $this->assertDropViewQuery( - $builder, - 'DROP VIEW active_users CASCADE' - ); - } - - public function test_drop_view_if_exists() : void - { - $builder = drop()->view('active_users')->ifExists(); - - $this->assertDropViewQuery( - $builder, - 'DROP VIEW IF EXISTS active_users' - ); - } - - public function test_drop_view_if_exists_cascade() : void - { - $builder = drop()->view('active_users') - ->ifExists() - ->cascade(); - - $this->assertDropViewQuery( - $builder, - 'DROP VIEW IF EXISTS active_users CASCADE' - ); - } - - public function test_drop_view_multiple() : void - { - $builder = drop()->view('view1', 'view2', 'view3'); - - $this->assertDropViewQuery( - $builder, - 'DROP VIEW view1, view2, view3' - ); - } - - public function test_drop_view_simple() : void - { - $builder = drop()->view('active_users'); - - $this->assertDropViewQuery( - $builder, - 'DROP VIEW active_users' - ); - } - - public function test_refresh_materialized_view_concurrently() : void - { - $builder = refresh_materialized_view('user_stats') - ->concurrently(); - - $this->assertRefreshMaterializedViewQuery( - $builder, - 'REFRESH MATERIALIZED VIEW CONCURRENTLY user_stats' - ); - } - - public function test_refresh_materialized_view_concurrently_with_data() : void - { - $builder = refresh_materialized_view('user_stats') - ->concurrently() - ->withData(); - - $this->assertRefreshMaterializedViewQuery( - $builder, - 'REFRESH MATERIALIZED VIEW CONCURRENTLY user_stats' - ); - } - - public function test_refresh_materialized_view_simple() : void - { - $builder = refresh_materialized_view('user_stats'); - - $this->assertRefreshMaterializedViewQuery( - $builder, - 'REFRESH MATERIALIZED VIEW user_stats' - ); - } - - public function test_refresh_materialized_view_with_data() : void - { - $builder = refresh_materialized_view('user_stats') - ->withData(); - - $this->assertRefreshMaterializedViewQuery( - $builder, - 'REFRESH MATERIALIZED VIEW user_stats' - ); - } - - public function test_refresh_materialized_view_with_no_data() : void - { - $builder = refresh_materialized_view('user_stats') - ->withNoData(); - - $this->assertRefreshMaterializedViewQuery( - $builder, - 'REFRESH MATERIALIZED VIEW user_stats WITH NO DATA' - ); - } - - public function test_refresh_materialized_view_with_schema() : void - { - $builder = refresh_materialized_view('analytics.user_stats'); - - $this->assertRefreshMaterializedViewQuery( - $builder, - 'REFRESH MATERIALIZED VIEW analytics.user_stats' - ); - } -} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/RowMapper/ConstructorMapperTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/RowMapper/ConstructorMapperTest.php index bf4c44037f..254eeb494f 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/RowMapper/ConstructorMapperTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/RowMapper/ConstructorMapperTest.php @@ -10,13 +10,6 @@ final class ConstructorMapperTest extends TestCase { - private ConstructorMapper $mapper; - - protected function setUp() : void - { - $this->mapper = new ConstructorMapper(); - } - public function test_allows_extra_columns_in_row() : void { $row = [ @@ -26,7 +19,7 @@ public function test_allows_extra_columns_in_row() : void 'extra_column' => 'ignored', ]; - $result = $this->mapper->map(SimpleDto::class, $row); + $result = (new ConstructorMapper(SimpleDto::class))->map($row); self::assertInstanceOf(SimpleDto::class, $result); self::assertSame(1, $result->id); @@ -40,7 +33,7 @@ public function test_handles_null_value_in_row() : void 'nickname' => null, ]; - $result = $this->mapper->map(NullableDto::class, $row); + $result = (new ConstructorMapper(NullableDto::class))->map($row); self::assertNull($result->nickname); } @@ -63,7 +56,7 @@ public function test_maps_all_supported_types() : void 'tags' => $tags, ]; - $result = $this->mapper->map(FullTypedDto::class, $row); + $result = (new ConstructorMapper(FullTypedDto::class))->map($row); self::assertInstanceOf(FullTypedDto::class, $result); self::assertSame(42, $result->id); @@ -84,7 +77,7 @@ public function test_maps_array_type() : void 'tags' => $tags, ]; - $result = $this->mapper->map(ArrayDto::class, $row); + $result = (new ConstructorMapper(ArrayDto::class))->map($row); self::assertInstanceOf(ArrayDto::class, $result); self::assertSame($tags, $result->tags); @@ -98,7 +91,7 @@ public function test_maps_bool_type() : void 'verified' => false, ]; - $result = $this->mapper->map(BoolDto::class, $row); + $result = (new ConstructorMapper(BoolDto::class))->map($row); self::assertInstanceOf(BoolDto::class, $result); self::assertTrue($result->active); @@ -113,7 +106,7 @@ public function test_maps_datetime_type() : void 'createdAt' => $createdAt, ]; - $result = $this->mapper->map(DateTimeDto::class, $row); + $result = (new ConstructorMapper(DateTimeDto::class))->map($row); self::assertInstanceOf(DateTimeDto::class, $result); self::assertSame($createdAt, $result->createdAt); @@ -127,7 +120,7 @@ public function test_maps_float_special_values() : void 'discount' => \NAN, ]; - $result = $this->mapper->map(FloatDto::class, $row); + $result = (new ConstructorMapper(FloatDto::class))->map($row); self::assertInstanceOf(FloatDto::class, $result); self::assertSame(\INF, $result->price); @@ -142,7 +135,7 @@ public function test_maps_float_type() : void 'discount' => 0.15, ]; - $result = $this->mapper->map(FloatDto::class, $row); + $result = (new ConstructorMapper(FloatDto::class))->map($row); self::assertInstanceOf(FloatDto::class, $result); self::assertSame(99.99, $result->price); @@ -157,7 +150,7 @@ public function test_maps_json_type() : void 'metadata' => $json, ]; - $result = $this->mapper->map(JsonDto::class, $row); + $result = (new ConstructorMapper(JsonDto::class))->map($row); self::assertInstanceOf(JsonDto::class, $result); self::assertSame($json, $result->metadata); @@ -170,7 +163,7 @@ public function test_maps_nullable_complex_types() : void 'id' => 1, ]; - $result = $this->mapper->map(NullableTypedDto::class, $row); + $result = (new ConstructorMapper(NullableTypedDto::class))->map($row); self::assertInstanceOf(NullableTypedDto::class, $result); self::assertSame(1, $result->id); @@ -195,7 +188,7 @@ public function test_maps_nullable_complex_types_with_values() : void 'tags' => $tags, ]; - $result = $this->mapper->map(NullableTypedDto::class, $row); + $result = (new ConstructorMapper(NullableTypedDto::class))->map($row); self::assertInstanceOf(NullableTypedDto::class, $result); self::assertSame($createdAt, $result->createdAt); @@ -211,7 +204,7 @@ public function test_maps_nullable_parameters() : void 'name' => 'John Doe', ]; - $result = $this->mapper->map(NullableDto::class, $row); + $result = (new ConstructorMapper(NullableDto::class))->map($row); self::assertInstanceOf(NullableDto::class, $result); self::assertSame(1, $result->id); @@ -227,7 +220,7 @@ public function test_maps_row_to_simple_dto() : void 'email' => 'john@example.com', ]; - $result = $this->mapper->map(SimpleDto::class, $row); + $result = (new ConstructorMapper(SimpleDto::class))->map($row); self::assertInstanceOf(SimpleDto::class, $result); self::assertSame(1, $result->id); @@ -243,7 +236,7 @@ public function test_maps_uuid_type() : void 'uuid' => $uuid, ]; - $result = $this->mapper->map(UuidDto::class, $row); + $result = (new ConstructorMapper(UuidDto::class))->map($row); self::assertInstanceOf(UuidDto::class, $result); self::assertSame($uuid, $result->uuid); @@ -254,16 +247,7 @@ public function test_throws_for_class_without_constructor() : void $this->expectException(MappingException::class); $this->expectExceptionMessage('Class has no constructor'); - $this->mapper->map(NoConstructorDto::class, ['id' => 1]); - } - - public function test_throws_for_invalid_class() : void - { - $this->expectException(MappingException::class); - $this->expectExceptionMessage('Class does not exist'); - - /** @phpstan-ignore argument.type */ - $this->mapper->map('NonExistentClass', ['id' => 1]); + (new ConstructorMapper(NoConstructorDto::class))->map(['id' => 1]); } public function test_throws_for_missing_required_parameter() : void @@ -275,7 +259,7 @@ public function test_throws_for_missing_required_parameter() : void $this->expectException(MappingException::class); $this->expectExceptionMessage('Property "name" not found'); - $this->mapper->map(SimpleDto::class, $row); + (new ConstructorMapper(SimpleDto::class))->map($row); } public function test_uses_default_values() : void @@ -285,7 +269,7 @@ public function test_uses_default_values() : void 'name' => 'John Doe', ]; - $result = $this->mapper->map(DefaultValueDto::class, $row); + $result = (new ConstructorMapper(DefaultValueDto::class))->map($row); self::assertInstanceOf(DefaultValueDto::class, $result); self::assertSame(1, $result->id); diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Telemetry/ParameterFormatterTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Telemetry/ParameterFormatterTest.php index 7047070483..4fd765fa52 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Telemetry/ParameterFormatterTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Telemetry/ParameterFormatterTest.php @@ -6,7 +6,7 @@ use Flow\PostgreSql\Client\Telemetry\ParameterFormatter; use Flow\PostgreSql\Client\TypedValue; -use Flow\PostgreSql\Client\Types\PostgreSqlType; +use Flow\PostgreSql\Client\Types\ValueType; use PHPUnit\Framework\TestCase; final class ParameterFormatterTest extends TestCase @@ -109,7 +109,7 @@ public function test_convert_to_string_string() : void public function test_convert_to_string_typed_value() : void { $formatter = new ParameterFormatter(); - $typedValue = new TypedValue('some_value', PostgreSqlType::TEXT); + $typedValue = new TypedValue('some_value', ValueType::TEXT); $result = $formatter->convertToString($typedValue); @@ -119,7 +119,7 @@ public function test_convert_to_string_typed_value() : void public function test_convert_to_string_typed_value_with_nested_value() : void { $formatter = new ParameterFormatter(); - $typedValue = new TypedValue(['a', 'b', 'c'], PostgreSqlType::TEXT_ARRAY); + $typedValue = new TypedValue(['a', 'b', 'c'], ValueType::TEXT_ARRAY); $result = $formatter->convertToString($typedValue); diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Telemetry/TraceableClientTelemetryTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Telemetry/TraceableClientTelemetryTest.php index 47539f4f26..082be8b584 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Telemetry/TraceableClientTelemetryTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Telemetry/TraceableClientTelemetryTest.php @@ -178,7 +178,7 @@ public function test_fetch_all_into_creates_span_with_correct_row_count() : void $mockClient->method('fetchAllInto')->willReturn($users); $client = traceable_postgresql_client($mockClient, $config); - $client->fetchAllInto(\stdClass::class, 'SELECT * FROM users'); + $client->fetchAllInto(new \Flow\PostgreSql\Client\RowMapper\ConstructorMapper(\stdClass::class), 'SELECT * FROM users'); $spans = $spanProcessor->endedSpans(); self::assertCount(1, $spans); @@ -198,7 +198,7 @@ public function test_fetch_into_creates_span_with_correct_row_count() : void $mockClient->method('fetchInto')->willReturn($user); $client = traceable_postgresql_client($mockClient, $config); - $client->fetchInto(\stdClass::class, 'SELECT * FROM users WHERE id = $1', [1]); + $client->fetchInto(new \Flow\PostgreSql\Client\RowMapper\ConstructorMapper(\stdClass::class), 'SELECT * FROM users WHERE id = $1', [1]); $spans = $spanProcessor->endedSpans(); self::assertCount(1, $spans); @@ -218,7 +218,7 @@ public function test_fetch_one_into_creates_span() : void $mockClient->method('fetchOneInto')->willReturn($user); $client = traceable_postgresql_client($mockClient, $config); - $client->fetchOneInto(\stdClass::class, 'SELECT * FROM users WHERE id = $1', [1]); + $client->fetchOneInto(new \Flow\PostgreSql\Client\RowMapper\ConstructorMapper(\stdClass::class), 'SELECT * FROM users WHERE id = $1', [1]); $spans = $spanProcessor->endedSpans(); self::assertCount(1, $spans); diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Telemetry/TraceableCursorTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Telemetry/TraceableCursorTest.php index aa70097e04..729d63c7d7 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Telemetry/TraceableCursorTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Telemetry/TraceableCursorTest.php @@ -147,7 +147,7 @@ public function test_map_completes_span_after_full_iteration() : void $objects = []; - foreach ($cursor->map(\stdClass::class) as $object) { + foreach ($cursor->map(new \Flow\PostgreSql\Client\RowMapper\ConstructorMapper(\stdClass::class)) as $object) { $objects[] = $object; } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/BoolArrayConverterTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/BoolArrayConverterTest.php index 073364032a..1420b6a4e9 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/BoolArrayConverterTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/BoolArrayConverterTest.php @@ -6,7 +6,7 @@ use Flow\PostgreSql\Client\Exception\ValueConversionException; use Flow\PostgreSql\Client\Types\Converter\BoolArrayConverter; -use Flow\PostgreSql\Client\Types\PostgreSqlType; +use Flow\PostgreSql\Client\Types\ValueType; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; @@ -61,7 +61,7 @@ public function test_supported_types() : void $converter = new BoolArrayConverter(); $types = $converter->supportedTypes(); - self::assertContains(PostgreSqlType::BOOL_ARRAY, $types); + self::assertContains(ValueType::BOOL_ARRAY, $types); self::assertCount(1, $types); } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/BooleanConverterTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/BooleanConverterTest.php index 7dcf8e304b..e00c67d92c 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/BooleanConverterTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/BooleanConverterTest.php @@ -6,7 +6,7 @@ use Flow\PostgreSql\Client\Exception\ValueConversionException; use Flow\PostgreSql\Client\Types\Converter\BooleanConverter; -use Flow\PostgreSql\Client\Types\PostgreSqlType; +use Flow\PostgreSql\Client\Types\ValueType; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; @@ -52,7 +52,7 @@ public function test_null_handling() : void public function test_supported_types() : void { $converter = new BooleanConverter(); - self::assertContains(PostgreSqlType::BOOL, $converter->supportedTypes()); + self::assertContains(ValueType::BOOL, $converter->supportedTypes()); } #[DataProvider('provide_valid_values')] diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/ByteaConverterTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/ByteaConverterTest.php index 0de66b1cb4..362d007ad7 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/ByteaConverterTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/ByteaConverterTest.php @@ -6,7 +6,7 @@ use Flow\PostgreSql\Client\Exception\ValueConversionException; use Flow\PostgreSql\Client\Types\Converter\ByteaConverter; -use Flow\PostgreSql\Client\Types\PostgreSqlType; +use Flow\PostgreSql\Client\Types\ValueType; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; @@ -54,7 +54,7 @@ public function test_null_handling() : void public function test_supported_types() : void { $converter = new ByteaConverter(); - self::assertContains(PostgreSqlType::BYTEA, $converter->supportedTypes()); + self::assertContains(ValueType::BYTEA, $converter->supportedTypes()); } #[DataProvider('provide_valid_values')] diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/CidrConverterTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/CidrConverterTest.php index b2a9f7e07a..ae8bbf0151 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/CidrConverterTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/CidrConverterTest.php @@ -6,7 +6,7 @@ use Flow\PostgreSql\Client\Exception\ValueConversionException; use Flow\PostgreSql\Client\Types\Converter\CidrConverter; -use Flow\PostgreSql\Client\Types\PostgreSqlType; +use Flow\PostgreSql\Client\Types\ValueType; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; @@ -59,7 +59,7 @@ public function test_null_handling() : void public function test_supported_types() : void { $converter = new CidrConverter(); - self::assertContains(PostgreSqlType::CIDR, $converter->supportedTypes()); + self::assertContains(ValueType::CIDR, $converter->supportedTypes()); } #[DataProvider('provide_valid_values')] diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/DateConverterTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/DateConverterTest.php index 11f99adff2..0ae4e6e506 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/DateConverterTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/DateConverterTest.php @@ -6,7 +6,7 @@ use Flow\PostgreSql\Client\Exception\ValueConversionException; use Flow\PostgreSql\Client\Types\Converter\DateConverter; -use Flow\PostgreSql\Client\Types\PostgreSqlType; +use Flow\PostgreSql\Client\Types\ValueType; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; @@ -54,7 +54,7 @@ public function test_null_handling() : void public function test_supported_types() : void { $converter = new DateConverter(); - self::assertContains(PostgreSqlType::DATE, $converter->supportedTypes()); + self::assertContains(ValueType::DATE, $converter->supportedTypes()); } #[DataProvider('provide_valid_values')] diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/DateTimeConverterTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/DateTimeConverterTest.php index 47c313a196..b57419ad1d 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/DateTimeConverterTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/DateTimeConverterTest.php @@ -6,7 +6,7 @@ use Flow\PostgreSql\Client\Exception\ValueConversionException; use Flow\PostgreSql\Client\Types\Converter\DateTimeConverter; -use Flow\PostgreSql\Client\Types\PostgreSqlType; +use Flow\PostgreSql\Client\Types\ValueType; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; @@ -55,8 +55,8 @@ public function test_supported_types() : void $converter = new DateTimeConverter(); $types = $converter->supportedTypes(); - self::assertContains(PostgreSqlType::TIMESTAMP, $types); - self::assertContains(PostgreSqlType::TIMESTAMPTZ, $types); + self::assertContains(ValueType::TIMESTAMP, $types); + self::assertContains(ValueType::TIMESTAMPTZ, $types); } #[DataProvider('provide_valid_values')] diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/FloatArrayConverterTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/FloatArrayConverterTest.php index c78dc3eff3..8c7465f803 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/FloatArrayConverterTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/FloatArrayConverterTest.php @@ -6,7 +6,7 @@ use Flow\PostgreSql\Client\Exception\ValueConversionException; use Flow\PostgreSql\Client\Types\Converter\FloatArrayConverter; -use Flow\PostgreSql\Client\Types\PostgreSqlType; +use Flow\PostgreSql\Client\Types\ValueType; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; @@ -64,8 +64,8 @@ public function test_supported_types() : void $converter = new FloatArrayConverter(); $types = $converter->supportedTypes(); - self::assertContains(PostgreSqlType::FLOAT4_ARRAY, $types); - self::assertContains(PostgreSqlType::FLOAT8_ARRAY, $types); + self::assertContains(ValueType::FLOAT4_ARRAY, $types); + self::assertContains(ValueType::FLOAT8_ARRAY, $types); self::assertCount(2, $types); } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/FloatConverterTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/FloatConverterTest.php index 95a5de540d..dce321fc64 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/FloatConverterTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/FloatConverterTest.php @@ -6,7 +6,7 @@ use Flow\PostgreSql\Client\Exception\ValueConversionException; use Flow\PostgreSql\Client\Types\Converter\FloatConverter; -use Flow\PostgreSql\Client\Types\PostgreSqlType; +use Flow\PostgreSql\Client\Types\ValueType; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; @@ -58,8 +58,8 @@ public function test_supported_types() : void $converter = new FloatConverter(); $types = $converter->supportedTypes(); - self::assertContains(PostgreSqlType::FLOAT4, $types); - self::assertContains(PostgreSqlType::FLOAT8, $types); + self::assertContains(ValueType::FLOAT4, $types); + self::assertContains(ValueType::FLOAT8, $types); self::assertCount(2, $types); } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/InetConverterTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/InetConverterTest.php index 226c461ff0..d2d9a9be0b 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/InetConverterTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/InetConverterTest.php @@ -6,7 +6,7 @@ use Flow\PostgreSql\Client\Exception\ValueConversionException; use Flow\PostgreSql\Client\Types\Converter\InetConverter; -use Flow\PostgreSql\Client\Types\PostgreSqlType; +use Flow\PostgreSql\Client\Types\ValueType; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; @@ -57,7 +57,7 @@ public function test_null_handling() : void public function test_supported_types() : void { $converter = new InetConverter(); - self::assertContains(PostgreSqlType::INET, $converter->supportedTypes()); + self::assertContains(ValueType::INET, $converter->supportedTypes()); } #[DataProvider('provide_valid_values')] diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/IntArrayConverterTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/IntArrayConverterTest.php index 1247627e90..7a16557630 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/IntArrayConverterTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/IntArrayConverterTest.php @@ -6,7 +6,7 @@ use Flow\PostgreSql\Client\Exception\ValueConversionException; use Flow\PostgreSql\Client\Types\Converter\IntArrayConverter; -use Flow\PostgreSql\Client\Types\PostgreSqlType; +use Flow\PostgreSql\Client\Types\ValueType; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; @@ -63,9 +63,9 @@ public function test_supported_types() : void $converter = new IntArrayConverter(); $types = $converter->supportedTypes(); - self::assertContains(PostgreSqlType::INT2_ARRAY, $types); - self::assertContains(PostgreSqlType::INT4_ARRAY, $types); - self::assertContains(PostgreSqlType::INT8_ARRAY, $types); + self::assertContains(ValueType::INT2_ARRAY, $types); + self::assertContains(ValueType::INT4_ARRAY, $types); + self::assertContains(ValueType::INT8_ARRAY, $types); self::assertCount(3, $types); } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/IntegerConverterTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/IntegerConverterTest.php index 3560e3371b..1d06baca21 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/IntegerConverterTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/IntegerConverterTest.php @@ -6,7 +6,7 @@ use Flow\PostgreSql\Client\Exception\ValueConversionException; use Flow\PostgreSql\Client\Types\Converter\IntegerConverter; -use Flow\PostgreSql\Client\Types\PostgreSqlType; +use Flow\PostgreSql\Client\Types\ValueType; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; @@ -56,9 +56,9 @@ public function test_supported_types() : void $converter = new IntegerConverter(); $types = $converter->supportedTypes(); - self::assertContains(PostgreSqlType::INT2, $types); - self::assertContains(PostgreSqlType::INT4, $types); - self::assertContains(PostgreSqlType::INT8, $types); + self::assertContains(ValueType::INT2, $types); + self::assertContains(ValueType::INT4, $types); + self::assertContains(ValueType::INT8, $types); } #[DataProvider('provide_valid_values')] diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/IntervalConverterTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/IntervalConverterTest.php index 4765b24fe3..af9cecbe38 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/IntervalConverterTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/IntervalConverterTest.php @@ -6,7 +6,7 @@ use Flow\PostgreSql\Client\Exception\ValueConversionException; use Flow\PostgreSql\Client\Types\Converter\IntervalConverter; -use Flow\PostgreSql\Client\Types\PostgreSqlType; +use Flow\PostgreSql\Client\Types\ValueType; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; @@ -60,7 +60,7 @@ public function test_null_handling() : void public function test_supported_types() : void { $converter = new IntervalConverter(); - self::assertContains(PostgreSqlType::INTERVAL, $converter->supportedTypes()); + self::assertContains(ValueType::INTERVAL, $converter->supportedTypes()); } #[DataProvider('provide_valid_values')] diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/JsonArrayConverterTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/JsonArrayConverterTest.php index 9b77312bc6..2c3daa2832 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/JsonArrayConverterTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/JsonArrayConverterTest.php @@ -6,7 +6,7 @@ use Flow\PostgreSql\Client\Exception\ValueConversionException; use Flow\PostgreSql\Client\Types\Converter\JsonArrayConverter; -use Flow\PostgreSql\Client\Types\PostgreSqlType; +use Flow\PostgreSql\Client\Types\ValueType; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; @@ -78,8 +78,8 @@ public function test_supported_types() : void $converter = new JsonArrayConverter(); $types = $converter->supportedTypes(); - self::assertContains(PostgreSqlType::JSON_ARRAY, $types); - self::assertContains(PostgreSqlType::JSONB_ARRAY, $types); + self::assertContains(ValueType::JSON_ARRAY, $types); + self::assertContains(ValueType::JSONB_ARRAY, $types); self::assertCount(2, $types); } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/JsonConverterTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/JsonConverterTest.php index 44b0810848..61ef549d8c 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/JsonConverterTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/JsonConverterTest.php @@ -6,7 +6,7 @@ use Flow\PostgreSql\Client\Exception\ValueConversionException; use Flow\PostgreSql\Client\Types\Converter\JsonConverter; -use Flow\PostgreSql\Client\Types\PostgreSqlType; +use Flow\PostgreSql\Client\Types\ValueType; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; @@ -78,8 +78,8 @@ public function test_supported_types() : void $converter = new JsonConverter(); $types = $converter->supportedTypes(); - self::assertContains(PostgreSqlType::JSON, $types); - self::assertContains(PostgreSqlType::JSONB, $types); + self::assertContains(ValueType::JSON, $types); + self::assertContains(ValueType::JSONB, $types); } #[DataProvider('provide_valid_values')] diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/MoneyConverterTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/MoneyConverterTest.php index 38b5c23644..5d6f6dc46c 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/MoneyConverterTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/MoneyConverterTest.php @@ -6,7 +6,7 @@ use Flow\PostgreSql\Client\Exception\ValueConversionException; use Flow\PostgreSql\Client\Types\Converter\MoneyConverter; -use Flow\PostgreSql\Client\Types\PostgreSqlType; +use Flow\PostgreSql\Client\Types\ValueType; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; @@ -55,7 +55,7 @@ public function test_null_handling() : void public function test_supported_types() : void { $converter = new MoneyConverter(); - self::assertContains(PostgreSqlType::MONEY, $converter->supportedTypes()); + self::assertContains(ValueType::MONEY, $converter->supportedTypes()); } #[DataProvider('provide_valid_values')] diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/NumericConverterTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/NumericConverterTest.php index 333549eb2c..7683ece662 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/NumericConverterTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/NumericConverterTest.php @@ -6,7 +6,7 @@ use Flow\PostgreSql\Client\Exception\ValueConversionException; use Flow\PostgreSql\Client\Types\Converter\NumericConverter; -use Flow\PostgreSql\Client\Types\PostgreSqlType; +use Flow\PostgreSql\Client\Types\ValueType; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; @@ -53,7 +53,7 @@ public function test_null_handling() : void public function test_supported_types() : void { $converter = new NumericConverter(); - self::assertContains(PostgreSqlType::NUMERIC, $converter->supportedTypes()); + self::assertContains(ValueType::NUMERIC, $converter->supportedTypes()); } #[DataProvider('provide_valid_values')] diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/StringConverterTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/StringConverterTest.php index f42564a033..2c6cc92a32 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/StringConverterTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/StringConverterTest.php @@ -6,7 +6,7 @@ use Flow\PostgreSql\Client\Exception\ValueConversionException; use Flow\PostgreSql\Client\Types\Converter\StringConverter; -use Flow\PostgreSql\Client\Types\PostgreSqlType; +use Flow\PostgreSql\Client\Types\ValueType; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; @@ -76,10 +76,10 @@ public function test_supported_types() : void $converter = new StringConverter(); $types = $converter->supportedTypes(); - self::assertContains(PostgreSqlType::TEXT, $types); - self::assertContains(PostgreSqlType::VARCHAR, $types); - self::assertContains(PostgreSqlType::CHAR, $types); - self::assertContains(PostgreSqlType::BPCHAR, $types); + self::assertContains(ValueType::TEXT, $types); + self::assertContains(ValueType::VARCHAR, $types); + self::assertContains(ValueType::CHAR, $types); + self::assertContains(ValueType::BPCHAR, $types); } #[DataProvider('provide_valid_values')] diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/TextArrayConverterTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/TextArrayConverterTest.php index 0cf0f10ec1..96ef6cde02 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/TextArrayConverterTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/TextArrayConverterTest.php @@ -6,7 +6,7 @@ use Flow\PostgreSql\Client\Exception\ValueConversionException; use Flow\PostgreSql\Client\Types\Converter\TextArrayConverter; -use Flow\PostgreSql\Client\Types\PostgreSqlType; +use Flow\PostgreSql\Client\Types\ValueType; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; @@ -67,8 +67,8 @@ public function test_supported_types() : void $converter = new TextArrayConverter(); $types = $converter->supportedTypes(); - self::assertContains(PostgreSqlType::TEXT_ARRAY, $types); - self::assertContains(PostgreSqlType::VARCHAR_ARRAY, $types); + self::assertContains(ValueType::TEXT_ARRAY, $types); + self::assertContains(ValueType::VARCHAR_ARRAY, $types); self::assertCount(2, $types); } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/TimeConverterTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/TimeConverterTest.php index be8a12cbf7..564343926f 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/TimeConverterTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/TimeConverterTest.php @@ -6,7 +6,7 @@ use Flow\PostgreSql\Client\Exception\ValueConversionException; use Flow\PostgreSql\Client\Types\Converter\TimeConverter; -use Flow\PostgreSql\Client\Types\PostgreSqlType; +use Flow\PostgreSql\Client\Types\ValueType; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; @@ -58,8 +58,8 @@ public function test_supported_types() : void $converter = new TimeConverter(); $types = $converter->supportedTypes(); - self::assertContains(PostgreSqlType::TIME, $types); - self::assertContains(PostgreSqlType::TIMETZ, $types); + self::assertContains(ValueType::TIME, $types); + self::assertContains(ValueType::TIMETZ, $types); } #[DataProvider('provide_valid_values')] diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/UuidArrayConverterTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/UuidArrayConverterTest.php index 469bd67dba..797a39ac2f 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/UuidArrayConverterTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/UuidArrayConverterTest.php @@ -6,7 +6,7 @@ use Flow\PostgreSql\Client\Exception\ValueConversionException; use Flow\PostgreSql\Client\Types\Converter\UuidArrayConverter; -use Flow\PostgreSql\Client\Types\PostgreSqlType; +use Flow\PostgreSql\Client\Types\ValueType; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; @@ -60,7 +60,7 @@ public function test_supported_types() : void $converter = new UuidArrayConverter(); $types = $converter->supportedTypes(); - self::assertContains(PostgreSqlType::UUID_ARRAY, $types); + self::assertContains(ValueType::UUID_ARRAY, $types); self::assertCount(1, $types); } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/UuidConverterTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/UuidConverterTest.php index 1c8945502e..0276928fc5 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/UuidConverterTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/Converter/UuidConverterTest.php @@ -6,7 +6,7 @@ use Flow\PostgreSql\Client\Exception\ValueConversionException; use Flow\PostgreSql\Client\Types\Converter\UuidConverter; -use Flow\PostgreSql\Client\Types\PostgreSqlType; +use Flow\PostgreSql\Client\Types\ValueType; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; @@ -64,7 +64,7 @@ public function __toString() : string public function test_supported_types() : void { $converter = new UuidConverter(); - self::assertContains(PostgreSqlType::UUID, $converter->supportedTypes()); + self::assertContains(ValueType::UUID, $converter->supportedTypes()); } #[DataProvider('provide_valid_values')] diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/ValueConvertersTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/ValueConvertersTest.php index a83c320948..22c36fec9d 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/ValueConvertersTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Client/Types/ValueConvertersTest.php @@ -5,7 +5,7 @@ namespace Flow\PostgreSql\Tests\Unit\Client\Types; use Flow\PostgreSql\Client\Types\Converter\{BooleanConverter, DateTimeConverter, IntArrayConverter, IntegerConverter, JsonConverter, StringConverter, TextArrayConverter, UuidArrayConverter, UuidConverter}; -use Flow\PostgreSql\Client\Types\{PostgreSqlType, PostgreSqlVersion, ValueConverter, ValueConverters}; +use Flow\PostgreSql\Client\Types\{PostgreSqlVersion, ValueConverter, ValueConverters, ValueType}; use PHPUnit\Framework\TestCase; final class ValueConvertersTest extends TestCase @@ -14,45 +14,45 @@ public function test_array_type_detection() : void { $converters = ValueConverters::create(); - self::assertTrue($converters->has(PostgreSqlType::INT4_ARRAY)); - self::assertTrue($converters->has(PostgreSqlType::TEXT_ARRAY)); - self::assertTrue($converters->has(PostgreSqlType::UUID_ARRAY)); + self::assertTrue($converters->has(ValueType::INT4_ARRAY)); + self::assertTrue($converters->has(ValueType::TEXT_ARRAY)); + self::assertTrue($converters->has(ValueType::UUID_ARRAY)); - self::assertInstanceOf(IntArrayConverter::class, $converters->forPostgreSqlType(PostgreSqlType::INT4_ARRAY)); - self::assertInstanceOf(TextArrayConverter::class, $converters->forPostgreSqlType(PostgreSqlType::TEXT_ARRAY)); - self::assertInstanceOf(UuidArrayConverter::class, $converters->forPostgreSqlType(PostgreSqlType::UUID_ARRAY)); + self::assertInstanceOf(IntArrayConverter::class, $converters->forValueType(ValueType::INT4_ARRAY)); + self::assertInstanceOf(TextArrayConverter::class, $converters->forValueType(ValueType::TEXT_ARRAY)); + self::assertInstanceOf(UuidArrayConverter::class, $converters->forValueType(ValueType::UUID_ARRAY)); } public function test_create_returns_default_converters() : void { $converters = ValueConverters::create(); - self::assertTrue($converters->has(PostgreSqlType::TEXT)); - self::assertTrue($converters->has(PostgreSqlType::INT4)); - self::assertTrue($converters->has(PostgreSqlType::BOOL)); - self::assertTrue($converters->has(PostgreSqlType::TIMESTAMP)); - self::assertTrue($converters->has(PostgreSqlType::UUID)); - self::assertTrue($converters->has(PostgreSqlType::JSON)); + self::assertTrue($converters->has(ValueType::TEXT)); + self::assertTrue($converters->has(ValueType::INT4)); + self::assertTrue($converters->has(ValueType::BOOL)); + self::assertTrue($converters->has(ValueType::TIMESTAMP)); + self::assertTrue($converters->has(ValueType::UUID)); + self::assertTrue($converters->has(ValueType::JSON)); } public function test_fallback_to_string_converter() : void { $converters = ValueConverters::create(); - $converter = $converters->forPostgreSqlType(PostgreSqlType::OID); + $converter = $converters->forValueType(ValueType::OID); self::assertInstanceOf(StringConverter::class, $converter); } - public function test_for_postgredata_type_returns_correct_converter() : void + public function test_for_postgrecolumn_type_returns_correct_converter() : void { $converters = ValueConverters::create(); - self::assertInstanceOf(StringConverter::class, $converters->forPostgreSqlType(PostgreSqlType::TEXT)); - self::assertInstanceOf(IntegerConverter::class, $converters->forPostgreSqlType(PostgreSqlType::INT4)); - self::assertInstanceOf(BooleanConverter::class, $converters->forPostgreSqlType(PostgreSqlType::BOOL)); - self::assertInstanceOf(DateTimeConverter::class, $converters->forPostgreSqlType(PostgreSqlType::TIMESTAMP)); - self::assertInstanceOf(UuidConverter::class, $converters->forPostgreSqlType(PostgreSqlType::UUID)); - self::assertInstanceOf(JsonConverter::class, $converters->forPostgreSqlType(PostgreSqlType::JSON)); + self::assertInstanceOf(StringConverter::class, $converters->forValueType(ValueType::TEXT)); + self::assertInstanceOf(IntegerConverter::class, $converters->forValueType(ValueType::INT4)); + self::assertInstanceOf(BooleanConverter::class, $converters->forValueType(ValueType::BOOL)); + self::assertInstanceOf(DateTimeConverter::class, $converters->forValueType(ValueType::TIMESTAMP)); + self::assertInstanceOf(UuidConverter::class, $converters->forValueType(ValueType::UUID)); + self::assertInstanceOf(JsonConverter::class, $converters->forValueType(ValueType::JSON)); } public function test_register_adds_custom_converter() : void @@ -62,7 +62,7 @@ public function test_register_adds_custom_converter() : void $customConverter = new class implements ValueConverter { public function supportedTypes() : array { - return [PostgreSqlType::XML]; + return [ValueType::XML]; } public function toDatabase(mixed $value) : ?string @@ -71,24 +71,24 @@ public function toDatabase(mixed $value) : ?string } }; - self::assertFalse($converters->has(PostgreSqlType::XML)); + self::assertFalse($converters->has(ValueType::XML)); $converters->register($customConverter); - self::assertTrue($converters->has(PostgreSqlType::XML)); - self::assertSame($customConverter, $converters->forPostgreSqlType(PostgreSqlType::XML)); + self::assertTrue($converters->has(ValueType::XML)); + self::assertSame($customConverter, $converters->forValueType(ValueType::XML)); } public function test_unregister_removes_converter() : void { $converters = ValueConverters::create(); - self::assertTrue($converters->has(PostgreSqlType::UUID)); + self::assertTrue($converters->has(ValueType::UUID)); - $converters->unregister(PostgreSqlType::UUID); + $converters->unregister(ValueType::UUID); - self::assertFalse($converters->has(PostgreSqlType::UUID)); - self::assertInstanceOf(StringConverter::class, $converters->forPostgreSqlType(PostgreSqlType::UUID)); + self::assertFalse($converters->has(ValueType::UUID)); + self::assertInstanceOf(StringConverter::class, $converters->forValueType(ValueType::UUID)); } public function test_version_specific_multirange_support() : void @@ -101,8 +101,8 @@ public function test_version_specific_multirange_support() : void self::assertTrue(PostgreSqlVersion::V14->supportsMultirange()); self::assertTrue(PostgreSqlVersion::V17->supportsMultirange()); - self::assertTrue($v13Converters->has(PostgreSqlType::TEXT)); - self::assertTrue($v14Converters->has(PostgreSqlType::TEXT)); - self::assertTrue($v17Converters->has(PostgreSqlType::TEXT)); + self::assertTrue($v13Converters->has(ValueType::TEXT)); + self::assertTrue($v14Converters->has(ValueType::TEXT)); + self::assertTrue($v17Converters->has(ValueType::TEXT)); } } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/DSL/ParametersTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/DSL/ParametersTest.php new file mode 100644 index 0000000000..d3b24c6f98 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/DSL/ParametersTest.php @@ -0,0 +1,63 @@ +number()); + self::assertSame(2, $params[1]->number()); + self::assertSame(3, $params[2]->number()); + } + + public function test_parameters_negative_count_throws() : void + { + $this->expectException(\InvalidArgumentException::class); + + parameters(-1); + } + + public function test_parameters_single() : void + { + $params = parameters(1); + + self::assertCount(1, $params); + self::assertInstanceOf(Parameter::class, $params[0]); + self::assertSame(1, $params[0]->number()); + } + + public function test_parameters_with_start_at() : void + { + $params = parameters(3, startAt: 4); + + self::assertCount(3, $params); + self::assertSame(4, $params[0]->number()); + self::assertSame(5, $params[1]->number()); + self::assertSame(6, $params[2]->number()); + } + + public function test_parameters_zero_count_throws() : void + { + $this->expectException(\InvalidArgumentException::class); + + parameters(0); + } + + public function test_parameters_zero_start_throws() : void + { + $this->expectException(\InvalidArgumentException::class); + + parameters(3, startAt: 0); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/DSL/StringCoercionTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/DSL/StringCoercionTest.php new file mode 100644 index 0000000000..c48e7bd96e --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/DSL/StringCoercionTest.php @@ -0,0 +1,190 @@ +from(table('orders'))->toSql(), + select(agg_sum('amount'))->from('orders')->toSql(), + ); + } + + public function test_asc_with_string_in_order_by() : void + { + self::assertSame( + select(star())->from(table('users'))->orderBy(asc(col('created_at')))->toSql(), + select(star())->from('users')->orderBy(asc('created_at'))->toSql(), + ); + } + + public function test_between_with_string_in_where() : void + { + self::assertSame( + select(star())->from(table('users'))->where(\Flow\PostgreSql\DSL\between(col('age'), literal(18), literal(65)))->toSql(), + select(star())->from('users')->where(\Flow\PostgreSql\DSL\between('age', literal(18), literal(65)))->toSql(), + ); + } + + public function test_cast_with_string_in_select() : void + { + self::assertSame( + select(\Flow\PostgreSql\DSL\cast(col('id'), \Flow\PostgreSql\QueryBuilder\Schema\ColumnType::integer()))->from(table('users'))->toSql(), + select(\Flow\PostgreSql\DSL\cast('id', \Flow\PostgreSql\QueryBuilder\Schema\ColumnType::integer()))->from('users')->toSql(), + ); + } + + public function test_coalesce_with_mixed_strings_in_select() : void + { + self::assertSame( + select(\Flow\PostgreSql\DSL\coalesce(col('name'), literal('unknown')))->from(table('users'))->toSql(), + select(\Flow\PostgreSql\DSL\coalesce('name', literal('unknown')))->from('users')->toSql(), + ); + } + + public function test_delete_using_with_string() : void + { + self::assertSame( + delete()->from('users')->using(table('orders'))->where(eq(col('users.id'), col('orders.user_id')))->toSql(), + delete()->from('users')->using('orders')->where(eq('users.id', 'orders.user_id'))->toSql(), + ); + } + + public function test_eq_with_strings_in_where() : void + { + self::assertSame( + select(star())->from(table('users'))->where(eq(col('status'), col('other')))->toSql(), + select(star())->from('users')->where(eq('status', 'other'))->toSql(), + ); + } + + public function test_from_with_schema_dot_table() : void + { + self::assertSame( + select(star())->from(table('users', 'public'))->toSql(), + select(star())->from('public.users')->toSql(), + ); + } + + public function test_from_with_string() : void + { + self::assertSame( + select(star())->from(table('users'))->toSql(), + select(star())->from('users')->toSql(), + ); + } + + public function test_full_query_with_string_coercion() : void + { + self::assertSame( + select(col('id'), col('name'), agg_sum(col('amount'))->as('total')) + ->from(table('orders')) + ->join(table('users'), eq(col('orders.user_id'), col('users.id'))) + ->where(eq(col('status'), literal('active'))) + ->groupBy(col('id'), col('name')) + ->orderBy(asc(col('name'))) + ->toSql(), + select('id', 'name', agg_sum('amount')->as('total')) + ->from('orders') + ->join('users', eq('orders.user_id', 'users.id')) + ->where(eq('status', literal('active'))) + ->groupBy('id', 'name') + ->orderBy(asc('name')) + ->toSql(), + ); + } + + public function test_group_by_with_strings() : void + { + self::assertSame( + select(star())->from(table('users'))->groupBy(col('category'), col('status'))->toSql(), + select(star())->from('users')->groupBy('category', 'status')->toSql(), + ); + } + + public function test_is_null_with_string_in_where() : void + { + self::assertSame( + select(star())->from(table('users'))->where(\Flow\PostgreSql\DSL\is_null(col('email')))->toSql(), + select(star())->from('users')->where(\Flow\PostgreSql\DSL\is_null('email'))->toSql(), + ); + } + + public function test_join_with_string_table() : void + { + self::assertSame( + select(star())->from(table('users'))->join(table('orders'), eq(col('users.id'), col('orders.user_id')))->toSql(), + select(star())->from('users')->join('orders', eq('users.id', 'orders.user_id'))->toSql(), + ); + } + + public function test_left_join_with_string_table() : void + { + self::assertSame( + select(star())->from(table('users'))->leftJoin(table('orders'), eq(col('users.id'), col('orders.user_id')))->toSql(), + select(star())->from('users')->leftJoin('orders', eq('users.id', 'orders.user_id'))->toSql(), + ); + } + + public function test_like_with_string_in_where() : void + { + self::assertSame( + select(star())->from(table('users'))->where(\Flow\PostgreSql\DSL\like(col('name'), literal('%test%')))->toSql(), + select(star())->from('users')->where(\Flow\PostgreSql\DSL\like('name', literal('%test%')))->toSql(), + ); + } + + public function test_nullif_with_strings_in_select() : void + { + self::assertSame( + select(\Flow\PostgreSql\DSL\nullif(col('a'), col('b')))->from(table('users'))->toSql(), + select(\Flow\PostgreSql\DSL\nullif('a', 'b'))->from('users')->toSql(), + ); + } + + public function test_returning_with_strings_in_delete() : void + { + self::assertSame( + delete()->from('users')->where(eq(col('id'), literal(1)))->returning(col('id'), col('name'))->toSql(), + delete()->from('users')->where(eq('id', literal(1)))->returning(col('id'), col('name'))->toSql(), + ); + } + + public function test_select_mixed_strings_and_expressions() : void + { + self::assertSame( + select(col('id'), col('name')->as('n'))->from(table('users'))->toSql(), + select('id', col('name')->as('n'))->from(table('users'))->toSql(), + ); + } + + public function test_select_with_strings_produces_same_sql_as_col() : void + { + self::assertSame( + select(col('id'), col('name'))->from(table('users'))->toSql(), + select('id', 'name')->from(table('users'))->toSql(), + ); + } + + public function test_update_from_with_string() : void + { + self::assertSame( + update()->update('users')->set('name', literal('test'))->from(table('logs'))->where(eq(col('users.id'), col('logs.user_id')))->toSql(), + update()->update('users')->set('name', literal('test'))->from('logs')->where(eq('users.id', 'logs.user_id'))->toSql(), + ); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/NamedParameterNormalizerTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/NamedParameterNormalizerTest.php index b1bb1ec1e3..f4e5d2dc29 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/NamedParameterNormalizerTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/NamedParameterNormalizerTest.php @@ -63,7 +63,7 @@ public function test_normalize_parameters_with_underscores() : void ); } - public function test_normalize_preserves_postgredata_type_casts() : void + public function test_normalize_preserves_postgrecolumn_type_casts() : void { $normalizer = new NamedParameterNormalizer(); diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Parser/ColumnTypeParserTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Parser/ColumnTypeParserTest.php new file mode 100644 index 0000000000..e9e0a8febf --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Parser/ColumnTypeParserTest.php @@ -0,0 +1,266 @@ +toAst()->serializeToString(), + column_type_from_string('bigint')->toAst()->serializeToString() + ); + } + + public function test_parse_boolean() : void + { + self::assertSame( + ColumnType::boolean()->toAst()->serializeToString(), + column_type_from_string('boolean')->toAst()->serializeToString() + ); + } + + public function test_parse_bytea() : void + { + $ast = column_type_from_string('bytea')->toAst(); + + self::assertCount(1, $ast->getNames()); + self::assertSame('bytea', $ast->getNames()[0]->getString()->getSval()); + } + + public function test_parse_char_with_length() : void + { + self::assertSame( + ColumnType::char(10)->toAst()->serializeToString(), + column_type_from_string('character(10)')->toAst()->serializeToString() + ); + } + + public function test_parse_cidr() : void + { + $ast = column_type_from_string('cidr')->toAst(); + + self::assertCount(1, $ast->getNames()); + self::assertSame('cidr', $ast->getNames()[0]->getString()->getSval()); + } + + public function test_parse_custom_type() : void + { + $ast = column_type_from_string('my_custom_type')->toAst(); + + self::assertCount(1, $ast->getNames()); + self::assertSame('my_custom_type', $ast->getNames()[0]->getString()->getSval()); + } + + public function test_parse_date() : void + { + $ast = column_type_from_string('date')->toAst(); + + self::assertCount(1, $ast->getNames()); + self::assertSame('date', $ast->getNames()[0]->getString()->getSval()); + } + + public function test_parse_double_precision() : void + { + self::assertSame( + ColumnType::doublePrecision()->toAst()->serializeToString(), + column_type_from_string('double precision')->toAst()->serializeToString() + ); + } + + public function test_parse_empty_throws_exception() : void + { + $this->expectException(\InvalidArgumentException::class); + + column_type_from_string(''); + } + + public function test_parse_inet() : void + { + $ast = column_type_from_string('inet')->toAst(); + + self::assertCount(1, $ast->getNames()); + self::assertSame('inet', $ast->getNames()[0]->getString()->getSval()); + } + + public function test_parse_integer() : void + { + self::assertSame( + ColumnType::integer()->toAst()->serializeToString(), + column_type_from_string('integer')->toAst()->serializeToString() + ); + } + + public function test_parse_integer_array() : void + { + $ast = column_type_from_string('integer[]')->toAst(); + $names = $ast->getNames(); + + self::assertCount(2, $names); + self::assertSame('pg_catalog', $names[0]->getString()->getSval()); + self::assertSame('int4', $names[1]->getString()->getSval()); + self::assertCount(1, $ast->getArrayBounds()); + } + + public function test_parse_interval() : void + { + self::assertSame( + ColumnType::interval()->toAst()->serializeToString(), + column_type_from_string('interval')->toAst()->serializeToString() + ); + } + + public function test_parse_json() : void + { + self::assertSame( + ColumnType::json()->toAst()->serializeToString(), + column_type_from_string('json')->toAst()->serializeToString() + ); + } + + public function test_parse_jsonb() : void + { + $ast = column_type_from_string('jsonb')->toAst(); + + self::assertCount(1, $ast->getNames()); + self::assertSame('jsonb', $ast->getNames()[0]->getString()->getSval()); + } + + public function test_parse_macaddr() : void + { + $ast = column_type_from_string('macaddr')->toAst(); + + self::assertCount(1, $ast->getNames()); + self::assertSame('macaddr', $ast->getNames()[0]->getString()->getSval()); + } + + public function test_parse_numeric() : void + { + self::assertSame( + ColumnType::numeric()->toAst()->serializeToString(), + column_type_from_string('numeric')->toAst()->serializeToString() + ); + } + + public function test_parse_numeric_with_precision_and_scale() : void + { + self::assertSame( + ColumnType::numeric(10, 2)->toAst()->serializeToString(), + column_type_from_string('numeric(10,2)')->toAst()->serializeToString() + ); + } + + public function test_parse_real() : void + { + self::assertSame( + ColumnType::real()->toAst()->serializeToString(), + column_type_from_string('real')->toAst()->serializeToString() + ); + } + + public function test_parse_schema_qualified_custom_type() : void + { + $ast = column_type_from_string('my_schema.my_type')->toAst(); + $names = $ast->getNames(); + + self::assertCount(2, $names); + self::assertSame('my_schema', $names[0]->getString()->getSval()); + self::assertSame('my_type', $names[1]->getString()->getSval()); + } + + public function test_parse_smallint() : void + { + self::assertSame( + ColumnType::smallint()->toAst()->serializeToString(), + column_type_from_string('smallint')->toAst()->serializeToString() + ); + } + + public function test_parse_text() : void + { + $ast = column_type_from_string('text')->toAst(); + + self::assertCount(1, $ast->getNames()); + self::assertSame('text', $ast->getNames()[0]->getString()->getSval()); + } + + public function test_parse_text_array() : void + { + $ast = column_type_from_string('text[]')->toAst(); + $names = $ast->getNames(); + + self::assertCount(1, $names); + self::assertSame('text', $names[0]->getString()->getSval()); + self::assertCount(1, $ast->getArrayBounds()); + } + + public function test_parse_time_with_precision() : void + { + self::assertSame( + ColumnType::time(3)->toAst()->serializeToString(), + column_type_from_string('time(3) without time zone')->toAst()->serializeToString() + ); + } + + public function test_parse_timestamp() : void + { + self::assertSame( + ColumnType::timestamp()->toAst()->serializeToString(), + column_type_from_string('timestamp without time zone')->toAst()->serializeToString() + ); + } + + public function test_parse_timestamp_with_precision() : void + { + self::assertSame( + ColumnType::timestamp(6)->toAst()->serializeToString(), + column_type_from_string('timestamp(6) without time zone')->toAst()->serializeToString() + ); + } + + public function test_parse_timestamptz() : void + { + self::assertSame( + ColumnType::timestamptz()->toAst()->serializeToString(), + column_type_from_string('timestamp with time zone')->toAst()->serializeToString() + ); + } + + public function test_parse_timestamptz_with_precision() : void + { + self::assertSame( + ColumnType::timestamptz(3)->toAst()->serializeToString(), + column_type_from_string('timestamp(3) with time zone')->toAst()->serializeToString() + ); + } + + public function test_parse_uuid() : void + { + $ast = column_type_from_string('uuid')->toAst(); + + self::assertCount(1, $ast->getNames()); + self::assertSame('uuid', $ast->getNames()[0]->getString()->getSval()); + } + + public function test_parse_varchar_with_length() : void + { + self::assertSame( + ColumnType::varchar(255)->toAst()->serializeToString(), + column_type_from_string('character varying(255)')->toAst()->serializeToString() + ); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/AndConditionTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/AndConditionTest.php index a4395f7beb..e48fea99dd 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/AndConditionTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/AndConditionTest.php @@ -4,9 +4,11 @@ namespace Flow\PostgreSql\Tests\Unit\QueryBuilder\Condition; +use function Flow\PostgreSql\DSL\{col, eq, literal}; use Flow\PostgreSql\Protobuf\AST\{BoolExpr, BoolExprType, Node}; -use Flow\PostgreSql\QueryBuilder\Condition\{AndCondition, NotCondition, OrCondition, RawCondition}; +use Flow\PostgreSql\QueryBuilder\Condition\{AndCondition, NotCondition, OrCondition}; use Flow\PostgreSql\QueryBuilder\Exception\InvalidAstException; + use PHPUnit\Framework\TestCase; final class AndConditionTest extends TestCase @@ -20,9 +22,9 @@ protected function setUp() : void public function test_and_flattens_multiple_and_conditions() : void { - $cond1 = new RawCondition('x = 1'); - $cond2 = new RawCondition('y = 2'); - $cond3 = new RawCondition('z = 3'); + $cond1 = eq(col('x'), literal(1)); + $cond2 = eq(col('y'), literal(2)); + $cond3 = eq(col('z'), literal(3)); $and1 = new AndCondition($cond1, $cond2); $and2 = $and1->and($cond3); @@ -39,8 +41,8 @@ public function test_and_flattens_multiple_and_conditions() : void public function test_and_method_returns_new_instance() : void { - $cond1 = new RawCondition('x = 1'); - $cond2 = new RawCondition('y = 2'); + $cond1 = eq(col('x'), literal(1)); + $cond2 = eq(col('y'), literal(2)); $original = new AndCondition($cond1); $modified = $original->and($cond2); @@ -50,10 +52,10 @@ public function test_and_method_returns_new_instance() : void public function test_and_with_another_and_condition_flattens() : void { - $cond1 = new RawCondition('a = 1'); - $cond2 = new RawCondition('b = 2'); - $cond3 = new RawCondition('c = 3'); - $cond4 = new RawCondition('d = 4'); + $cond1 = eq(col('a'), literal(1)); + $cond2 = eq(col('b'), literal(2)); + $cond3 = eq(col('c'), literal(3)); + $cond4 = eq(col('d'), literal(4)); $and1 = new AndCondition($cond1, $cond2); $and2 = new AndCondition($cond3, $cond4); @@ -70,8 +72,8 @@ public function test_and_with_another_and_condition_flattens() : void public function test_and_with_single_condition() : void { - $cond1 = new RawCondition('x = 1'); - $cond2 = new RawCondition('y = 2'); + $cond1 = eq(col('x'), literal(1)); + $cond2 = eq(col('y'), literal(2)); $and = new AndCondition($cond1, $cond2); $ast = $and->toAst(); @@ -99,8 +101,8 @@ public function test_empty_and_condition() : void public function test_from_ast_reconstructs_and_condition() : void { - $cond1 = new RawCondition('x = 1'); - $cond2 = new RawCondition('y = 2'); + $cond1 = eq(col('x'), literal(1)); + $cond2 = eq(col('y'), literal(2)); $original = new AndCondition($cond1, $cond2); $ast = $original->toAst(); @@ -142,8 +144,8 @@ public function test_from_ast_throws_on_wrong_bool_type() : void public function test_not_returns_not_condition() : void { - $cond1 = new RawCondition('x = 1'); - $cond2 = new RawCondition('y = 2'); + $cond1 = eq(col('x'), literal(1)); + $cond2 = eq(col('y'), literal(2)); $and = new AndCondition($cond1, $cond2); $not = $and->not(); @@ -153,9 +155,9 @@ public function test_not_returns_not_condition() : void public function test_or_returns_or_condition() : void { - $cond1 = new RawCondition('x = 1'); - $cond2 = new RawCondition('y = 2'); - $cond3 = new RawCondition('z = 3'); + $cond1 = eq(col('x'), literal(1)); + $cond2 = eq(col('y'), literal(2)); + $cond3 = eq(col('z'), literal(3)); $and = new AndCondition($cond1, $cond2); $or = $and->or($cond3); @@ -165,8 +167,8 @@ public function test_or_returns_or_condition() : void public function test_to_ast_creates_bool_expr() : void { - $cond1 = new RawCondition('x = 1'); - $cond2 = new RawCondition('y = 2'); + $cond1 = eq(col('x'), literal(1)); + $cond2 = eq(col('y'), literal(2)); $and = new AndCondition($cond1, $cond2); $ast = $and->toAst(); diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/ConditionBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/ConditionBuilderTest.php index 03ea39542e..810b88200e 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/ConditionBuilderTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/ConditionBuilderTest.php @@ -4,7 +4,7 @@ namespace Flow\PostgreSql\Tests\Unit\QueryBuilder\Condition; -use function Flow\PostgreSql\DSL\{conditions, raw_cond}; +use function Flow\PostgreSql\DSL\{col, conditions, eq, literal}; use Flow\PostgreSql\Protobuf\AST\BoolExprType; use Flow\PostgreSql\QueryBuilder\Condition\{AndCondition, ConditionBuilder, OrCondition}; use PHPUnit\Framework\TestCase; @@ -20,7 +20,7 @@ protected function setUp() : void public function test_and_on_empty_builder_returns_new_builder_with_condition() : void { - $cond = raw_cond('x = 1'); + $cond = eq(col('x'), literal(1)); $builder = ConditionBuilder::create(); $result = $builder->and($cond); @@ -31,8 +31,8 @@ public function test_and_on_empty_builder_returns_new_builder_with_condition() : public function test_builder_is_immutable() : void { - $cond1 = raw_cond('x = 1'); - $cond2 = raw_cond('y = 2'); + $cond1 = eq(col('x'), literal(1)); + $cond2 = eq(col('y'), literal(2)); $original = ConditionBuilder::create(); $modified = $original->and($cond1); @@ -53,7 +53,7 @@ public function test_empty_builder_is_empty() : void public function test_empty_nested_builder_is_ignored_in_and() : void { - $cond = raw_cond('x = 1'); + $cond = eq(col('x'), literal(1)); $emptyBuilder = conditions(); $builder = conditions() @@ -66,7 +66,7 @@ public function test_empty_nested_builder_is_ignored_in_and() : void public function test_empty_nested_builder_is_ignored_in_or() : void { - $cond = raw_cond('x = 1'); + $cond = eq(col('x'), literal(1)); $emptyBuilder = conditions(); $builder = conditions() @@ -79,9 +79,9 @@ public function test_empty_nested_builder_is_ignored_in_or() : void public function test_mixing_and_then_or() : void { - $cond1 = raw_cond('x = 1'); - $cond2 = raw_cond('y = 2'); - $cond3 = raw_cond('z = 3'); + $cond1 = eq(col('x'), literal(1)); + $cond2 = eq(col('y'), literal(2)); + $cond3 = eq(col('z'), literal(3)); $builder = conditions() ->and($cond1) @@ -94,9 +94,9 @@ public function test_mixing_and_then_or() : void public function test_mixing_or_then_and() : void { - $cond1 = raw_cond('x = 1'); - $cond2 = raw_cond('y = 2'); - $cond3 = raw_cond('z = 3'); + $cond1 = eq(col('x'), literal(1)); + $cond2 = eq(col('y'), literal(2)); + $cond3 = eq(col('z'), literal(3)); $builder = conditions() ->or($cond1) @@ -109,9 +109,9 @@ public function test_mixing_or_then_and() : void public function test_multiple_and_conditions() : void { - $cond1 = raw_cond('x = 1'); - $cond2 = raw_cond('y = 2'); - $cond3 = raw_cond('z = 3'); + $cond1 = eq(col('x'), literal(1)); + $cond2 = eq(col('y'), literal(2)); + $cond3 = eq(col('z'), literal(3)); $builder = conditions() ->and($cond1) @@ -134,9 +134,9 @@ public function test_multiple_and_conditions() : void public function test_multiple_or_conditions() : void { - $cond1 = raw_cond('x = 1'); - $cond2 = raw_cond('y = 2'); - $cond3 = raw_cond('z = 3'); + $cond1 = eq(col('x'), literal(1)); + $cond2 = eq(col('y'), literal(2)); + $cond3 = eq(col('z'), literal(3)); $builder = conditions() ->or($cond1) @@ -159,9 +159,9 @@ public function test_multiple_or_conditions() : void public function test_nested_builder_via_and() : void { - $cond1 = raw_cond('x = 1'); - $cond2 = raw_cond('y = 2'); - $cond3 = raw_cond('z = 3'); + $cond1 = eq(col('x'), literal(1)); + $cond2 = eq(col('y'), literal(2)); + $cond3 = eq(col('z'), literal(3)); $nestedBuilder = conditions() ->or($cond2) @@ -179,9 +179,9 @@ public function test_nested_builder_via_and() : void public function test_nested_builder_via_or() : void { - $cond1 = raw_cond('x = 1'); - $cond2 = raw_cond('y = 2'); - $cond3 = raw_cond('z = 3'); + $cond1 = eq(col('x'), literal(1)); + $cond2 = eq(col('y'), literal(2)); + $cond3 = eq(col('z'), literal(3)); $nestedBuilder = conditions() ->and($cond2) @@ -199,7 +199,7 @@ public function test_nested_builder_via_or() : void public function test_or_on_empty_builder_returns_new_builder_with_condition() : void { - $cond = raw_cond('x = 1'); + $cond = eq(col('x'), literal(1)); $builder = conditions(); $result = $builder->or($cond); @@ -210,7 +210,7 @@ public function test_or_on_empty_builder_returns_new_builder_with_condition() : public function test_single_condition_via_and() : void { - $cond = raw_cond('x = 1'); + $cond = eq(col('x'), literal(1)); $builder = conditions()->and($cond); self::assertFalse($builder->isEmpty()); @@ -219,7 +219,7 @@ public function test_single_condition_via_and() : void public function test_single_condition_via_or() : void { - $cond = raw_cond('x = 1'); + $cond = eq(col('x'), literal(1)); $builder = conditions()->or($cond); self::assertFalse($builder->isEmpty()); diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/NotConditionTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/NotConditionTest.php index 57f286dde0..21537bc228 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/NotConditionTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/NotConditionTest.php @@ -4,9 +4,11 @@ namespace Flow\PostgreSql\Tests\Unit\QueryBuilder\Condition; +use function Flow\PostgreSql\DSL\{col, eq, literal}; use Flow\PostgreSql\Protobuf\AST\{BoolExpr, BoolExprType, Node}; -use Flow\PostgreSql\QueryBuilder\Condition\{AndCondition, NotCondition, OrCondition, RawCondition}; +use Flow\PostgreSql\QueryBuilder\Condition\{AndCondition, NotCondition, OrCondition}; use Flow\PostgreSql\QueryBuilder\Exception\InvalidAstException; + use PHPUnit\Framework\TestCase; final class NotConditionTest extends TestCase @@ -20,8 +22,8 @@ protected function setUp() : void public function test_and_returns_and_condition() : void { - $cond1 = new RawCondition('x = 1'); - $cond2 = new RawCondition('y = 2'); + $cond1 = eq(col('x'), literal(1)); + $cond2 = eq(col('y'), literal(2)); $not = new NotCondition($cond1); $and = $not->and($cond2); @@ -31,7 +33,7 @@ public function test_and_returns_and_condition() : void public function test_double_negation() : void { - $cond = new RawCondition('x = 1'); + $cond = eq(col('x'), literal(1)); $not1 = new NotCondition($cond); $not2 = $not1->not(); @@ -54,7 +56,7 @@ public function test_double_negation() : void public function test_from_ast_reconstructs_not_condition() : void { - $cond = new RawCondition('x = 1'); + $cond = eq(col('x'), literal(1)); $original = new NotCondition($cond); $ast = $original->toAst(); @@ -91,8 +93,8 @@ public function test_from_ast_throws_on_multiple_args() : void $this->expectException(InvalidAstException::class); $this->expectExceptionMessage('NOT_EXPR must have exactly one argument, got 2'); - $cond1 = new RawCondition('x = 1'); - $cond2 = new RawCondition('y = 2'); + $cond1 = eq(col('x'), literal(1)); + $cond2 = eq(col('y'), literal(2)); $boolExpr = new BoolExpr(); $boolExpr->setBoolop(BoolExprType::NOT_EXPR); @@ -129,7 +131,7 @@ public function test_from_ast_throws_on_wrong_bool_type() : void public function test_not_negates_condition() : void { - $cond = new RawCondition('x = 1'); + $cond = eq(col('x'), literal(1)); $not = new NotCondition($cond); $ast = $not->toAst(); @@ -143,7 +145,7 @@ public function test_not_negates_condition() : void public function test_not_returns_not_condition() : void { - $cond = new RawCondition('x = 1'); + $cond = eq(col('x'), literal(1)); $not = new NotCondition($cond); $notNot = $not->not(); @@ -152,8 +154,8 @@ public function test_not_returns_not_condition() : void public function test_or_returns_or_condition() : void { - $cond1 = new RawCondition('x = 1'); - $cond2 = new RawCondition('y = 2'); + $cond1 = eq(col('x'), literal(1)); + $cond2 = eq(col('y'), literal(2)); $not = new NotCondition($cond1); $or = $not->or($cond2); @@ -163,7 +165,7 @@ public function test_or_returns_or_condition() : void public function test_to_ast_creates_bool_expr() : void { - $cond = new RawCondition('x = 1'); + $cond = eq(col('x'), literal(1)); $not = new NotCondition($cond); $ast = $not->toAst(); diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/OperatorConditionTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/OperatorConditionTest.php similarity index 72% rename from src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/OperatorConditionTest.php rename to src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/OperatorConditionTest.php index a49c6da350..a991ca1a53 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/OperatorConditionTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/OperatorConditionTest.php @@ -2,13 +2,15 @@ declare(strict_types=1); -namespace Flow\PostgreSql\Tests\Integration\QueryBuilder; +namespace Flow\PostgreSql\Tests\Unit\QueryBuilder\Condition; use function Flow\PostgreSql\DSL\{ array_contained_by, array_contains, + array_expr, array_overlap, col, + func, json_contained_by, json_contains, json_exists, @@ -21,7 +23,6 @@ literal, not_regex_imatch, not_regex_match, - raw_expr, regex_imatch, regex_match, select, @@ -30,18 +31,20 @@ text_search_match }; -final class OperatorConditionTest extends PGQueryTestCase +use PHPUnit\Framework\TestCase; + +final class OperatorConditionTest extends TestCase { public function test_array_contained_by() : void { $query = select() ->select(star()) ->from(table('products')) - ->where(array_contained_by(col('tags'), raw_expr("ARRAY['sale', 'featured', 'new']"))); + ->where(array_contained_by(col('tags'), array_expr([literal('sale'), literal('featured'), literal('new')]))); - $this->assertSelectQueryRoundTrip( - $query, - "SELECT * FROM products WHERE tags <@ ARRAY['sale', 'featured', 'new']" + self::assertSame( + "SELECT * FROM products WHERE tags <@ ARRAY['sale', 'featured', 'new']", + $query->toSql() ); } @@ -50,11 +53,11 @@ public function test_array_contains() : void $query = select() ->select(star()) ->from(table('products')) - ->where(array_contains(col('tags'), raw_expr("ARRAY['sale']"))); + ->where(array_contains(col('tags'), array_expr([literal('sale')]))); - $this->assertSelectQueryRoundTrip( - $query, - "SELECT * FROM products WHERE tags @> ARRAY['sale']" + self::assertSame( + "SELECT * FROM products WHERE tags @> ARRAY['sale']", + $query->toSql() ); } @@ -63,11 +66,11 @@ public function test_array_overlap() : void $query = select() ->select(star()) ->from(table('products')) - ->where(array_overlap(col('tags'), raw_expr("ARRAY['sale', 'featured']"))); + ->where(array_overlap(col('tags'), array_expr([literal('sale'), literal('featured')]))); - $this->assertSelectQueryRoundTrip( - $query, - "SELECT * FROM products WHERE tags && ARRAY['sale', 'featured']" + self::assertSame( + "SELECT * FROM products WHERE tags && ARRAY['sale', 'featured']", + $query->toSql() ); } @@ -78,9 +81,9 @@ public function test_json_contained_by() : void ->from(table('products')) ->where(json_contained_by(col('metadata'), literal('{"category": "electronics", "price": 100}'))); - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT * FROM products WHERE metadata <@ \'{"category": "electronics", "price": 100}\'' + self::assertSame( + 'SELECT * FROM products WHERE metadata <@ \'{"category": "electronics", "price": 100}\'', + $query->toSql() ); } @@ -91,9 +94,9 @@ public function test_json_contains() : void ->from(table('products')) ->where(json_contains(col('metadata'), literal('{"category": "electronics"}'))); - $this->assertSelectQueryRoundTrip( - $query, - 'SELECT * FROM products WHERE metadata @> \'{"category": "electronics"}\'' + self::assertSame( + 'SELECT * FROM products WHERE metadata @> \'{"category": "electronics"}\'', + $query->toSql() ); } @@ -104,9 +107,9 @@ public function test_json_exists() : void ->from(table('products')) ->where(json_exists(col('metadata'), literal('category'))); - $this->assertSelectQueryRoundTrip( - $query, - "SELECT * FROM products WHERE metadata ? 'category'" + self::assertSame( + "SELECT * FROM products WHERE metadata ? 'category'", + $query->toSql() ); } @@ -115,11 +118,11 @@ public function test_json_exists_all() : void $query = select() ->select(star()) ->from(table('products')) - ->where(json_exists_all(col('metadata'), raw_expr("array['category', 'name']"))); + ->where(json_exists_all(col('metadata'), array_expr([literal('category'), literal('name')]))); - $this->assertSelectQueryRoundTrip( - $query, - "SELECT * FROM products WHERE metadata ?& ARRAY['category', 'name']" + self::assertSame( + "SELECT * FROM products WHERE metadata ?& ARRAY['category', 'name']", + $query->toSql() ); } @@ -128,11 +131,11 @@ public function test_json_exists_any() : void $query = select() ->select(star()) ->from(table('products')) - ->where(json_exists_any(col('metadata'), raw_expr("array['category', 'name']"))); + ->where(json_exists_any(col('metadata'), array_expr([literal('category'), literal('name')]))); - $this->assertSelectQueryRoundTrip( - $query, - "SELECT * FROM products WHERE metadata ?| ARRAY['category', 'name']" + self::assertSame( + "SELECT * FROM products WHERE metadata ?| ARRAY['category', 'name']", + $query->toSql() ); } @@ -142,9 +145,9 @@ public function test_json_get() : void ->select(json_get(col('metadata'), literal('category'))->as('category')) ->from(table('products')); - $this->assertSelectQueryRoundTrip( - $query, - "SELECT metadata -> 'category' AS category FROM products" + self::assertSame( + "SELECT metadata -> 'category' AS category FROM products", + $query->toSql() ); } @@ -154,9 +157,9 @@ public function test_json_get_text() : void ->select(json_get_text(col('metadata'), literal('name'))->as('product_name')) ->from(table('products')); - $this->assertSelectQueryRoundTrip( - $query, - "SELECT metadata ->> 'name' AS product_name FROM products" + self::assertSame( + "SELECT metadata ->> 'name' AS product_name FROM products", + $query->toSql() ); } @@ -166,9 +169,9 @@ public function test_json_path() : void ->select(json_path(col('metadata'), literal('{category,name}'))->as('nested')) ->from(table('products')); - $this->assertSelectQueryRoundTrip( - $query, - "SELECT metadata #> '{category,name}' AS nested FROM products" + self::assertSame( + "SELECT metadata #> '{category,name}' AS nested FROM products", + $query->toSql() ); } @@ -178,9 +181,9 @@ public function test_json_path_text() : void ->select(json_path_text(col('metadata'), literal('{category,name}'))->as('nested_text')) ->from(table('products')); - $this->assertSelectQueryRoundTrip( - $query, - "SELECT metadata #>> '{category,name}' AS nested_text FROM products" + self::assertSame( + "SELECT metadata #>> '{category,name}' AS nested_text FROM products", + $query->toSql() ); } @@ -191,9 +194,9 @@ public function test_not_regex_imatch() : void ->from(table('users')) ->where(not_regex_imatch(col('email'), literal('.*@spam\\.com'))); - $this->assertSelectQueryRoundTrip( - $query, - "SELECT * FROM users WHERE email !~* E'.*@spam\\\\.com'" + self::assertSame( + "SELECT * FROM users WHERE email !~* E'.*@spam\\\\.com'", + $query->toSql() ); } @@ -204,9 +207,9 @@ public function test_not_regex_match() : void ->from(table('users')) ->where(not_regex_match(col('email'), literal('.*@spam\\.com'))); - $this->assertSelectQueryRoundTrip( - $query, - "SELECT * FROM users WHERE email !~ E'.*@spam\\\\.com'" + self::assertSame( + "SELECT * FROM users WHERE email !~ E'.*@spam\\\\.com'", + $query->toSql() ); } @@ -217,9 +220,9 @@ public function test_regex_imatch() : void ->from(table('users')) ->where(regex_imatch(col('email'), literal('.*@gmail\\.com'))); - $this->assertSelectQueryRoundTrip( - $query, - "SELECT * FROM users WHERE email ~* E'.*@gmail\\\\.com'" + self::assertSame( + "SELECT * FROM users WHERE email ~* E'.*@gmail\\\\.com'", + $query->toSql() ); } @@ -230,9 +233,9 @@ public function test_regex_match() : void ->from(table('users')) ->where(regex_match(col('email'), literal('.*@gmail\\.com'))); - $this->assertSelectQueryRoundTrip( - $query, - "SELECT * FROM users WHERE email ~ E'.*@gmail\\\\.com'" + self::assertSame( + "SELECT * FROM users WHERE email ~ E'.*@gmail\\\\.com'", + $query->toSql() ); } @@ -241,11 +244,11 @@ public function test_text_search_match() : void $query = select() ->select(star()) ->from(table('documents')) - ->where(text_search_match(col('content'), raw_expr("to_tsquery('english', 'hello & world')"))); + ->where(text_search_match(col('content'), func('to_tsquery', [literal('english'), literal('hello & world')]))); - $this->assertSelectQueryRoundTrip( - $query, - "SELECT * FROM documents WHERE content @@ to_tsquery('english', 'hello & world')" + self::assertSame( + "SELECT * FROM documents WHERE content @@ to_tsquery('english', 'hello & world')", + $query->toSql() ); } } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/OrConditionTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/OrConditionTest.php index daec5c418e..27dd201825 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/OrConditionTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/OrConditionTest.php @@ -4,9 +4,11 @@ namespace Flow\PostgreSql\Tests\Unit\QueryBuilder\Condition; +use function Flow\PostgreSql\DSL\{col, eq, literal}; use Flow\PostgreSql\Protobuf\AST\{BoolExpr, BoolExprType, Node}; -use Flow\PostgreSql\QueryBuilder\Condition\{AndCondition, NotCondition, OrCondition, RawCondition}; +use Flow\PostgreSql\QueryBuilder\Condition\{AndCondition, NotCondition, OrCondition}; use Flow\PostgreSql\QueryBuilder\Exception\InvalidAstException; + use PHPUnit\Framework\TestCase; final class OrConditionTest extends TestCase @@ -20,9 +22,9 @@ protected function setUp() : void public function test_and_returns_and_condition() : void { - $cond1 = new RawCondition('x = 1'); - $cond2 = new RawCondition('y = 2'); - $cond3 = new RawCondition('z = 3'); + $cond1 = eq(col('x'), literal(1)); + $cond2 = eq(col('y'), literal(2)); + $cond3 = eq(col('z'), literal(3)); $or = new OrCondition($cond1, $cond2); $and = $or->and($cond3); @@ -45,8 +47,8 @@ public function test_empty_or_condition() : void public function test_from_ast_reconstructs_or_condition() : void { - $cond1 = new RawCondition('x = 1'); - $cond2 = new RawCondition('y = 2'); + $cond1 = eq(col('x'), literal(1)); + $cond2 = eq(col('y'), literal(2)); $original = new OrCondition($cond1, $cond2); $ast = $original->toAst(); @@ -88,8 +90,8 @@ public function test_from_ast_throws_on_wrong_bool_type() : void public function test_not_returns_not_condition() : void { - $cond1 = new RawCondition('x = 1'); - $cond2 = new RawCondition('y = 2'); + $cond1 = eq(col('x'), literal(1)); + $cond2 = eq(col('y'), literal(2)); $or = new OrCondition($cond1, $cond2); $not = $or->not(); @@ -99,9 +101,9 @@ public function test_not_returns_not_condition() : void public function test_or_flattens_multiple_or_conditions() : void { - $cond1 = new RawCondition('x = 1'); - $cond2 = new RawCondition('y = 2'); - $cond3 = new RawCondition('z = 3'); + $cond1 = eq(col('x'), literal(1)); + $cond2 = eq(col('y'), literal(2)); + $cond3 = eq(col('z'), literal(3)); $or1 = new OrCondition($cond1, $cond2); $or2 = $or1->or($cond3); @@ -118,8 +120,8 @@ public function test_or_flattens_multiple_or_conditions() : void public function test_or_method_returns_new_instance() : void { - $cond1 = new RawCondition('x = 1'); - $cond2 = new RawCondition('y = 2'); + $cond1 = eq(col('x'), literal(1)); + $cond2 = eq(col('y'), literal(2)); $original = new OrCondition($cond1); $modified = $original->or($cond2); @@ -129,10 +131,10 @@ public function test_or_method_returns_new_instance() : void public function test_or_with_another_or_condition_flattens() : void { - $cond1 = new RawCondition('a = 1'); - $cond2 = new RawCondition('b = 2'); - $cond3 = new RawCondition('c = 3'); - $cond4 = new RawCondition('d = 4'); + $cond1 = eq(col('a'), literal(1)); + $cond2 = eq(col('b'), literal(2)); + $cond3 = eq(col('c'), literal(3)); + $cond4 = eq(col('d'), literal(4)); $or1 = new OrCondition($cond1, $cond2); $or2 = new OrCondition($cond3, $cond4); @@ -149,8 +151,8 @@ public function test_or_with_another_or_condition_flattens() : void public function test_or_with_single_condition() : void { - $cond1 = new RawCondition('x = 1'); - $cond2 = new RawCondition('y = 2'); + $cond1 = eq(col('x'), literal(1)); + $cond2 = eq(col('y'), literal(2)); $or = new OrCondition($cond1, $cond2); $ast = $or->toAst(); @@ -165,8 +167,8 @@ public function test_or_with_single_condition() : void public function test_to_ast_creates_bool_expr() : void { - $cond1 = new RawCondition('x = 1'); - $cond2 = new RawCondition('y = 2'); + $cond1 = eq(col('x'), literal(1)); + $cond2 = eq(col('y'), literal(2)); $or = new OrCondition($cond1, $cond2); $ast = $or->toAst(); diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/RawConditionTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/RawConditionTest.php deleted file mode 100644 index c163c8ffa2..0000000000 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/RawConditionTest.php +++ /dev/null @@ -1,138 +0,0 @@ -and($cond2); - - self::assertInstanceOf(AndCondition::class, $and); - } - - public function test_from_ast_throws_unsupported_exception() : void - { - $this->expectException(UnsupportedNodeException::class); - $this->expectExceptionMessage('Cannot reconstruct Flow\PostgreSql\QueryBuilder\Condition\RawCondition from AST'); - - $node = new Node(); - RawCondition::fromAst($node); - } - - public function test_not_returns_not_condition() : void - { - $cond = new RawCondition('x = 1'); - $not = $cond->not(); - - self::assertInstanceOf(NotCondition::class, $not); - } - - public function test_or_returns_or_condition() : void - { - $cond1 = new RawCondition('x = 1'); - $cond2 = new RawCondition('y = 2'); - - $or = $cond1->or($cond2); - - self::assertInstanceOf(OrCondition::class, $or); - } - - public function test_to_ast_with_comparison_condition() : void - { - $raw = new RawCondition('id = 42'); - $ast = $raw->toAst(); - - self::assertInstanceOf(Node::class, $ast); - - $parser = new Parser(); - $parsed = $parser->parse('SELECT 1 WHERE id = 42'); - $stmts = $parsed->raw()->getStmts(); - $stmt = $stmts[0]->getStmt(); - self::assertNotNull($stmt); - $selectStmt = $stmt->getSelectStmt(); - self::assertNotNull($selectStmt); - $expectedWhereClause = $selectStmt->getWhereClause(); - self::assertNotNull($expectedWhereClause); - - self::assertTrue($ast->hasAExpr()); - self::assertTrue($expectedWhereClause->hasAExpr()); - } - - public function test_to_ast_with_complex_condition() : void - { - $raw = new RawCondition('age > 18 AND status = \'active\''); - $ast = $raw->toAst(); - - self::assertInstanceOf(Node::class, $ast); - self::assertTrue($ast->hasBoolExpr()); - } - - public function test_to_ast_with_in_condition() : void - { - $raw = new RawCondition('category IN (\'A\', \'B\', \'C\')'); - $ast = $raw->toAst(); - - self::assertInstanceOf(Node::class, $ast); - } - - public function test_to_ast_with_like_condition() : void - { - $raw = new RawCondition('name LIKE \'%john%\''); - $ast = $raw->toAst(); - - self::assertInstanceOf(Node::class, $ast); - } - - public function test_to_ast_with_nested_conditions() : void - { - $raw = new RawCondition('(x = 1 OR y = 2) AND z = 3'); - $ast = $raw->toAst(); - - self::assertInstanceOf(Node::class, $ast); - self::assertTrue($ast->hasBoolExpr()); - } - - public function test_to_ast_with_not_condition() : void - { - $raw = new RawCondition('NOT active'); - $ast = $raw->toAst(); - - self::assertInstanceOf(Node::class, $ast); - } - - public function test_to_ast_with_null_check() : void - { - $raw = new RawCondition('email IS NOT NULL'); - $ast = $raw->toAst(); - - self::assertInstanceOf(Node::class, $ast); - self::assertTrue($ast->hasNullTest()); - } - - public function test_to_ast_with_simple_boolean() : void - { - $raw = new RawCondition('active'); - $ast = $raw->toAst(); - - self::assertInstanceOf(Node::class, $ast); - } -} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/CopyBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Copy/CopyBuilderTest.php similarity index 51% rename from src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/CopyBuilderTest.php rename to src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Copy/CopyBuilderTest.php index 4b27d1e030..5aa8c41849 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/CopyBuilderTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Copy/CopyBuilderTest.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\PostgreSql\Tests\Integration\QueryBuilder; +namespace Flow\PostgreSql\Tests\Unit\QueryBuilder\Copy; use function Flow\PostgreSql\DSL\{ col, @@ -10,12 +10,11 @@ select }; -use Flow\PostgreSql\{ParsedQuery, Parser}; -use Flow\PostgreSql\Protobuf\AST\{CopyStmt, Node, RawStmt}; -use Flow\PostgreSql\QueryBuilder\Copy\{CopyFormat, CopyFromFinalStep, CopyOnError, CopyToFinalStep}; +use Flow\PostgreSql\QueryBuilder\Copy\{CopyFormat, CopyOnError}; use Flow\PostgreSql\QueryBuilder\Table\Table; +use PHPUnit\Framework\TestCase; -final class CopyBuilderTest extends PGQueryTestCase +final class CopyBuilderTest extends TestCase { public function test_copy_from_basic() : void { @@ -23,10 +22,7 @@ public function test_copy_from_basic() : void ->from('users') ->file('/tmp/users.csv'); - $this->assertCopyFromQueryEquals( - $query, - "COPY users FROM '/tmp/users.csv'" - ); + self::assertSame("COPY users FROM '/tmp/users.csv'", $query->toSql()); } public function test_copy_from_csv_with_header() : void @@ -37,10 +33,7 @@ public function test_copy_from_csv_with_header() : void ->format(CopyFormat::CSV) ->withHeader(); - $this->assertCopyFromQueryEquals( - $query, - "COPY users FROM '/tmp/users.csv' WITH (FORMAT CSV, HEADER true)" - ); + self::assertSame("COPY users FROM '/tmp/users.csv' WITH (FORMAT CSV, HEADER true)", $query->toSql()); } public function test_copy_from_program() : void @@ -49,10 +42,7 @@ public function test_copy_from_program() : void ->from('logs') ->program('gunzip -c /var/log/app.log.gz'); - $this->assertCopyFromQueryEquals( - $query, - "COPY logs FROM PROGRAM 'gunzip -c /var/log/app.log.gz'" - ); + self::assertSame("COPY logs FROM PROGRAM 'gunzip -c /var/log/app.log.gz'", $query->toSql()); } public function test_copy_from_stdin() : void @@ -62,10 +52,7 @@ public function test_copy_from_stdin() : void ->stdin() ->format(CopyFormat::CSV); - $this->assertCopyFromQueryEquals( - $query, - 'COPY users FROM STDIN CSV' - ); + self::assertSame('COPY users FROM STDIN CSV', $query->toSql()); } public function test_copy_from_with_all_csv_options() : void @@ -81,10 +68,7 @@ public function test_copy_from_with_all_csv_options() : void ->escape('\\') ->encoding('UTF8'); - $this->assertCopyFromQueryEquals( - $query, - "COPY data FROM '/tmp/data.csv' WITH (FORMAT CSV, DELIMITER ';', NULL 'NULL', HEADER true, QUOTE '''', ESCAPE E'\\\\', ENCODING 'UTF8')" - ); + self::assertSame("COPY data FROM '/tmp/data.csv' WITH (FORMAT CSV, DELIMITER ';', NULL 'NULL', HEADER true, QUOTE '''', ESCAPE E'\\\\', ENCODING 'UTF8')", $query->toSql()); } public function test_copy_from_with_columns() : void @@ -94,10 +78,7 @@ public function test_copy_from_with_columns() : void ->columns('id', 'name', 'email') ->file('/tmp/users.csv'); - $this->assertCopyFromQueryEquals( - $query, - "COPY users(id, name, email) FROM '/tmp/users.csv'" - ); + self::assertSame("COPY users(id, name, email) FROM '/tmp/users.csv'", $query->toSql()); } public function test_copy_from_with_force_not_null() : void @@ -108,10 +89,7 @@ public function test_copy_from_with_force_not_null() : void ->format(CopyFormat::CSV) ->forceNotNull('name', 'email'); - $this->assertCopyFromQueryEquals( - $query, - "COPY users FROM '/tmp/users.csv' WITH (FORMAT CSV, FORCE_NOT_NULL (name, email))" - ); + self::assertSame("COPY users FROM '/tmp/users.csv' WITH (FORMAT CSV, FORCE_NOT_NULL (name, email))", $query->toSql()); } public function test_copy_from_with_on_error_ignore() : void @@ -121,10 +99,7 @@ public function test_copy_from_with_on_error_ignore() : void ->file('/tmp/events.csv') ->onError(CopyOnError::IGNORE); - $this->assertCopyFromQueryEquals( - $query, - "COPY events FROM '/tmp/events.csv' WITH (on_error ignore)" - ); + self::assertSame("COPY events FROM '/tmp/events.csv' WITH (on_error ignore)", $query->toSql()); } public function test_copy_to_basic() : void @@ -133,10 +108,7 @@ public function test_copy_to_basic() : void ->to('users') ->file('/tmp/users.csv'); - $this->assertCopyToQueryEquals( - $query, - "COPY users TO '/tmp/users.csv'" - ); + self::assertSame("COPY users TO '/tmp/users.csv'", $query->toSql()); } public function test_copy_to_binary_format() : void @@ -146,10 +118,7 @@ public function test_copy_to_binary_format() : void ->file('/tmp/data.bin') ->format(CopyFormat::BINARY); - $this->assertCopyToQueryEquals( - $query, - "COPY data TO '/tmp/data.bin' WITH (FORMAT BINARY)" - ); + self::assertSame("COPY data TO '/tmp/data.bin' WITH (FORMAT BINARY)", $query->toSql()); } public function test_copy_to_csv_with_header() : void @@ -160,10 +129,7 @@ public function test_copy_to_csv_with_header() : void ->format(CopyFormat::CSV) ->withHeader(); - $this->assertCopyToQueryEquals( - $query, - "COPY users TO '/tmp/users.csv' WITH (FORMAT CSV, HEADER true)" - ); + self::assertSame("COPY users TO '/tmp/users.csv' WITH (FORMAT CSV, HEADER true)", $query->toSql()); } public function test_copy_to_program() : void @@ -172,10 +138,7 @@ public function test_copy_to_program() : void ->to('logs') ->program('gzip > /tmp/logs.csv.gz'); - $this->assertCopyToQueryEquals( - $query, - "COPY logs TO PROGRAM 'gzip > /tmp/logs.csv.gz'" - ); + self::assertSame("COPY logs TO PROGRAM 'gzip > /tmp/logs.csv.gz'", $query->toSql()); } public function test_copy_to_stdout() : void @@ -185,10 +148,7 @@ public function test_copy_to_stdout() : void ->stdout() ->format(CopyFormat::CSV); - $this->assertCopyToQueryEquals( - $query, - 'COPY users TO STDOUT CSV' - ); + self::assertSame('COPY users TO STDOUT CSV', $query->toSql()); } public function test_copy_to_with_columns() : void @@ -198,10 +158,7 @@ public function test_copy_to_with_columns() : void ->columns('id', 'name', 'email') ->file('/tmp/users.csv'); - $this->assertCopyToQueryEquals( - $query, - "COPY users(id, name, email) TO '/tmp/users.csv'" - ); + self::assertSame("COPY users(id, name, email) TO '/tmp/users.csv'", $query->toSql()); } public function test_copy_to_with_force_quote_all() : void @@ -212,10 +169,7 @@ public function test_copy_to_with_force_quote_all() : void ->format(CopyFormat::CSV) ->forceQuoteAll(); - $this->assertCopyToQueryEquals( - $query, - "COPY products TO '/tmp/products.csv' WITH (FORMAT CSV, FORCE_QUOTE *)" - ); + self::assertSame("COPY products TO '/tmp/products.csv' WITH (FORMAT CSV, FORCE_QUOTE *)", $query->toSql()); } public function test_copy_to_with_force_quote_columns() : void @@ -226,10 +180,7 @@ public function test_copy_to_with_force_quote_columns() : void ->format(CopyFormat::CSV) ->forceQuote('name', 'description'); - $this->assertCopyToQueryEquals( - $query, - "COPY products TO '/tmp/products.csv' CSV FORCE QUOTE name, description" - ); + self::assertSame("COPY products TO '/tmp/products.csv' CSV FORCE QUOTE name, description", $query->toSql()); } public function test_copy_to_with_query() : void @@ -243,10 +194,7 @@ public function test_copy_to_with_query() : void ->file('/tmp/active_users.csv') ->format(CopyFormat::CSV); - $this->assertCopyToQueryEquals( - $query, - "COPY (SELECT id, name FROM users) TO '/tmp/active_users.csv' CSV" - ); + self::assertSame("COPY (SELECT id, name FROM users) TO '/tmp/active_users.csv' CSV", $query->toSql()); } public function test_copy_to_with_schema() : void @@ -255,37 +203,6 @@ public function test_copy_to_with_schema() : void ->to('analytics.events') ->file('/tmp/events.csv'); - $this->assertCopyToQueryEquals( - $query, - "COPY analytics.events TO '/tmp/events.csv'" - ); - } - - protected function assertCopyFromQueryEquals(CopyFromFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseCopyStmt($builder->toAst()); - - self::assertSame($expectedSql, $sql); - } - - protected function assertCopyToQueryEquals(CopyToFinalStep $builder, string $expectedSql) : void - { - $sql = $this->deparseCopyStmt($builder->toAst()); - - self::assertSame($expectedSql, $sql); - } - - protected function deparseCopyStmt(CopyStmt $copyStmt) : string - { - $node = new Node(); - $node->setCopyStmt($copyStmt); - - $parser = new Parser(); - $rawStmt = new RawStmt(['stmt' => $node]); - $parsed = $parser->parse('SELECT 1'); - $parseResult = $parsed->raw(); - $parseResult->setStmts([$rawStmt]); - - return (new ParsedQuery($parseResult))->deparse(); + self::assertSame("COPY analytics.events TO '/tmp/events.csv'", $query->toSql()); } } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Delete/DeleteBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Delete/DeleteBuilderTest.php index c438b584d5..6e2d4422a4 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Delete/DeleteBuilderTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Delete/DeleteBuilderTest.php @@ -4,6 +4,7 @@ namespace Flow\PostgreSql\Tests\Unit\QueryBuilder\Delete; +use function Flow\PostgreSql\DSL\{any_, col, delete, eq, literal, param, select, table}; use Flow\PostgreSql\{ParsedQuery, Parser}; use Flow\PostgreSql\Protobuf\AST\{DeleteStmt, Node, RawStmt, SelectStmt}; use Flow\PostgreSql\QueryBuilder\Clause\{CTE, WithClause}; @@ -240,6 +241,15 @@ public function test_delete_with_multiple_using_tables_deparsed_output() : void self::assertSame('DELETE FROM order_items oi USING orders o, customers c WHERE oi.order_id = o.id AND o.customer_id = c.id', $deparsed); } + public function test_delete_with_parameters() : void + { + $query = delete() + ->from('users') + ->where(eq(col('id'), param(1))); + + self::assertSame('DELETE FROM users WHERE id = $1', $query->toSql()); + } + public function test_delete_with_returning() : void { $query = DeleteBuilder::create() @@ -269,6 +279,16 @@ public function test_delete_with_returning() : void self::assertTrue($secondVal->hasColumnRef()); } + public function test_delete_with_returning_all() : void + { + $query = delete() + ->from('users') + ->where(eq(col('id'), literal(1))) + ->returningAll(); + + self::assertSame('DELETE FROM users WHERE id = 1 RETURNING *', $query->toSql()); + } + public function test_delete_with_returning_deparsed_output() : void { if (!\function_exists('pg_query_deparse')) { @@ -329,6 +349,19 @@ public function test_delete_with_schema_round_trip() : void self::assertSame($originalRelation->getSchemaname(), $restoredRelation->getSchemaname()); } + public function test_delete_with_subquery_in_where() : void + { + $subquery = select() + ->select(col('user_id')) + ->from(table('inactive_users')); + + $query = delete() + ->from('users') + ->where(any_(col('id'), ComparisonOperator::EQ, $subquery)); + + self::assertSame('DELETE FROM users WHERE id = ANY (SELECT user_id FROM inactive_users)', $query->toSql()); + } + public function test_delete_with_using() : void { $query = DeleteBuilder::create() diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/RawExpressionTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/RawExpressionTest.php deleted file mode 100644 index e752c8e9f9..0000000000 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/RawExpressionTest.php +++ /dev/null @@ -1,133 +0,0 @@ -as('result'); - - self::assertInstanceOf(AliasedExpression::class, $aliased); - } - - public function test_constructor_throws_on_empty_sql() : void - { - $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage('RawExpression SQL cannot be empty'); - - new RawExpression(''); - } - - public function test_from_ast_throws_unsupported_exception() : void - { - $this->expectException(UnsupportedNodeException::class); - $this->expectExceptionMessage('Cannot reconstruct RawExpression - cannot convert AST back to raw SQL string from AST'); - - $node = new Node(); - RawExpression::fromAst($node); - } - - public function test_sql_getter() : void - { - $sql = '1 + 1'; - $expr = new RawExpression($sql); - - self::assertSame($sql, $expr->sql()); - } - - public function test_to_ast_with_arithmetic_expression() : void - { - $expr = new RawExpression('1 + 2'); - - $ast = $expr->toAst(); - - self::assertInstanceOf(Node::class, $ast); - self::assertTrue($ast->hasAExpr()); - } - - public function test_to_ast_with_column_reference() : void - { - $expr = new RawExpression('users.name'); - - $ast = $expr->toAst(); - - self::assertInstanceOf(Node::class, $ast); - self::assertTrue($ast->hasColumnRef()); - } - - public function test_to_ast_with_complex_expression() : void - { - $expr = new RawExpression('CASE WHEN x > 0 THEN 1 ELSE 0 END'); - - $ast = $expr->toAst(); - - self::assertInstanceOf(Node::class, $ast); - self::assertTrue($ast->hasCaseExpr()); - } - - public function test_to_ast_with_function_call() : void - { - $expr = new RawExpression('NOW()'); - - $ast = $expr->toAst(); - - self::assertInstanceOf(Node::class, $ast); - self::assertTrue($ast->hasFuncCall()); - } - - public function test_to_ast_with_invalid_sql_throws_parser_exception() : void - { - $this->expectException(ParserException::class); - - $expr = new RawExpression('INVALID SQL @#$%'); - $expr->toAst(); - } - - public function test_to_ast_with_literal_value() : void - { - $expr = new RawExpression('42'); - - $ast = $expr->toAst(); - - self::assertInstanceOf(Node::class, $ast); - self::assertTrue($ast->hasAConst()); - } - - public function test_to_ast_with_nested_subquery() : void - { - $expr = new RawExpression('(SELECT id FROM users WHERE active = true)'); - - $ast = $expr->toAst(); - - self::assertInstanceOf(Node::class, $ast); - self::assertTrue($ast->hasSubLink()); - } - - public function test_to_ast_with_string_literal() : void - { - $expr = new RawExpression("'hello world'"); - - $ast = $expr->toAst(); - - self::assertInstanceOf(Node::class, $ast); - self::assertTrue($ast->hasAConst()); - } -} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/TypeCastTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/TypeCastTest.php index 26d18b216a..ac8e352a4d 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/TypeCastTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/TypeCastTest.php @@ -6,15 +6,15 @@ use Flow\PostgreSql\Protobuf\AST\{Node, PBString, TypeCast as AstTypeCast, TypeName}; use Flow\PostgreSql\QueryBuilder\Expression\{Column, Literal, TypeCast}; -use Flow\PostgreSql\QueryBuilder\Schema\DataType; +use Flow\PostgreSql\QueryBuilder\Schema\ColumnType; use PHPUnit\Framework\TestCase; final class TypeCastTest extends TestCase { public function test_complex_expression_cast() : void { - $innerExpr = new TypeCast(Literal::string('42'), DataType::integer()); - $outerCast = new TypeCast($innerExpr, DataType::varchar(255)); + $innerExpr = new TypeCast(Literal::string('42'), ColumnType::integer()); + $outerCast = new TypeCast($innerExpr, ColumnType::varchar(255)); $node = $outerCast->toAst(); $restored = TypeCast::fromAst($node); @@ -25,7 +25,7 @@ public function test_complex_expression_cast() : void public function test_converts_to_ast() : void { $expr = Literal::string('123'); - $cast = new TypeCast($expr, DataType::integer()); + $cast = new TypeCast($expr, ColumnType::integer()); $node = $cast->toAst(); @@ -49,7 +49,7 @@ public function test_converts_to_ast() : void public function test_converts_type_cast_with_schema_to_ast() : void { $expr = Column::name('id'); - $cast = new TypeCast($expr, DataType::text()); + $cast = new TypeCast($expr, ColumnType::text()); $node = $cast->toAst(); $typeCast = $node->getTypeCast(); @@ -70,7 +70,7 @@ public function test_converts_type_cast_with_schema_to_ast() : void public function test_creates_aliased_expression() : void { $expr = Literal::int(42); - $cast = new TypeCast($expr, DataType::varchar(100)); + $cast = new TypeCast($expr, ColumnType::varchar(100)); $aliased = $cast->as('casted_value'); self::assertSame('casted_value', $aliased->getAlias()); @@ -80,20 +80,20 @@ public function test_creates_aliased_expression() : void public function test_creates_simple_type_cast() : void { $expr = Literal::int(42); - $dataType = DataType::varchar(100); + $dataType = ColumnType::varchar(100); $cast = new TypeCast($expr, $dataType); - self::assertSame($dataType, $cast->getDataType()); + self::assertSame($dataType, $cast->getColumnType()); self::assertSame($expr, $cast->getExpression()); } public function test_creates_type_cast_with_schema() : void { $expr = Column::name('value'); - $dataType = DataType::integer(); + $dataType = ColumnType::integer(); $cast = new TypeCast($expr, $dataType); - self::assertSame($dataType, $cast->getDataType()); + self::assertSame($dataType, $cast->getColumnType()); } public function test_recreates_from_ast() : void @@ -118,7 +118,7 @@ public function test_recreates_from_ast() : void $cast = TypeCast::fromAst($node); - self::assertInstanceOf(DataType::class, $cast->getDataType()); + self::assertInstanceOf(ColumnType::class, $cast->getColumnType()); } public function test_recreates_type_cast_with_schema_from_ast() : void @@ -147,39 +147,39 @@ public function test_recreates_type_cast_with_schema_from_ast() : void $cast = TypeCast::fromAst($node); - self::assertInstanceOf(DataType::class, $cast->getDataType()); + self::assertInstanceOf(ColumnType::class, $cast->getColumnType()); } public function test_round_trip_conversion() : void { $expr = Column::name('amount'); - $cast = new TypeCast($expr, DataType::numeric(10, 2)); + $cast = new TypeCast($expr, ColumnType::numeric(10, 2)); $node = $cast->toAst(); $restored = TypeCast::fromAst($node); - self::assertInstanceOf(DataType::class, $restored->getDataType()); + self::assertInstanceOf(ColumnType::class, $restored->getColumnType()); } - public function test_with_data_type_creates_new_instance() : void + public function test_with_column_type_creates_new_instance() : void { $expr = Literal::int(1); - $dataType1 = DataType::integer(); - $dataType2 = DataType::varchar(100); + $dataType1 = ColumnType::integer(); + $dataType2 = ColumnType::varchar(100); $cast = new TypeCast($expr, $dataType1); - $newCast = $cast->withDataType($dataType2); + $newCast = $cast->withColumnType($dataType2); self::assertNotSame($cast, $newCast); - self::assertSame($dataType1, $cast->getDataType()); - self::assertSame($dataType2, $newCast->getDataType()); + self::assertSame($dataType1, $cast->getColumnType()); + self::assertSame($dataType2, $newCast->getColumnType()); } public function test_with_expression_creates_new_instance() : void { $expr1 = Literal::int(1); $expr2 = Literal::int(2); - $cast = new TypeCast($expr1, DataType::integer()); + $cast = new TypeCast($expr1, ColumnType::integer()); $newCast = $cast->withExpression($expr2); diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Insert/InsertBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Insert/InsertBuilderTest.php index 410cf5971e..d5bc58f261 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Insert/InsertBuilderTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Insert/InsertBuilderTest.php @@ -4,6 +4,8 @@ namespace Flow\PostgreSql\Tests\Unit\QueryBuilder\Insert; +use function Flow\PostgreSql\DSL\{col, conflict_columns, insert, literal, param, parameters, select, table}; + use Flow\PostgreSql\{ParsedQuery, Parser}; use Flow\PostgreSql\Protobuf\AST\{InsertStmt, Node, RawStmt}; use Flow\PostgreSql\QueryBuilder\Clause\{ConflictTarget, OnConflictClause}; @@ -259,6 +261,22 @@ public function test_insert_returning_all() : void self::assertCount(1, $returning); } + public function test_insert_select_to_sql() : void + { + self::assertSame( + 'INSERT INTO users (name, email) SELECT name, email FROM archived_users', + insert() + ->into('users') + ->columns('name', 'email') + ->select( + select() + ->select(col('name'), col('email')) + ->from(table('archived_users')) + ) + ->toSql() + ); + } + public function test_insert_with_alias() : void { $query = InsertBuilder::create() @@ -277,6 +295,17 @@ public function test_insert_with_alias() : void self::assertSame('u', $alias->getAliasname()); } + public function test_insert_with_default_values_to_sql() : void + { + self::assertSame( + 'INSERT INTO users DEFAULT VALUES', + insert() + ->into('users') + ->defaultValues() + ->toSql() + ); + } + public function test_insert_with_function_values() : void { $query = InsertBuilder::create() @@ -308,6 +337,19 @@ public function test_insert_with_function_values_deparsed_output() : void self::assertSame("INSERT INTO logs (message, created_at) VALUES ('test message', now())", $deparsed); } + public function test_insert_with_multiple_rows_to_sql() : void + { + self::assertSame( + "INSERT INTO users (name, email) VALUES ('John', 'john@example.com'), ('Jane', 'jane@example.com')", + insert() + ->into('users') + ->columns('name', 'email') + ->values(literal('John'), literal('john@example.com')) + ->values(literal('Jane'), literal('jane@example.com')) + ->toSql() + ); + } + public function test_insert_with_on_conflict_do_nothing_deparsed_output() : void { if (!\function_exists('pg_query_deparse')) { @@ -324,6 +366,19 @@ public function test_insert_with_on_conflict_do_nothing_deparsed_output() : void self::assertSame("INSERT INTO users (email, name) VALUES ('john@example.com', 'John') ON CONFLICT (email) DO NOTHING", $deparsed); } + public function test_insert_with_on_conflict_do_nothing_to_sql() : void + { + self::assertSame( + "INSERT INTO users (name, email) VALUES ('John', 'john@example.com') ON CONFLICT DO NOTHING", + insert() + ->into('users') + ->columns('name', 'email') + ->values(literal('John'), literal('john@example.com')) + ->onConflictDoNothing() + ->toSql() + ); + } + public function test_insert_with_on_conflict_do_update_deparsed_output() : void { if (!\function_exists('pg_query_deparse')) { @@ -343,6 +398,85 @@ public function test_insert_with_on_conflict_do_update_deparsed_output() : void self::assertSame("INSERT INTO users (email, name) VALUES ('john@example.com', 'John') ON CONFLICT (email) DO UPDATE SET name = excluded.name", $deparsed); } + public function test_insert_with_on_conflict_do_update_to_sql() : void + { + self::assertSame( + "INSERT INTO users (email, name) VALUES ('john@example.com', 'John') ON CONFLICT (email) DO UPDATE SET name = 'Updated John'", + insert() + ->into('users') + ->columns('email', 'name') + ->values(literal('john@example.com'), literal('John')) + ->onConflictDoUpdate( + conflict_columns(['email']), + ['name' => literal('Updated John')] + ) + ->toSql() + ); + } + + public function test_insert_with_on_conflict_on_columns_do_nothing_to_sql() : void + { + self::assertSame( + "INSERT INTO users (name, email) VALUES ('John', 'john@example.com') ON CONFLICT (email) DO NOTHING", + insert() + ->into('users') + ->columns('name', 'email') + ->values(literal('John'), literal('john@example.com')) + ->onConflictDoNothing(conflict_columns(['email'])) + ->toSql() + ); + } + + public function test_insert_with_parameters_function_multiple_rows_to_sql() : void + { + self::assertSame( + 'INSERT INTO users (name, email) VALUES ($1, $2), ($3, $4)', + insert() + ->into('users') + ->columns('name', 'email') + ->values(...parameters(2)) + ->values(...parameters(2, startAt: 3)) + ->toSql() + ); + } + + public function test_insert_with_parameters_function_to_sql() : void + { + self::assertSame( + 'INSERT INTO users (name, email) VALUES ($1, $2)', + insert() + ->into('users') + ->columns('name', 'email') + ->values(...parameters(2)) + ->toSql() + ); + } + + public function test_insert_with_parameters_to_sql() : void + { + self::assertSame( + 'INSERT INTO users (name, email) VALUES ($1, $2)', + insert() + ->into('users') + ->columns('name', 'email') + ->values(param(1), param(2)) + ->toSql() + ); + } + + public function test_insert_with_returning_all_to_sql() : void + { + self::assertSame( + "INSERT INTO users (name) VALUES ('John') RETURNING *", + insert() + ->into('users') + ->columns('name') + ->values(literal('John')) + ->returningAll() + ->toSql() + ); + } + public function test_insert_with_returning_deparsed_output() : void { if (!\function_exists('pg_query_deparse')) { @@ -359,6 +493,19 @@ public function test_insert_with_returning_deparsed_output() : void self::assertSame("INSERT INTO users (name) VALUES ('John') RETURNING id", $deparsed); } + public function test_insert_with_returning_to_sql() : void + { + self::assertSame( + "INSERT INTO users (name) VALUES ('John') RETURNING id", + insert() + ->into('users') + ->columns('name') + ->values(literal('John')) + ->returning(col('id')) + ->toSql() + ); + } + public function test_insert_with_schema() : void { $query = InsertBuilder::create() @@ -389,6 +536,18 @@ public function test_insert_with_schema_deparsed_output() : void self::assertSame("INSERT INTO public.users (name) VALUES ('John')", $deparsed); } + public function test_insert_with_schema_qualified_table_to_sql() : void + { + self::assertSame( + "INSERT INTO public.users (name) VALUES ('John')", + insert() + ->into('public.users') + ->columns('name') + ->values(literal('John')) + ->toSql() + ); + } + public function test_insert_without_columns() : void { $query = InsertBuilder::create() @@ -607,6 +766,18 @@ public function test_simple_insert_deparsed_output() : void self::assertSame("INSERT INTO users (name, email) VALUES ('John', 'john@example.com')", $deparsed); } + public function test_simple_insert_with_values_to_sql() : void + { + self::assertSame( + "INSERT INTO users (name, email) VALUES ('John', 'john@example.com')", + insert() + ->into('users') + ->columns('name', 'email') + ->values(literal('John'), literal('john@example.com')) + ->toSql() + ); + } + private function deparse(InsertStmt $insertStmt) : string { $parser = new Parser(); diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Merge/MergeBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Merge/MergeBuilderTest.php index 043480e40a..4dd1b4a35d 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Merge/MergeBuilderTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Merge/MergeBuilderTest.php @@ -4,6 +4,8 @@ namespace Flow\PostgreSql\Tests\Unit\QueryBuilder\Merge; +use function Flow\PostgreSql\DSL\{col, cte, eq, gt, literal, merge, param, select, table, with}; + use Flow\PostgreSql\{ParsedQuery, Parser}; use Flow\PostgreSql\Protobuf\AST\{MergeStmt, Node, RawStmt, SelectStmt}; use Flow\PostgreSql\QueryBuilder\Clause\{CTE, WithClause}; @@ -144,6 +146,21 @@ public function test_merge_match_kind_enum_values() : void self::assertSame(3, MergeMatchKind::NOT_MATCHED_BY_TARGET->value); } + public function test_merge_simple_update_to_sql() : void + { + self::assertSame( + 'MERGE INTO target USING source s ON target.id = s.id WHEN MATCHED THEN UPDATE SET value = s.value', + merge('target') + ->using('source', 's') + ->on(eq(col('target.id'), col('s.id'))) + ->whenMatched() + ->thenUpdate([ + 'value' => col('s.value'), + ]) + ->toSql() + ); + } + public function test_merge_using_parses_schema_and_table() : void { $query = MergeBuilder::create() @@ -168,6 +185,27 @@ public function test_merge_using_parses_schema_and_table() : void self::assertSame('s', $alias->getAliasname()); } + public function test_merge_using_subquery_to_sql() : void + { + self::assertSame( + 'MERGE INTO users USING (SELECT id, name, email FROM staged_data) src ON users.id = src.id WHEN MATCHED THEN UPDATE SET name = src.name, email = src.email', + merge('users') + ->using( + select() + ->select(col('id'), col('name'), col('email')) + ->from(table('staged_data')), + 'src' + ) + ->on(eq(col('users.id'), col('src.id'))) + ->whenMatched() + ->thenUpdate([ + 'name' => col('src.name'), + 'email' => col('src.email'), + ]) + ->toSql() + ); + } + public function test_merge_when_clause_data_structure() : void { $condition = new Comparison(Column::name('id'), ComparisonOperator::EQ, Literal::int(1)); @@ -436,6 +474,97 @@ public function test_merge_when_not_matched_with_condition() : void self::assertTrue($whenClause->hasCondition()); } + public function test_merge_with_conditional_when_matched_to_sql() : void + { + self::assertSame( + 'MERGE INTO products p USING price_updates pu ON p.id = pu.product_id WHEN MATCHED AND pu.price > 0 THEN UPDATE SET price = pu.price', + merge('products', 'p') + ->using('price_updates', 'pu') + ->on(eq(col('p.id'), col('pu.product_id'))) + ->whenMatchedAnd(gt(col('pu.price'), literal(0))) + ->thenUpdate([ + 'price' => col('pu.price'), + ]) + ->toSql() + ); + } + + public function test_merge_with_cte_to_sql() : void + { + self::assertSame( + 'WITH staged_data AS (SELECT id, name FROM raw_input) MERGE INTO users USING staged_data s ON users.id = s.id WHEN MATCHED THEN UPDATE SET name = s.name', + with(cte('staged_data', select() + ->select(col('id'), col('name')) + ->from(table('raw_input'))))->merge('users') + ->using('staged_data', 's') + ->on(eq(col('users.id'), col('s.id'))) + ->whenMatched() + ->thenUpdate([ + 'name' => col('s.name'), + ]) + ->toSql() + ); + } + + public function test_merge_with_delete_to_sql() : void + { + self::assertSame( + 'MERGE INTO target_table t USING source_table s ON t.id = s.id WHEN MATCHED THEN DELETE', + merge('target_table', 't') + ->using('source_table', 's') + ->on(eq(col('t.id'), col('s.id'))) + ->whenMatched() + ->thenDelete() + ->toSql() + ); + } + + public function test_merge_with_do_nothing_to_sql() : void + { + self::assertSame( + 'MERGE INTO products USING updates u ON products.id = u.id WHEN MATCHED THEN DO NOTHING', + merge('products') + ->using('updates', 'u') + ->on(eq(col('products.id'), col('u.id'))) + ->whenMatched() + ->thenDoNothing() + ->toSql() + ); + } + + public function test_merge_with_insert_to_sql() : void + { + self::assertSame( + 'MERGE INTO customers USING new_customers nc ON customers.id = nc.id WHEN NOT MATCHED THEN INSERT (id, name, email) VALUES (nc.id, nc.name, nc.email)', + merge('customers') + ->using('new_customers', 'nc') + ->on(eq(col('customers.id'), col('nc.id'))) + ->whenNotMatched() + ->thenInsert( + ['id', 'name', 'email'], + [col('nc.id'), col('nc.name'), col('nc.email')] + ) + ->toSql() + ); + } + + public function test_merge_with_insert_values_to_sql() : void + { + self::assertSame( + "MERGE INTO users USING new_users n ON users.id = n.id WHEN NOT MATCHED THEN INSERT (id, name, status) VALUES (n.id, n.name, 'active')", + merge('users') + ->using('new_users', 'n') + ->on(eq(col('users.id'), col('n.id'))) + ->whenNotMatched() + ->thenInsertValues([ + 'id' => col('n.id'), + 'name' => col('n.name'), + 'status' => literal('active'), + ]) + ->toSql() + ); + } + public function test_merge_with_multiple_when_clauses() : void { $query = MergeBuilder::create() @@ -463,6 +592,21 @@ public function test_merge_with_multiple_when_clauses() : void self::assertSame(MergeActionType::INSERT->value, $secondClause->getCommandType()); } + public function test_merge_with_parameters_to_sql() : void + { + self::assertSame( + 'MERGE INTO accounts USING transactions t ON accounts.id = t.account_id WHEN MATCHED THEN UPDATE SET balance = $1', + merge('accounts') + ->using('transactions', 't') + ->on(eq(col('accounts.id'), col('t.account_id'))) + ->whenMatched() + ->thenUpdate([ + 'balance' => param(1), + ]) + ->toSql() + ); + } + public function test_merge_with_source_subquery() : void { $subquery = SelectBuilder::create() diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/AlterTable/AlterTableBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/AlterTable/AlterTableBuilderTest.php index 6451c2dad4..5cf234ec0b 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/AlterTable/AlterTableBuilderTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/AlterTable/AlterTableBuilderTest.php @@ -4,10 +4,12 @@ namespace Flow\PostgreSql\Tests\Unit\QueryBuilder\Schema\AlterTable; +use function Flow\PostgreSql\DSL\literal; use Flow\PostgreSql\Protobuf\AST\{AlterTableStmt, AlterTableType, DropBehavior, ObjectType}; -use Flow\PostgreSql\QueryBuilder\Schema\AlterTable\AlterTableBuilder; -use Flow\PostgreSql\QueryBuilder\Schema\{ColumnDefinition, DataType}; +use Flow\PostgreSql\QueryBuilder\Schema\AlterTable\{AlterTableBuilder, RenameTableBuilder}; +use Flow\PostgreSql\QueryBuilder\Schema\{ColumnDefinition, ColumnType}; use Flow\PostgreSql\QueryBuilder\Schema\Constraint\{ForeignKeyConstraint, PrimaryKeyConstraint, UniqueConstraint}; +use Flow\PostgreSql\QueryBuilder\Sql; use PHPUnit\Framework\TestCase; final class AlterTableBuilderTest extends TestCase @@ -22,7 +24,7 @@ protected function setUp() : void public function test_add_column() : void { $builder = AlterTableBuilder::create('users') - ->addColumn(ColumnDefinition::create('email', DataType::varchar(255))->notNull()); + ->addColumn(ColumnDefinition::create('email', ColumnType::varchar(255))->notNull()); $ast = $builder->toAst(); @@ -56,6 +58,28 @@ public function test_add_foreign_key_constraint() : void self::assertSame(AlterTableType::AT_AddConstraint, $ast->getCmds()[0]->getAlterTableCmd()->getSubtype()); } + public function test_add_inherit() : void + { + $builder = AlterTableBuilder::create('employees') + ->addInherit('persons'); + + $ast = $builder->toAst(); + + self::assertInstanceOf(AlterTableStmt::class, $ast); + self::assertCount(1, $ast->getCmds()); + self::assertSame(AlterTableType::AT_AddInherit, $ast->getCmds()[0]->getAlterTableCmd()->getSubtype()); + self::assertTrue($ast->getCmds()[0]->getAlterTableCmd()->hasDef()); + self::assertSame('persons', $ast->getCmds()[0]->getAlterTableCmd()->getDef()->getRangeVar()->getRelname()); + } + + public function test_add_inherit_to_sql() : void + { + self::assertSame( + 'ALTER TABLE employees INHERIT persons', + AlterTableBuilder::create('employees')->addInherit('persons')->toSql(), + ); + } + public function test_add_unique_constraint() : void { $builder = AlterTableBuilder::create('users') @@ -98,7 +122,7 @@ public function test_alter_column_drop_not_null() : void public function test_alter_column_set_default() : void { $builder = AlterTableBuilder::create('users') - ->alterColumnSetDefault('status', "'active'"); + ->alterColumnSetDefault('status', literal('active')); $ast = $builder->toAst(); @@ -125,7 +149,7 @@ public function test_alter_column_set_not_null() : void public function test_alter_column_type() : void { $builder = AlterTableBuilder::create('users') - ->alterColumnType('name', DataType::text()); + ->alterColumnType('name', ColumnType::text()); $ast = $builder->toAst(); @@ -139,7 +163,7 @@ public function test_alter_table_if_exists() : void { $builder = AlterTableBuilder::create('users') ->ifExists() - ->addColumn(ColumnDefinition::create('email', DataType::varchar(255))); + ->addColumn(ColumnDefinition::create('email', ColumnType::varchar(255))); $ast = $builder->toAst(); @@ -150,7 +174,7 @@ public function test_alter_table_if_exists() : void public function test_alter_table_with_schema() : void { $builder = AlterTableBuilder::create('users', 'public') - ->addColumn(ColumnDefinition::create('email', DataType::varchar(255))); + ->addColumn(ColumnDefinition::create('email', ColumnType::varchar(255))); $ast = $builder->toAst(); @@ -231,10 +255,32 @@ public function test_drop_constraint_if_exists() : void self::assertTrue($ast->getCmds()[0]->getAlterTableCmd()->getMissingOk()); } + public function test_drop_inherit() : void + { + $builder = AlterTableBuilder::create('employees') + ->dropInherit('persons'); + + $ast = $builder->toAst(); + + self::assertInstanceOf(AlterTableStmt::class, $ast); + self::assertCount(1, $ast->getCmds()); + self::assertSame(AlterTableType::AT_DropInherit, $ast->getCmds()[0]->getAlterTableCmd()->getSubtype()); + self::assertTrue($ast->getCmds()[0]->getAlterTableCmd()->hasDef()); + self::assertSame('persons', $ast->getCmds()[0]->getAlterTableCmd()->getDef()->getRangeVar()->getRelname()); + } + + public function test_drop_inherit_to_sql() : void + { + self::assertSame( + 'ALTER TABLE employees NO INHERIT persons', + AlterTableBuilder::create('employees')->dropInherit('persons')->toSql(), + ); + } + public function test_immutability() : void { $original = AlterTableBuilder::create('users'); - $modified = $original->addColumn(ColumnDefinition::create('email', DataType::varchar(255))); + $modified = $original->addColumn(ColumnDefinition::create('email', ColumnType::varchar(255))); self::assertCount(0, $original->toAst()->getCmds()); self::assertCount(1, $modified->toAst()->getCmds()); @@ -243,8 +289,8 @@ public function test_immutability() : void public function test_multiple_commands() : void { $builder = AlterTableBuilder::create('users') - ->addColumn(ColumnDefinition::create('email', DataType::varchar(255))->notNull()) - ->addColumn(ColumnDefinition::create('phone', DataType::varchar(20))) + ->addColumn(ColumnDefinition::create('email', ColumnType::varchar(255))->notNull()) + ->addColumn(ColumnDefinition::create('phone', ColumnType::varchar(20))) ->addConstraint(UniqueConstraint::create('email')) ->alterColumnSetNotNull('phone'); @@ -254,10 +300,111 @@ public function test_multiple_commands() : void self::assertCount(4, $ast->getCmds()); } + public function test_rename_column_to_sql() : void + { + self::assertSame( + 'ALTER TABLE users RENAME COLUMN name TO full_name', + AlterTableBuilder::create('users')->renameColumn('name', 'full_name')->toSql() + ); + } + + public function test_rename_constraint_to_sql() : void + { + self::assertSame( + 'ALTER TABLE users RENAME CONSTRAINT pk_old TO pk_new', + AlterTableBuilder::create('users')->renameConstraint('pk_old', 'pk_new')->toSql() + ); + } + + public function test_rename_table_builder_implements_sql_query() : void + { + self::assertInstanceOf( + Sql::class, + RenameTableBuilder::renameTo('users', null, 'people', false) + ); + } + + public function test_rename_table_to_sql() : void + { + self::assertSame( + 'ALTER TABLE users RENAME TO people', + AlterTableBuilder::create('users')->renameTo('people')->toSql() + ); + } + + public function test_set_logged() : void + { + $builder = AlterTableBuilder::create('users') + ->setLogged(); + + self::assertSame('ALTER TABLE users SET LOGGED', $builder->toSql()); + + $ast = $builder->toAst(); + + self::assertInstanceOf(AlterTableStmt::class, $ast); + self::assertSame(ObjectType::OBJECT_TABLE, $ast->getObjtype()); + self::assertSame('users', $ast->getRelation()->getRelname()); + self::assertCount(1, $ast->getCmds()); + self::assertSame(AlterTableType::AT_SetLogged, $ast->getCmds()[0]->getAlterTableCmd()->getSubtype()); + } + + public function test_set_logged_with_schema() : void + { + self::assertSame( + 'ALTER TABLE public.users SET LOGGED', + AlterTableBuilder::create('users', 'public')->setLogged()->toSql(), + ); + } + + public function test_set_tablespace() : void + { + $builder = AlterTableBuilder::create('users') + ->setTablespace('fast_storage'); + + $ast = $builder->toAst(); + + self::assertInstanceOf(AlterTableStmt::class, $ast); + self::assertCount(1, $ast->getCmds()); + self::assertSame(AlterTableType::AT_SetTableSpace, $ast->getCmds()[0]->getAlterTableCmd()->getSubtype()); + self::assertSame('fast_storage', $ast->getCmds()[0]->getAlterTableCmd()->getName()); + } + + public function test_set_tablespace_to_sql() : void + { + self::assertSame( + 'ALTER TABLE users SET TABLESPACE fast_storage', + AlterTableBuilder::create('users')->setTablespace('fast_storage')->toSql(), + ); + } + + public function test_set_unlogged() : void + { + $builder = AlterTableBuilder::create('users') + ->setUnlogged(); + + self::assertSame('ALTER TABLE users SET UNLOGGED', $builder->toSql()); + + $ast = $builder->toAst(); + + self::assertInstanceOf(AlterTableStmt::class, $ast); + self::assertSame(ObjectType::OBJECT_TABLE, $ast->getObjtype()); + self::assertSame('users', $ast->getRelation()->getRelname()); + self::assertCount(1, $ast->getCmds()); + self::assertSame(AlterTableType::AT_SetUnLogged, $ast->getCmds()[0]->getAlterTableCmd()->getSubtype()); + } + + public function test_set_unlogged_if_exists() : void + { + self::assertSame( + 'ALTER TABLE IF EXISTS users SET UNLOGGED', + AlterTableBuilder::create('users')->ifExists()->setUnlogged()->toSql(), + ); + } + public function test_simple_alter_table() : void { $builder = AlterTableBuilder::create('users') - ->addColumn(ColumnDefinition::create('email', DataType::varchar(255))); + ->addColumn(ColumnDefinition::create('email', ColumnType::varchar(255))); $ast = $builder->toAst(); diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/ColumnDefinitionTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/ColumnDefinitionTest.php index f591660760..48a47921cf 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/ColumnDefinitionTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/ColumnDefinitionTest.php @@ -4,11 +4,11 @@ namespace Flow\PostgreSql\Tests\Unit\QueryBuilder\Schema; -use function Flow\PostgreSql\DSL\{current_date, current_time, current_timestamp}; +use function Flow\PostgreSql\DSL\{col, concat, current_date, current_time, current_timestamp, gt, literal}; use Flow\PostgreSql\Protobuf\AST\{ColumnDef, ConstrType}; use Flow\PostgreSql\QueryBuilder\Expression\SQLValueFunctionExpression; -use Flow\PostgreSql\QueryBuilder\Schema\{ColumnDefinition, DataType}; - +use Flow\PostgreSql\QueryBuilder\Schema\{ColumnDefinition, ColumnType}; +use Flow\PostgreSql\Schema\IdentityGeneration; use PHPUnit\Framework\TestCase; final class ColumnDefinitionTest extends TestCase @@ -22,7 +22,7 @@ protected function setUp() : void public function test_basic_column() : void { - $column = ColumnDefinition::create('id', DataType::integer()); + $column = ColumnDefinition::create('id', ColumnType::integer()); $ast = $column->toAst(); @@ -33,8 +33,8 @@ public function test_basic_column() : void public function test_check_constraint() : void { - $column = ColumnDefinition::create('age', DataType::integer()) - ->check('age > 0'); + $column = ColumnDefinition::create('age', ColumnType::integer()) + ->check(gt(col('age'), literal(0))); $ast = $column->toAst(); @@ -45,7 +45,7 @@ public function test_check_constraint() : void public function test_column_default_with_current_date() : void { - $column = ColumnDefinition::create('birth_date', DataType::date()) + $column = ColumnDefinition::create('birth_date', ColumnType::date()) ->default(current_date()); $ast = $column->toAst(); @@ -57,7 +57,7 @@ public function test_column_default_with_current_date() : void public function test_column_default_with_current_time() : void { - $column = ColumnDefinition::create('check_in_time', DataType::time()) + $column = ColumnDefinition::create('check_in_time', ColumnType::time()) ->default(current_time()); $ast = $column->toAst(); @@ -69,7 +69,7 @@ public function test_column_default_with_current_time() : void public function test_column_default_with_current_timestamp() : void { - $column = ColumnDefinition::create('created_at', DataType::timestamp()) + $column = ColumnDefinition::create('created_at', ColumnType::timestamp()) ->default(current_timestamp()); $ast = $column->toAst(); @@ -81,7 +81,7 @@ public function test_column_default_with_current_timestamp() : void public function test_column_default_with_expression() : void { - $column = ColumnDefinition::create('created_at', DataType::timestamp()) + $column = ColumnDefinition::create('created_at', ColumnType::timestamp()) ->default(SQLValueFunctionExpression::currentTimestamp()); $ast = $column->toAst(); @@ -93,7 +93,7 @@ public function test_column_default_with_expression() : void public function test_column_with_boolean_default_false() : void { - $column = ColumnDefinition::create('is_active', DataType::boolean()) + $column = ColumnDefinition::create('is_active', ColumnType::boolean()) ->default(false); $ast = $column->toAst(); @@ -105,7 +105,7 @@ public function test_column_with_boolean_default_false() : void public function test_column_with_boolean_default_true() : void { - $column = ColumnDefinition::create('is_active', DataType::boolean()) + $column = ColumnDefinition::create('is_active', ColumnType::boolean()) ->default(true); $ast = $column->toAst(); @@ -117,7 +117,7 @@ public function test_column_with_boolean_default_true() : void public function test_column_with_default_integer() : void { - $column = ColumnDefinition::create('status', DataType::integer()) + $column = ColumnDefinition::create('status', ColumnType::integer()) ->default(0); $ast = $column->toAst(); @@ -129,7 +129,7 @@ public function test_column_with_default_integer() : void public function test_column_with_default_null() : void { - $column = ColumnDefinition::create('optional', DataType::text()) + $column = ColumnDefinition::create('optional', ColumnType::text()) ->default(null); $ast = $column->toAst(); @@ -141,8 +141,8 @@ public function test_column_with_default_null() : void public function test_column_with_default_raw_expression() : void { - $column = ColumnDefinition::create('created_at', DataType::timestamp()) - ->defaultRaw('CURRENT_TIMESTAMP'); + $column = ColumnDefinition::create('created_at', ColumnType::timestamp()) + ->defaultRaw(current_timestamp()); $ast = $column->toAst(); @@ -153,7 +153,7 @@ public function test_column_with_default_raw_expression() : void public function test_column_with_default_string() : void { - $column = ColumnDefinition::create('name', DataType::varchar(100)) + $column = ColumnDefinition::create('name', ColumnType::varchar(100)) ->default('Unknown'); $ast = $column->toAst(); @@ -165,8 +165,8 @@ public function test_column_with_default_string() : void public function test_generated_column() : void { - $column = ColumnDefinition::create('full_name', DataType::text()) - ->generatedAs("first_name || ' ' || last_name"); + $column = ColumnDefinition::create('full_name', ColumnType::text()) + ->generatedAs(concat(col('first_name'), literal(' '), col('last_name'))); $ast = $column->toAst(); @@ -178,29 +178,37 @@ public function test_generated_column() : void public function test_identity_always() : void { - $column = ColumnDefinition::create('id', DataType::integer()) - ->identity('ALWAYS'); + $column = ColumnDefinition::create('id', ColumnType::integer()) + ->identity(IdentityGeneration::ALWAYS); $ast = $column->toAst(); self::assertInstanceOf(ColumnDef::class, $ast); - self::assertSame('a', $ast->getIdentity()); + + $constraints = $ast->getConstraints(); + self::assertCount(1, $constraints); + self::assertSame(ConstrType::CONSTR_IDENTITY, $constraints[0]->getConstraint()->getContype()); + self::assertSame('a', $constraints[0]->getConstraint()->getGeneratedWhen()); } public function test_identity_by_default() : void { - $column = ColumnDefinition::create('id', DataType::integer()) - ->identity('BY DEFAULT'); + $column = ColumnDefinition::create('id', ColumnType::integer()) + ->identity(IdentityGeneration::BY_DEFAULT); $ast = $column->toAst(); self::assertInstanceOf(ColumnDef::class, $ast); - self::assertSame('d', $ast->getIdentity()); + + $constraints = $ast->getConstraints(); + self::assertCount(1, $constraints); + self::assertSame(ConstrType::CONSTR_IDENTITY, $constraints[0]->getConstraint()->getContype()); + self::assertSame('d', $constraints[0]->getConstraint()->getGeneratedWhen()); } public function test_immutability() : void { - $original = ColumnDefinition::create('id', DataType::integer()); + $original = ColumnDefinition::create('id', ColumnType::integer()); $modified = $original->notNull(); self::assertNotSame($original, $modified); @@ -211,7 +219,7 @@ public function test_immutability() : void public function test_multiple_constraints() : void { - $column = ColumnDefinition::create('id', DataType::integer()) + $column = ColumnDefinition::create('id', ColumnType::integer()) ->notNull() ->primaryKey(); @@ -225,7 +233,7 @@ public function test_multiple_constraints() : void public function test_not_null_column() : void { - $column = ColumnDefinition::create('name', DataType::varchar(100)) + $column = ColumnDefinition::create('name', ColumnType::varchar(100)) ->notNull(); $ast = $column->toAst(); @@ -237,7 +245,7 @@ public function test_not_null_column() : void public function test_nullable_column() : void { - $column = ColumnDefinition::create('name', DataType::varchar(100)) + $column = ColumnDefinition::create('name', ColumnType::varchar(100)) ->notNull() ->nullable(); @@ -249,7 +257,7 @@ public function test_nullable_column() : void public function test_primary_key_constraint() : void { - $column = ColumnDefinition::create('id', DataType::integer()) + $column = ColumnDefinition::create('id', ColumnType::integer()) ->primaryKey(); $ast = $column->toAst(); @@ -261,7 +269,7 @@ public function test_primary_key_constraint() : void public function test_references_constraint() : void { - $column = ColumnDefinition::create('user_id', DataType::integer()) + $column = ColumnDefinition::create('user_id', ColumnType::integer()) ->references('users', 'id'); $ast = $column->toAst(); @@ -275,7 +283,7 @@ public function test_references_constraint() : void public function test_references_with_schema() : void { - $column = ColumnDefinition::create('user_id', DataType::integer()) + $column = ColumnDefinition::create('user_id', ColumnType::integer()) ->references('users', 'id', 'public'); $ast = $column->toAst(); @@ -288,7 +296,7 @@ public function test_references_with_schema() : void public function test_unique_constraint() : void { - $column = ColumnDefinition::create('email', DataType::varchar(255)) + $column = ColumnDefinition::create('email', ColumnType::varchar(255)) ->unique(); $ast = $column->toAst(); diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/DataTypeTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/ColumnTypeTest.php similarity index 72% rename from src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/DataTypeTest.php rename to src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/ColumnTypeTest.php index ffbc99abdb..b6ef13eb89 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/DataTypeTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/ColumnTypeTest.php @@ -4,15 +4,17 @@ namespace Flow\PostgreSql\Tests\Unit\QueryBuilder\Schema; +use function Flow\PostgreSql\DSL\{column_type_array, column_type_bigint, column_type_boolean, column_type_custom, column_type_integer, column_type_text, column_type_varchar}; + use Flow\PostgreSql\Protobuf\AST\TypeName; -use Flow\PostgreSql\QueryBuilder\Schema\DataType; +use Flow\PostgreSql\QueryBuilder\Schema\ColumnType; use PHPUnit\Framework\TestCase; -final class DataTypeTest extends TestCase +final class ColumnTypeTest extends TestCase { public function test_array_type() : void { - $type = DataType::array(DataType::integer()); + $type = ColumnType::array(ColumnType::integer()); $ast = $type->toAst(); @@ -23,7 +25,7 @@ public function test_array_type() : void public function test_bigint() : void { - $type = DataType::bigint(); + $type = ColumnType::bigint(); $ast = $type->toAst(); @@ -35,7 +37,7 @@ public function test_bigint() : void public function test_bigserial() : void { - $type = DataType::bigserial(); + $type = ColumnType::bigserial(); $ast = $type->toAst(); @@ -46,7 +48,7 @@ public function test_bigserial() : void public function test_boolean() : void { - $type = DataType::boolean(); + $type = ColumnType::boolean(); $ast = $type->toAst(); @@ -58,7 +60,7 @@ public function test_boolean() : void public function test_bytea() : void { - $type = DataType::bytea(); + $type = ColumnType::bytea(); $ast = $type->toAst(); @@ -68,7 +70,7 @@ public function test_bytea() : void public function test_char_with_length() : void { - $type = DataType::char(10); + $type = ColumnType::char(10); $ast = $type->toAst(); @@ -80,7 +82,7 @@ public function test_char_with_length() : void public function test_cidr() : void { - $type = DataType::cidr(); + $type = ColumnType::cidr(); $ast = $type->toAst(); @@ -90,7 +92,7 @@ public function test_cidr() : void public function test_custom_type_with_schema() : void { - $type = DataType::custom('my_type', 'my_schema'); + $type = ColumnType::custom('my_type', 'my_schema'); $ast = $type->toAst(); @@ -102,7 +104,7 @@ public function test_custom_type_with_schema() : void public function test_custom_type_without_schema() : void { - $type = DataType::custom('my_type'); + $type = ColumnType::custom('my_type'); $ast = $type->toAst(); @@ -113,7 +115,7 @@ public function test_custom_type_without_schema() : void public function test_date() : void { - $type = DataType::date(); + $type = ColumnType::date(); $ast = $type->toAst(); @@ -123,7 +125,7 @@ public function test_date() : void public function test_double_precision() : void { - $type = DataType::doublePrecision(); + $type = ColumnType::doublePrecision(); $ast = $type->toAst(); @@ -133,7 +135,7 @@ public function test_double_precision() : void public function test_inet() : void { - $type = DataType::inet(); + $type = ColumnType::inet(); $ast = $type->toAst(); @@ -143,7 +145,7 @@ public function test_inet() : void public function test_integer() : void { - $type = DataType::integer(); + $type = ColumnType::integer(); $ast = $type->toAst(); @@ -155,7 +157,7 @@ public function test_integer() : void public function test_interval() : void { - $type = DataType::interval(); + $type = ColumnType::interval(); $ast = $type->toAst(); @@ -163,9 +165,64 @@ public function test_interval() : void self::assertSame('interval', $ast->getNames()[1]->getString()->getSval()); } + public function test_is_equal_array_different_element_type() : void + { + self::assertFalse(column_type_array(column_type_integer())->isEqual(column_type_array(column_type_text()))); + } + + public function test_is_equal_array_same_element_type() : void + { + self::assertTrue(column_type_array(column_type_integer())->isEqual(column_type_array(column_type_integer()))); + } + + public function test_is_equal_array_vs_non_array() : void + { + self::assertFalse(column_type_array(column_type_integer())->isEqual(column_type_integer())); + } + + public function test_is_equal_boolean_vs_bigint() : void + { + self::assertFalse(column_type_boolean()->isEqual(column_type_bigint())); + } + + public function test_is_equal_custom_types_different_name() : void + { + self::assertFalse(column_type_custom('type_a')->isEqual(column_type_custom('type_b'))); + } + + public function test_is_equal_custom_types_different_schema() : void + { + self::assertFalse(column_type_custom('my_type', 'schema_a')->isEqual(column_type_custom('my_type', 'schema_b'))); + } + + public function test_is_equal_custom_types_same() : void + { + self::assertTrue(column_type_custom('my_type', 'my_schema')->isEqual(column_type_custom('my_type', 'my_schema'))); + } + + public function test_is_equal_with_different_types() : void + { + self::assertFalse(column_type_integer()->isEqual(column_type_text())); + } + + public function test_is_equal_with_different_typmods() : void + { + self::assertFalse(column_type_varchar(100)->isEqual(column_type_varchar(255))); + } + + public function test_is_equal_with_same_type() : void + { + self::assertTrue(column_type_integer()->isEqual(column_type_integer())); + } + + public function test_is_equal_with_same_type_and_typmods() : void + { + self::assertTrue(column_type_varchar(255)->isEqual(column_type_varchar(255))); + } + public function test_json() : void { - $type = DataType::json(); + $type = ColumnType::json(); $ast = $type->toAst(); @@ -175,7 +232,7 @@ public function test_json() : void public function test_jsonb() : void { - $type = DataType::jsonb(); + $type = ColumnType::jsonb(); $ast = $type->toAst(); @@ -185,7 +242,7 @@ public function test_jsonb() : void public function test_macaddr() : void { - $type = DataType::macaddr(); + $type = ColumnType::macaddr(); $ast = $type->toAst(); @@ -195,7 +252,7 @@ public function test_macaddr() : void public function test_numeric_with_precision_and_scale() : void { - $type = DataType::numeric(10, 2); + $type = ColumnType::numeric(10, 2); $ast = $type->toAst(); @@ -208,7 +265,7 @@ public function test_numeric_with_precision_and_scale() : void public function test_numeric_with_precision_only() : void { - $type = DataType::numeric(10); + $type = ColumnType::numeric(10); $ast = $type->toAst(); @@ -220,7 +277,7 @@ public function test_numeric_with_precision_only() : void public function test_numeric_without_precision() : void { - $type = DataType::numeric(); + $type = ColumnType::numeric(); $ast = $type->toAst(); @@ -231,7 +288,7 @@ public function test_numeric_without_precision() : void public function test_real() : void { - $type = DataType::real(); + $type = ColumnType::real(); $ast = $type->toAst(); @@ -241,7 +298,7 @@ public function test_real() : void public function test_serial() : void { - $type = DataType::serial(); + $type = ColumnType::serial(); $ast = $type->toAst(); @@ -252,7 +309,7 @@ public function test_serial() : void public function test_smallint() : void { - $type = DataType::smallint(); + $type = ColumnType::smallint(); $ast = $type->toAst(); @@ -262,7 +319,7 @@ public function test_smallint() : void public function test_text() : void { - $type = DataType::text(); + $type = ColumnType::text(); $ast = $type->toAst(); @@ -272,7 +329,7 @@ public function test_text() : void public function test_time_with_precision() : void { - $type = DataType::time(3); + $type = ColumnType::time(3); $ast = $type->toAst(); @@ -284,7 +341,7 @@ public function test_time_with_precision() : void public function test_time_without_precision() : void { - $type = DataType::time(); + $type = ColumnType::time(); $ast = $type->toAst(); @@ -295,7 +352,7 @@ public function test_time_without_precision() : void public function test_timestamp_with_precision() : void { - $type = DataType::timestamp(6); + $type = ColumnType::timestamp(6); $ast = $type->toAst(); @@ -307,7 +364,7 @@ public function test_timestamp_with_precision() : void public function test_timestamp_without_precision() : void { - $type = DataType::timestamp(); + $type = ColumnType::timestamp(); $ast = $type->toAst(); @@ -318,7 +375,7 @@ public function test_timestamp_without_precision() : void public function test_timestamptz_with_precision() : void { - $type = DataType::timestamptz(3); + $type = ColumnType::timestamptz(3); $ast = $type->toAst(); @@ -330,7 +387,7 @@ public function test_timestamptz_with_precision() : void public function test_uuid() : void { - $type = DataType::uuid(); + $type = ColumnType::uuid(); $ast = $type->toAst(); @@ -340,7 +397,7 @@ public function test_uuid() : void public function test_varchar_with_length() : void { - $type = DataType::varchar(255); + $type = ColumnType::varchar(255); $ast = $type->toAst(); diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Constraint/CheckConstraintTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Constraint/CheckConstraintTest.php index 965c210cb1..6932c5ebcc 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Constraint/CheckConstraintTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Constraint/CheckConstraintTest.php @@ -4,6 +4,7 @@ namespace Flow\PostgreSql\Tests\Unit\QueryBuilder\Schema\Constraint; +use function Flow\PostgreSql\DSL\{col, ge, gt, in_, literal, lt}; use Flow\PostgreSql\Protobuf\AST\{ConstrType, Constraint}; use Flow\PostgreSql\QueryBuilder\Schema\Constraint\CheckConstraint; use PHPUnit\Framework\TestCase; @@ -19,7 +20,7 @@ protected function setUp() : void public function test_check_constraint_with_name() : void { - $constraint = CheckConstraint::create('age > 0') + $constraint = CheckConstraint::create(gt(col('age'), literal(0))) ->name('chk_positive_age'); $ast = $constraint->toAst(); @@ -31,7 +32,7 @@ public function test_check_constraint_with_name() : void public function test_complex_check_expression() : void { - $constraint = CheckConstraint::create('start_date < end_date'); + $constraint = CheckConstraint::create(lt(col('start_date'), col('end_date'))); $ast = $constraint->toAst(); @@ -42,7 +43,7 @@ public function test_complex_check_expression() : void public function test_immutability() : void { - $original = CheckConstraint::create('value > 0'); + $original = CheckConstraint::create(gt(col('value'), literal(0))); $withName = $original->name('chk_test'); self::assertNotSame($original, $withName); @@ -52,7 +53,7 @@ public function test_immutability() : void public function test_no_inherit() : void { - $constraint = CheckConstraint::create('status IN (\'active\', \'inactive\')') + $constraint = CheckConstraint::create(in_(col('status'), [literal('active'), literal('inactive')])) ->noInherit(); $ast = $constraint->toAst(); @@ -64,7 +65,7 @@ public function test_no_inherit() : void public function test_simple_check_constraint() : void { - $constraint = CheckConstraint::create('age > 0'); + $constraint = CheckConstraint::create(gt(col('age'), literal(0))); $ast = $constraint->toAst(); @@ -75,7 +76,7 @@ public function test_simple_check_constraint() : void public function test_with_all_options() : void { - $constraint = CheckConstraint::create('amount >= 0') + $constraint = CheckConstraint::create(ge(col('amount'), literal(0))) ->name('chk_positive_amount') ->noInherit(); diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Constraint/ExcludeConstraintTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Constraint/ExcludeConstraintTest.php index 2afe979c0c..4ec031a122 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Constraint/ExcludeConstraintTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Constraint/ExcludeConstraintTest.php @@ -4,6 +4,7 @@ namespace Flow\PostgreSql\Tests\Unit\QueryBuilder\Schema\Constraint; +use function Flow\PostgreSql\DSL\{col, eq, literal}; use Flow\PostgreSql\Protobuf\AST\{ConstrType, Constraint}; use Flow\PostgreSql\QueryBuilder\Schema\Constraint\ExcludeConstraint; use PHPUnit\Framework\TestCase; @@ -20,7 +21,7 @@ protected function setUp() : void public function test_exclude_constraint_with_btree() : void { $constraint = ExcludeConstraint::create('btree') - ->element('id', '='); + ->element(col('id'), '='); $ast = $constraint->toAst(); @@ -32,8 +33,8 @@ public function test_exclude_constraint_with_btree() : void public function test_exclude_constraint_with_multiple_elements() : void { $constraint = ExcludeConstraint::create('gist') - ->element('room_id', '=') - ->element('during', '&&'); + ->element(col('room_id'), '=') + ->element(col('during'), '&&'); $ast = $constraint->toAst(); @@ -45,7 +46,7 @@ public function test_exclude_constraint_with_multiple_elements() : void public function test_exclude_constraint_with_name() : void { $constraint = ExcludeConstraint::create() - ->element('room_id', '=') + ->element(col('room_id'), '=') ->name('exc_room_booking'); $ast = $constraint->toAst(); @@ -57,8 +58,8 @@ public function test_exclude_constraint_with_name() : void public function test_exclude_constraint_with_where_clause() : void { $constraint = ExcludeConstraint::create() - ->element('room_id', '=') - ->where('active = true'); + ->element(col('room_id'), '=') + ->where(eq(col('active'), literal(true))); $ast = $constraint->toAst(); @@ -70,9 +71,9 @@ public function test_exclude_with_all_options() : void { $constraint = ExcludeConstraint::create('gist') ->name('exc_booking') - ->element('room_id', '=') - ->element('period', '&&') - ->where('cancelled = false'); + ->element(col('room_id'), '=') + ->element(col('period'), '&&') + ->where(eq(col('cancelled'), literal(false))); $ast = $constraint->toAst(); @@ -96,7 +97,7 @@ public function test_immutability() : void public function test_simple_exclude_constraint() : void { $constraint = ExcludeConstraint::create() - ->element('room_id', '='); + ->element(col('room_id'), '='); $ast = $constraint->toAst(); diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/SequenceBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/CreateSequence/SequenceBuilderTest.php similarity index 61% rename from src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/SequenceBuilderTest.php rename to src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/CreateSequence/SequenceBuilderTest.php index 4c9325075e..996cca6a27 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/SequenceBuilderTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/CreateSequence/SequenceBuilderTest.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\PostgreSql\Tests\Integration\QueryBuilder; +namespace Flow\PostgreSql\Tests\Unit\QueryBuilder\Schema\CreateSequence; use function Flow\PostgreSql\DSL\{ alter, @@ -10,16 +10,18 @@ drop }; -final class SequenceBuilderTest extends PGQueryTestCase +use PHPUnit\Framework\TestCase; + +final class SequenceBuilderTest extends TestCase { public function test_alter_sequence_as_type() : void { $builder = alter()->sequence('user_id_seq') ->asType('smallint'); - $this->assertAlterSequenceQuery( - $builder, - 'ALTER SEQUENCE user_id_seq AS smallint' + self::assertSame( + 'ALTER SEQUENCE user_id_seq AS smallint', + $builder->toSql() ); } @@ -28,9 +30,9 @@ public function test_alter_sequence_cache() : void $builder = alter()->sequence('user_id_seq') ->cache(20); - $this->assertAlterSequenceQuery( - $builder, - 'ALTER SEQUENCE user_id_seq CACHE 20' + self::assertSame( + 'ALTER SEQUENCE user_id_seq CACHE 20', + $builder->toSql() ); } @@ -39,9 +41,9 @@ public function test_alter_sequence_cycle() : void $builder = alter()->sequence('user_id_seq') ->cycle(); - $this->assertAlterSequenceQuery( - $builder, - 'ALTER SEQUENCE user_id_seq CYCLE' + self::assertSame( + 'ALTER SEQUENCE user_id_seq CYCLE', + $builder->toSql() ); } @@ -51,9 +53,9 @@ public function test_alter_sequence_if_exists() : void ->withIfExists() ->incrementBy(10); - $this->assertAlterSequenceQuery( - $builder, - 'ALTER SEQUENCE IF EXISTS user_id_seq INCREMENT 10' + self::assertSame( + 'ALTER SEQUENCE IF EXISTS user_id_seq INCREMENT 10', + $builder->toSql() ); } @@ -62,9 +64,9 @@ public function test_alter_sequence_increment_by() : void $builder = alter()->sequence('user_id_seq') ->incrementBy(10); - $this->assertAlterSequenceQuery( - $builder, - 'ALTER SEQUENCE user_id_seq INCREMENT 10' + self::assertSame( + 'ALTER SEQUENCE user_id_seq INCREMENT 10', + $builder->toSql() ); } @@ -73,9 +75,9 @@ public function test_alter_sequence_max_value() : void $builder = alter()->sequence('user_id_seq') ->maxValue(9999999); - $this->assertAlterSequenceQuery( - $builder, - 'ALTER SEQUENCE user_id_seq MAXVALUE 9999999' + self::assertSame( + 'ALTER SEQUENCE user_id_seq MAXVALUE 9999999', + $builder->toSql() ); } @@ -84,9 +86,9 @@ public function test_alter_sequence_min_value() : void $builder = alter()->sequence('user_id_seq') ->minValue(1); - $this->assertAlterSequenceQuery( - $builder, - 'ALTER SEQUENCE user_id_seq MINVALUE 1' + self::assertSame( + 'ALTER SEQUENCE user_id_seq MINVALUE 1', + $builder->toSql() ); } @@ -98,9 +100,9 @@ public function test_alter_sequence_multiple_options() : void ->maxValue(1000000) ->cache(5); - $this->assertAlterSequenceQuery( - $builder, - 'ALTER SEQUENCE user_id_seq INCREMENT 10 MINVALUE 1 MAXVALUE 1000000 CACHE 5' + self::assertSame( + 'ALTER SEQUENCE user_id_seq INCREMENT 10 MINVALUE 1 MAXVALUE 1000000 CACHE 5', + $builder->toSql() ); } @@ -109,9 +111,9 @@ public function test_alter_sequence_no_cycle() : void $builder = alter()->sequence('user_id_seq') ->noCycle(); - $this->assertAlterSequenceQuery( - $builder, - 'ALTER SEQUENCE user_id_seq NO CYCLE' + self::assertSame( + 'ALTER SEQUENCE user_id_seq NO CYCLE', + $builder->toSql() ); } @@ -120,9 +122,9 @@ public function test_alter_sequence_no_max_value() : void $builder = alter()->sequence('user_id_seq') ->noMaxValue(); - $this->assertAlterSequenceQuery( - $builder, - 'ALTER SEQUENCE user_id_seq NO MAXVALUE' + self::assertSame( + 'ALTER SEQUENCE user_id_seq NO MAXVALUE', + $builder->toSql() ); } @@ -131,9 +133,9 @@ public function test_alter_sequence_no_min_value() : void $builder = alter()->sequence('user_id_seq') ->noMinValue(); - $this->assertAlterSequenceQuery( - $builder, - 'ALTER SEQUENCE user_id_seq NO MINVALUE' + self::assertSame( + 'ALTER SEQUENCE user_id_seq NO MINVALUE', + $builder->toSql() ); } @@ -142,9 +144,9 @@ public function test_alter_sequence_owned_by() : void $builder = alter()->sequence('user_id_seq') ->ownedBy('users', 'id'); - $this->assertAlterSequenceQuery( - $builder, - 'ALTER SEQUENCE user_id_seq OWNED BY users.id' + self::assertSame( + 'ALTER SEQUENCE user_id_seq OWNED BY users.id', + $builder->toSql() ); } @@ -153,9 +155,9 @@ public function test_alter_sequence_owned_by_none() : void $builder = alter()->sequence('user_id_seq') ->ownedByNone(); - $this->assertAlterSequenceQuery( - $builder, - 'ALTER SEQUENCE user_id_seq OWNED BY "none"' + self::assertSame( + 'ALTER SEQUENCE user_id_seq OWNED BY "none"', + $builder->toSql() ); } @@ -164,9 +166,9 @@ public function test_alter_sequence_owner_to() : void $builder = alter()->sequence('user_id_seq') ->ownerTo('new_owner'); - $this->assertAlterSequenceOwnerQuery( - $builder, - 'ALTER SEQUENCE user_id_seq OWNER TO new_owner' + self::assertSame( + 'ALTER SEQUENCE user_id_seq OWNER TO new_owner', + $builder->toSql() ); } @@ -176,9 +178,9 @@ public function test_alter_sequence_owner_to_if_exists() : void ->withIfExists() ->ownerTo('new_owner'); - $this->assertAlterSequenceOwnerQuery( - $builder, - 'ALTER SEQUENCE IF EXISTS user_id_seq OWNER TO new_owner' + self::assertSame( + 'ALTER SEQUENCE IF EXISTS user_id_seq OWNER TO new_owner', + $builder->toSql() ); } @@ -187,9 +189,9 @@ public function test_alter_sequence_rename_to() : void $builder = alter()->sequence('old_seq') ->renameTo('new_seq'); - $this->assertAlterSequenceRenameQuery( - $builder, - 'ALTER SEQUENCE old_seq RENAME TO new_seq' + self::assertSame( + 'ALTER SEQUENCE old_seq RENAME TO new_seq', + $builder->toSql() ); } @@ -199,9 +201,9 @@ public function test_alter_sequence_rename_to_if_exists() : void ->withIfExists() ->renameTo('new_seq'); - $this->assertAlterSequenceRenameQuery( - $builder, - 'ALTER SEQUENCE IF EXISTS old_seq RENAME TO new_seq' + self::assertSame( + 'ALTER SEQUENCE IF EXISTS old_seq RENAME TO new_seq', + $builder->toSql() ); } @@ -210,9 +212,9 @@ public function test_alter_sequence_rename_to_with_schema() : void $builder = alter()->sequence('old_seq', 'public') ->renameTo('new_seq'); - $this->assertAlterSequenceRenameQuery( - $builder, - 'ALTER SEQUENCE public.old_seq RENAME TO new_seq' + self::assertSame( + 'ALTER SEQUENCE public.old_seq RENAME TO new_seq', + $builder->toSql() ); } @@ -221,9 +223,9 @@ public function test_alter_sequence_restart() : void $builder = alter()->sequence('user_id_seq') ->restart(); - $this->assertAlterSequenceQuery( - $builder, - 'ALTER SEQUENCE user_id_seq RESTART' + self::assertSame( + 'ALTER SEQUENCE user_id_seq RESTART', + $builder->toSql() ); } @@ -232,9 +234,9 @@ public function test_alter_sequence_restart_with_value() : void $builder = alter()->sequence('user_id_seq') ->restartWith(1000); - $this->assertAlterSequenceQuery( - $builder, - 'ALTER SEQUENCE user_id_seq RESTART 1000' + self::assertSame( + 'ALTER SEQUENCE user_id_seq RESTART 1000', + $builder->toSql() ); } @@ -243,9 +245,9 @@ public function test_alter_sequence_set_logged() : void $builder = alter()->sequence('user_id_seq') ->setLogged(); - $this->assertAlterSequenceLoggingQuery( - $builder, - 'ALTER SEQUENCE user_id_seq SET LOGGED' + self::assertSame( + 'ALTER SEQUENCE user_id_seq SET LOGGED', + $builder->toSql() ); } @@ -255,9 +257,9 @@ public function test_alter_sequence_set_logged_if_exists() : void ->withIfExists() ->setLogged(); - $this->assertAlterSequenceLoggingQuery( - $builder, - 'ALTER SEQUENCE IF EXISTS user_id_seq SET LOGGED' + self::assertSame( + 'ALTER SEQUENCE IF EXISTS user_id_seq SET LOGGED', + $builder->toSql() ); } @@ -266,9 +268,9 @@ public function test_alter_sequence_set_schema() : void $builder = alter()->sequence('user_id_seq') ->setSchema('new_schema'); - $this->assertAlterSequenceSchemaQuery( - $builder, - 'ALTER SEQUENCE user_id_seq SET SCHEMA new_schema' + self::assertSame( + 'ALTER SEQUENCE user_id_seq SET SCHEMA new_schema', + $builder->toSql() ); } @@ -278,9 +280,9 @@ public function test_alter_sequence_set_schema_if_exists() : void ->withIfExists() ->setSchema('new_schema'); - $this->assertAlterSequenceSchemaQuery( - $builder, - 'ALTER SEQUENCE IF EXISTS user_id_seq SET SCHEMA new_schema' + self::assertSame( + 'ALTER SEQUENCE IF EXISTS user_id_seq SET SCHEMA new_schema', + $builder->toSql() ); } @@ -289,9 +291,9 @@ public function test_alter_sequence_set_unlogged() : void $builder = alter()->sequence('user_id_seq') ->setUnlogged(); - $this->assertAlterSequenceLoggingQuery( - $builder, - 'ALTER SEQUENCE user_id_seq SET UNLOGGED' + self::assertSame( + 'ALTER SEQUENCE user_id_seq SET UNLOGGED', + $builder->toSql() ); } @@ -300,9 +302,9 @@ public function test_alter_sequence_start_with() : void $builder = alter()->sequence('user_id_seq') ->startWith(100); - $this->assertAlterSequenceQuery( - $builder, - 'ALTER SEQUENCE user_id_seq START 100' + self::assertSame( + 'ALTER SEQUENCE user_id_seq START 100', + $builder->toSql() ); } @@ -311,9 +313,9 @@ public function test_alter_sequence_with_schema() : void $builder = alter()->sequence('user_id_seq', 'public') ->incrementBy(10); - $this->assertAlterSequenceQuery( - $builder, - 'ALTER SEQUENCE public.user_id_seq INCREMENT 10' + self::assertSame( + 'ALTER SEQUENCE public.user_id_seq INCREMENT 10', + $builder->toSql() ); } @@ -321,9 +323,9 @@ public function test_create_sequence_if_not_exists() : void { $builder = create()->sequence('user_id_seq')->ifNotExists(); - $this->assertCreateSequenceQuery( - $builder, - 'CREATE SEQUENCE IF NOT EXISTS user_id_seq' + self::assertSame( + 'CREATE SEQUENCE IF NOT EXISTS user_id_seq', + $builder->toSql() ); } @@ -331,9 +333,9 @@ public function test_create_sequence_simple() : void { $builder = create()->sequence('user_id_seq'); - $this->assertCreateSequenceQuery( - $builder, - 'CREATE SEQUENCE user_id_seq' + self::assertSame( + 'CREATE SEQUENCE user_id_seq', + $builder->toSql() ); } @@ -348,9 +350,9 @@ public function test_create_sequence_with_all_options() : void ->cache(1) ->noCycle(); - $this->assertCreateSequenceQuery( - $builder, - 'CREATE SEQUENCE user_id_seq AS bigint START 1 INCREMENT 1 MINVALUE 1 MAXVALUE 1000000 CACHE 1 NO CYCLE' + self::assertSame( + 'CREATE SEQUENCE user_id_seq AS bigint START 1 INCREMENT 1 MINVALUE 1 MAXVALUE 1000000 CACHE 1 NO CYCLE', + $builder->toSql() ); } @@ -359,9 +361,9 @@ public function test_create_sequence_with_as_type() : void $builder = create()->sequence('user_id_seq') ->asType('bigint'); - $this->assertCreateSequenceQuery( - $builder, - 'CREATE SEQUENCE user_id_seq AS bigint' + self::assertSame( + 'CREATE SEQUENCE user_id_seq AS bigint', + $builder->toSql() ); } @@ -370,9 +372,9 @@ public function test_create_sequence_with_cache() : void $builder = create()->sequence('user_id_seq') ->cache(20); - $this->assertCreateSequenceQuery( - $builder, - 'CREATE SEQUENCE user_id_seq CACHE 20' + self::assertSame( + 'CREATE SEQUENCE user_id_seq CACHE 20', + $builder->toSql() ); } @@ -381,9 +383,9 @@ public function test_create_sequence_with_cycle() : void $builder = create()->sequence('user_id_seq') ->cycle(); - $this->assertCreateSequenceQuery( - $builder, - 'CREATE SEQUENCE user_id_seq CYCLE' + self::assertSame( + 'CREATE SEQUENCE user_id_seq CYCLE', + $builder->toSql() ); } @@ -392,9 +394,9 @@ public function test_create_sequence_with_increment() : void $builder = create()->sequence('user_id_seq') ->incrementBy(10); - $this->assertCreateSequenceQuery( - $builder, - 'CREATE SEQUENCE user_id_seq INCREMENT 10' + self::assertSame( + 'CREATE SEQUENCE user_id_seq INCREMENT 10', + $builder->toSql() ); } @@ -403,9 +405,9 @@ public function test_create_sequence_with_max_value() : void $builder = create()->sequence('user_id_seq') ->maxValue(9999999); - $this->assertCreateSequenceQuery( - $builder, - 'CREATE SEQUENCE user_id_seq MAXVALUE 9999999' + self::assertSame( + 'CREATE SEQUENCE user_id_seq MAXVALUE 9999999', + $builder->toSql() ); } @@ -414,9 +416,9 @@ public function test_create_sequence_with_min_value() : void $builder = create()->sequence('user_id_seq') ->minValue(1); - $this->assertCreateSequenceQuery( - $builder, - 'CREATE SEQUENCE user_id_seq MINVALUE 1' + self::assertSame( + 'CREATE SEQUENCE user_id_seq MINVALUE 1', + $builder->toSql() ); } @@ -425,9 +427,9 @@ public function test_create_sequence_with_no_cycle() : void $builder = create()->sequence('user_id_seq') ->noCycle(); - $this->assertCreateSequenceQuery( - $builder, - 'CREATE SEQUENCE user_id_seq NO CYCLE' + self::assertSame( + 'CREATE SEQUENCE user_id_seq NO CYCLE', + $builder->toSql() ); } @@ -436,9 +438,9 @@ public function test_create_sequence_with_no_max_value() : void $builder = create()->sequence('user_id_seq') ->noMaxValue(); - $this->assertCreateSequenceQuery( - $builder, - 'CREATE SEQUENCE user_id_seq NO MAXVALUE' + self::assertSame( + 'CREATE SEQUENCE user_id_seq NO MAXVALUE', + $builder->toSql() ); } @@ -447,9 +449,9 @@ public function test_create_sequence_with_no_min_value() : void $builder = create()->sequence('user_id_seq') ->noMinValue(); - $this->assertCreateSequenceQuery( - $builder, - 'CREATE SEQUENCE user_id_seq NO MINVALUE' + self::assertSame( + 'CREATE SEQUENCE user_id_seq NO MINVALUE', + $builder->toSql() ); } @@ -458,9 +460,9 @@ public function test_create_sequence_with_owned_by() : void $builder = create()->sequence('user_id_seq') ->ownedBy('users', 'id'); - $this->assertCreateSequenceQuery( - $builder, - 'CREATE SEQUENCE user_id_seq OWNED BY users.id' + self::assertSame( + 'CREATE SEQUENCE user_id_seq OWNED BY users.id', + $builder->toSql() ); } @@ -469,9 +471,9 @@ public function test_create_sequence_with_owned_by_none() : void $builder = create()->sequence('user_id_seq') ->ownedByNone(); - $this->assertCreateSequenceQuery( - $builder, - 'CREATE SEQUENCE user_id_seq OWNED BY "none"' + self::assertSame( + 'CREATE SEQUENCE user_id_seq OWNED BY "none"', + $builder->toSql() ); } @@ -480,9 +482,9 @@ public function test_create_sequence_with_owned_by_schema_qualified() : void $builder = create()->sequence('user_id_seq') ->ownedBy('public.users', 'id'); - $this->assertCreateSequenceQuery( - $builder, - 'CREATE SEQUENCE user_id_seq OWNED BY public.users.id' + self::assertSame( + 'CREATE SEQUENCE user_id_seq OWNED BY public.users.id', + $builder->toSql() ); } @@ -490,9 +492,9 @@ public function test_create_sequence_with_schema() : void { $builder = create()->sequence('user_id_seq', 'public'); - $this->assertCreateSequenceQuery( - $builder, - 'CREATE SEQUENCE public.user_id_seq' + self::assertSame( + 'CREATE SEQUENCE public.user_id_seq', + $builder->toSql() ); } @@ -501,9 +503,9 @@ public function test_create_sequence_with_start_value() : void $builder = create()->sequence('user_id_seq') ->startWith(100); - $this->assertCreateSequenceQuery( - $builder, - 'CREATE SEQUENCE user_id_seq START 100' + self::assertSame( + 'CREATE SEQUENCE user_id_seq START 100', + $builder->toSql() ); } @@ -511,9 +513,9 @@ public function test_create_temporary_sequence() : void { $builder = create()->sequence('temp_seq')->temporary(); - $this->assertCreateSequenceQuery( - $builder, - 'CREATE TEMPORARY SEQUENCE temp_seq' + self::assertSame( + 'CREATE TEMPORARY SEQUENCE temp_seq', + $builder->toSql() ); } @@ -521,9 +523,9 @@ public function test_create_unlogged_sequence() : void { $builder = create()->sequence('fast_seq')->unlogged(); - $this->assertCreateSequenceQuery( - $builder, - 'CREATE UNLOGGED SEQUENCE fast_seq' + self::assertSame( + 'CREATE UNLOGGED SEQUENCE fast_seq', + $builder->toSql() ); } @@ -532,9 +534,9 @@ public function test_drop_sequence_cascade() : void $builder = drop()->sequence('user_id_seq') ->cascade(); - $this->assertDropSequenceQuery( - $builder, - 'DROP SEQUENCE user_id_seq CASCADE' + self::assertSame( + 'DROP SEQUENCE user_id_seq CASCADE', + $builder->toSql() ); } @@ -542,9 +544,9 @@ public function test_drop_sequence_if_exists() : void { $builder = drop()->sequence('user_id_seq')->ifExists(); - $this->assertDropSequenceQuery( - $builder, - 'DROP SEQUENCE IF EXISTS user_id_seq' + self::assertSame( + 'DROP SEQUENCE IF EXISTS user_id_seq', + $builder->toSql() ); } @@ -554,9 +556,9 @@ public function test_drop_sequence_if_exists_cascade() : void ->ifExists() ->cascade(); - $this->assertDropSequenceQuery( - $builder, - 'DROP SEQUENCE IF EXISTS user_id_seq CASCADE' + self::assertSame( + 'DROP SEQUENCE IF EXISTS user_id_seq CASCADE', + $builder->toSql() ); } @@ -564,9 +566,9 @@ public function test_drop_sequence_multiple() : void { $builder = drop()->sequence('user_id_seq', 'order_id_seq', 'product_id_seq'); - $this->assertDropSequenceQuery( - $builder, - 'DROP SEQUENCE user_id_seq, order_id_seq, product_id_seq' + self::assertSame( + 'DROP SEQUENCE user_id_seq, order_id_seq, product_id_seq', + $builder->toSql() ); } @@ -575,9 +577,9 @@ public function test_drop_sequence_restrict() : void $builder = drop()->sequence('user_id_seq') ->restrict(); - $this->assertDropSequenceQuery( - $builder, - 'DROP SEQUENCE user_id_seq' + self::assertSame( + 'DROP SEQUENCE user_id_seq', + $builder->toSql() ); } @@ -585,9 +587,9 @@ public function test_drop_sequence_simple() : void { $builder = drop()->sequence('user_id_seq'); - $this->assertDropSequenceQuery( - $builder, - 'DROP SEQUENCE user_id_seq' + self::assertSame( + 'DROP SEQUENCE user_id_seq', + $builder->toSql() ); } @@ -595,9 +597,9 @@ public function test_drop_sequence_with_schema() : void { $builder = drop()->sequence('public.user_id_seq'); - $this->assertDropSequenceQuery( - $builder, - 'DROP SEQUENCE public.user_id_seq' + self::assertSame( + 'DROP SEQUENCE public.user_id_seq', + $builder->toSql() ); } } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/CreateTable/CreateTableBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/CreateTable/CreateTableBuilderTest.php index 7fcace30fc..c3b1226ee3 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/CreateTable/CreateTableBuilderTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/CreateTable/CreateTableBuilderTest.php @@ -5,7 +5,7 @@ namespace Flow\PostgreSql\Tests\Unit\QueryBuilder\Schema\CreateTable; use Flow\PostgreSql\Protobuf\AST\{CreateStmt, PartitionStrategy}; -use Flow\PostgreSql\QueryBuilder\Schema\{ColumnDefinition, DataType}; +use Flow\PostgreSql\QueryBuilder\Schema\{ColumnDefinition, ColumnType}; use Flow\PostgreSql\QueryBuilder\Schema\Constraint\{ForeignKeyConstraint, PrimaryKeyConstraint, UniqueConstraint}; use Flow\PostgreSql\QueryBuilder\Schema\CreateTable\CreateTableBuilder; use PHPUnit\Framework\TestCase; @@ -22,7 +22,7 @@ protected function setUp() : void public function test_create_table_if_not_exists() : void { $builder = CreateTableBuilder::create('users') - ->column(ColumnDefinition::create('id', DataType::integer())) + ->column(ColumnDefinition::create('id', ColumnType::integer())) ->ifNotExists(); $ast = $builder->toAst(); @@ -34,7 +34,7 @@ public function test_create_table_if_not_exists() : void public function test_create_table_inherits() : void { $builder = CreateTableBuilder::create('employees') - ->column(ColumnDefinition::create('department', DataType::text())) + ->column(ColumnDefinition::create('department', ColumnType::text())) ->inherits('persons'); $ast = $builder->toAst(); @@ -47,7 +47,7 @@ public function test_create_table_inherits() : void public function test_create_table_inherits_multiple() : void { $builder = CreateTableBuilder::create('employees') - ->column(ColumnDefinition::create('department', DataType::text())) + ->column(ColumnDefinition::create('department', ColumnType::text())) ->inherits('persons', 'contacts'); $ast = $builder->toAst(); @@ -59,7 +59,7 @@ public function test_create_table_inherits_multiple() : void public function test_create_table_partition_by_hash() : void { $builder = CreateTableBuilder::create('orders') - ->column(ColumnDefinition::create('id', DataType::integer())) + ->column(ColumnDefinition::create('id', ColumnType::integer())) ->partitionByHash('id'); $ast = $builder->toAst(); @@ -72,7 +72,7 @@ public function test_create_table_partition_by_hash() : void public function test_create_table_partition_by_list() : void { $builder = CreateTableBuilder::create('sales') - ->column(ColumnDefinition::create('region', DataType::text())) + ->column(ColumnDefinition::create('region', ColumnType::text())) ->partitionByList('region'); $ast = $builder->toAst(); @@ -86,7 +86,7 @@ public function test_create_table_partition_by_list() : void public function test_create_table_partition_by_range() : void { $builder = CreateTableBuilder::create('logs') - ->column(ColumnDefinition::create('created_at', DataType::timestamp())) + ->column(ColumnDefinition::create('created_at', ColumnType::timestamp())) ->partitionByRange('created_at'); $ast = $builder->toAst(); @@ -99,7 +99,7 @@ public function test_create_table_partition_by_range() : void public function test_create_table_tablespace() : void { $builder = CreateTableBuilder::create('users') - ->column(ColumnDefinition::create('id', DataType::integer())) + ->column(ColumnDefinition::create('id', ColumnType::integer())) ->tablespace('fast_storage'); $ast = $builder->toAst(); @@ -111,7 +111,7 @@ public function test_create_table_tablespace() : void public function test_create_table_temporary() : void { $builder = CreateTableBuilder::create('temp_users') - ->column(ColumnDefinition::create('id', DataType::integer())) + ->column(ColumnDefinition::create('id', ColumnType::integer())) ->temporary(); $ast = $builder->toAst(); @@ -124,7 +124,7 @@ public function test_create_table_temporary() : void public function test_create_table_unlogged() : void { $builder = CreateTableBuilder::create('unlogged_users') - ->column(ColumnDefinition::create('id', DataType::integer())) + ->column(ColumnDefinition::create('id', ColumnType::integer())) ->unlogged(); $ast = $builder->toAst(); @@ -136,8 +136,8 @@ public function test_create_table_unlogged() : void public function test_create_table_with_constraint() : void { $builder = CreateTableBuilder::create('users') - ->column(ColumnDefinition::create('id', DataType::integer())) - ->column(ColumnDefinition::create('email', DataType::varchar(255))) + ->column(ColumnDefinition::create('id', ColumnType::integer())) + ->column(ColumnDefinition::create('email', ColumnType::varchar(255))) ->constraint(PrimaryKeyConstraint::create('id')) ->constraint(UniqueConstraint::create('email')); @@ -152,8 +152,8 @@ public function test_create_table_with_constraint() : void public function test_create_table_with_foreign_key_constraint() : void { $builder = CreateTableBuilder::create('orders') - ->column(ColumnDefinition::create('id', DataType::integer())) - ->column(ColumnDefinition::create('user_id', DataType::integer())) + ->column(ColumnDefinition::create('id', ColumnType::integer())) + ->column(ColumnDefinition::create('user_id', ColumnType::integer())) ->constraint(ForeignKeyConstraint::create(['user_id'], 'users', ['id'])); $ast = $builder->toAst(); @@ -166,9 +166,9 @@ public function test_create_table_with_foreign_key_constraint() : void public function test_create_table_with_multiple_columns() : void { $builder = CreateTableBuilder::create('users') - ->column(ColumnDefinition::create('id', DataType::serial())) - ->column(ColumnDefinition::create('name', DataType::varchar(100))->notNull()) - ->column(ColumnDefinition::create('email', DataType::varchar(255))->unique()); + ->column(ColumnDefinition::create('id', ColumnType::serial())) + ->column(ColumnDefinition::create('name', ColumnType::varchar(100))->notNull()) + ->column(ColumnDefinition::create('email', ColumnType::varchar(255))->unique()); $ast = $builder->toAst(); @@ -179,7 +179,7 @@ public function test_create_table_with_multiple_columns() : void public function test_create_table_with_schema() : void { $builder = CreateTableBuilder::create('users', 'public') - ->column(ColumnDefinition::create('id', DataType::integer())); + ->column(ColumnDefinition::create('id', ColumnType::integer())); $ast = $builder->toAst(); @@ -191,7 +191,7 @@ public function test_create_table_with_schema() : void public function test_immutability() : void { $original = CreateTableBuilder::create('users') - ->column(ColumnDefinition::create('id', DataType::integer())); + ->column(ColumnDefinition::create('id', ColumnType::integer())); $modified = $original->ifNotExists(); self::assertFalse($original->toAst()->getIfNotExists()); @@ -201,7 +201,7 @@ public function test_immutability() : void public function test_simple_create_table() : void { $builder = CreateTableBuilder::create('users') - ->column(ColumnDefinition::create('id', DataType::integer())); + ->column(ColumnDefinition::create('id', ColumnType::integer())); $ast = $builder->toAst(); diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/CreateTableAs/CreateTableAsBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/CreateTableAs/CreateTableAsBuilderTest.php index 26f827e93b..38712eaa72 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/CreateTableAs/CreateTableAsBuilderTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/CreateTableAs/CreateTableAsBuilderTest.php @@ -4,11 +4,12 @@ namespace Flow\PostgreSql\Tests\Unit\QueryBuilder\Schema\CreateTableAs; +use function Flow\PostgreSql\DSL\{col, literal}; use Flow\PostgreSql\Protobuf\AST\{CreateTableAsStmt, ObjectType}; -use Flow\PostgreSql\QueryBuilder\Expression\RawExpression; use Flow\PostgreSql\QueryBuilder\Schema\CreateTableAs\CreateTableAsBuilder; use Flow\PostgreSql\QueryBuilder\Select\SelectBuilder; use Flow\PostgreSql\QueryBuilder\Table\Table; + use PHPUnit\Framework\TestCase; final class CreateTableAsBuilderTest extends TestCase @@ -23,7 +24,7 @@ protected function setUp() : void public function test_create_table_as_if_not_exists() : void { $select = SelectBuilder::create() - ->select(new RawExpression('1')); + ->select(literal(1)); $builder = CreateTableAsBuilder::create('new_table', $select) ->ifNotExists(); @@ -37,7 +38,7 @@ public function test_create_table_as_if_not_exists() : void public function test_create_table_as_with_column_names() : void { $select = SelectBuilder::create() - ->select(new RawExpression('id'), new RawExpression('name')); + ->select(col('id'), col('name')); $builder = CreateTableAsBuilder::create('new_table', $select) ->columnNames('user_id', 'user_name'); @@ -53,7 +54,7 @@ public function test_create_table_as_with_column_names() : void public function test_create_table_as_with_no_data() : void { $select = SelectBuilder::create() - ->select(new RawExpression('id'), new RawExpression('name')) + ->select(col('id'), col('name')) ->from(new Table('users')); $builder = CreateTableAsBuilder::create('users_copy', $select) @@ -68,7 +69,7 @@ public function test_create_table_as_with_no_data() : void public function test_create_table_as_with_schema() : void { $select = SelectBuilder::create() - ->select(new RawExpression('id'), new RawExpression('email')) + ->select(col('id'), col('email')) ->from(new Table('users')); $builder = CreateTableAsBuilder::create('new_table', $select, 'archive'); @@ -83,7 +84,7 @@ public function test_create_table_as_with_schema() : void public function test_immutability() : void { $select = SelectBuilder::create() - ->select(new RawExpression('1')); + ->select(literal(1)); $original = CreateTableAsBuilder::create('new_table', $select); $modified = $original->ifNotExists(); @@ -95,7 +96,7 @@ public function test_immutability() : void public function test_simple_create_table_as() : void { $select = SelectBuilder::create() - ->select(new RawExpression('id'), new RawExpression('name')) + ->select(col('id'), col('name')) ->from(new Table('users')); $builder = CreateTableAsBuilder::create('users_copy', $select); @@ -111,7 +112,7 @@ public function test_simple_create_table_as() : void public function test_with_all_options() : void { $select = SelectBuilder::create() - ->select(new RawExpression('id'), new RawExpression('name')) + ->select(col('id'), col('name')) ->from(new Table('users')); $builder = CreateTableAsBuilder::create('users_backup', $select, 'archive') diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Database/CreateDatabaseBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Database/CreateDatabaseBuilderTest.php new file mode 100644 index 0000000000..19c9d801fa --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Database/CreateDatabaseBuilderTest.php @@ -0,0 +1,161 @@ +database('mydb')->toSql()); + } + + public function test_create_database_ast_type() : void + { + self::assertInstanceOf(CreatedbStmt::class, CreateDatabaseBuilder::create('mydb')->toAst()); + } + + public function test_create_database_if_not_exists() : void + { + self::assertSame('CREATE DATABASE mydb IF_NOT_EXISTS 1', create()->database('mydb')->ifNotExists()->toSql()); + } + + public function test_create_database_if_not_exists_with_options() : void + { + self::assertSame( + 'CREATE DATABASE mydb IF_NOT_EXISTS 1 OWNER admin', + create()->database('mydb')->ifNotExists()->owner('admin')->toSql() + ); + } + + public function test_create_database_immutability() : void + { + $original = CreateDatabaseBuilder::create('mydb'); + $modified = $original->ifNotExists(); + + self::assertSame('CREATE DATABASE mydb', $original->toSql()); + self::assertSame('CREATE DATABASE mydb IF_NOT_EXISTS 1', $modified->toSql()); + } + + public function test_create_database_sets_name_in_ast() : void + { + self::assertSame('mydb', CreateDatabaseBuilder::create('mydb')->toAst()->getDbname()); + } + + public function test_create_database_with_all_options() : void + { + self::assertSame( + 'CREATE DATABASE mydb OWNER admin TEMPLATE template0 ENCODING "UTF8" LOCALE "en_US.UTF-8" LC_COLLATE "en_US.UTF-8" LC_CTYPE "en_US.UTF-8" CONNECTION LIMIT 10', + create()->database('mydb') + ->owner('admin') + ->template('template0') + ->encoding('UTF8') + ->locale('en_US.UTF-8') + ->lcCollate('en_US.UTF-8') + ->lcCtype('en_US.UTF-8') + ->connectionLimit(10) + ->toSql() + ); + } + + public function test_create_database_with_allow_connections() : void + { + self::assertSame('CREATE DATABASE mydb ALLOW_CONNECTIONS 0', create()->database('mydb')->allowConnections(false)->toSql()); + } + + public function test_create_database_with_allow_connections_true() : void + { + self::assertSame('CREATE DATABASE mydb ALLOW_CONNECTIONS 1', create()->database('mydb')->allowConnections(true)->toSql()); + } + + public function test_create_database_with_builtin_locale() : void + { + self::assertSame('CREATE DATABASE mydb BUILTIN_LOCALE "C"', create()->database('mydb')->builtinLocale('C')->toSql()); + } + + public function test_create_database_with_collation_version() : void + { + self::assertSame('CREATE DATABASE mydb COLLATION_VERSION "1.0"', create()->database('mydb')->collationVersion('1.0')->toSql()); + } + + public function test_create_database_with_connection_limit() : void + { + self::assertSame('CREATE DATABASE mydb CONNECTION LIMIT 100', create()->database('mydb')->connectionLimit(100)->toSql()); + } + + public function test_create_database_with_encoding() : void + { + self::assertSame('CREATE DATABASE mydb ENCODING "UTF8"', create()->database('mydb')->encoding('UTF8')->toSql()); + } + + public function test_create_database_with_icu_locale() : void + { + self::assertSame('CREATE DATABASE mydb ICU_LOCALE "en-US"', create()->database('mydb')->icuLocale('en-US')->toSql()); + } + + public function test_create_database_with_icu_rules() : void + { + self::assertSame('CREATE DATABASE mydb ICU_RULES "&V << w <<< W"', create()->database('mydb')->icuRules('&V << w <<< W')->toSql()); + } + + public function test_create_database_with_is_template() : void + { + self::assertSame('CREATE DATABASE mydb IS_TEMPLATE 1', create()->database('mydb')->isTemplate(true)->toSql()); + } + + public function test_create_database_with_locale() : void + { + self::assertSame('CREATE DATABASE mydb LOCALE "en_US.UTF-8"', create()->database('mydb')->locale('en_US.UTF-8')->toSql()); + } + + public function test_create_database_with_locale_provider() : void + { + self::assertSame('CREATE DATABASE mydb LOCALE_PROVIDER icu', create()->database('mydb')->localeProvider('icu')->toSql()); + } + + public function test_create_database_with_multiple_options() : void + { + self::assertSame( + 'CREATE DATABASE mydb OWNER admin ENCODING "UTF8" CONNECTION LIMIT 50', + create()->database('mydb')->owner('admin')->encoding('UTF8')->connectionLimit(50)->toSql() + ); + } + + public function test_create_database_with_oid() : void + { + self::assertSame('CREATE DATABASE mydb OID 12345', create()->database('mydb')->oid(12345)->toSql()); + } + + public function test_create_database_with_owner() : void + { + self::assertSame('CREATE DATABASE mydb OWNER admin', create()->database('mydb')->owner('admin')->toSql()); + } + + public function test_create_database_with_strategy() : void + { + self::assertSame('CREATE DATABASE mydb STRATEGY wal_log', create()->database('mydb')->strategy('wal_log')->toSql()); + } + + public function test_create_database_with_tablespace() : void + { + self::assertSame('CREATE DATABASE mydb TABLESPACE fast_ssd', create()->database('mydb')->tablespace('fast_ssd')->toSql()); + } + + public function test_create_database_with_template() : void + { + self::assertSame('CREATE DATABASE mydb TEMPLATE template0', create()->database('mydb')->template('template0')->toSql()); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Database/DropDatabaseBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Database/DropDatabaseBuilderTest.php new file mode 100644 index 0000000000..b800ccc487 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Database/DropDatabaseBuilderTest.php @@ -0,0 +1,84 @@ +database('mydb')->toSql()); + } + + public function test_drop_database_ast_type() : void + { + self::assertInstanceOf(DropdbStmt::class, DropDatabaseBuilder::create('mydb')->toAst()); + } + + public function test_drop_database_force() : void + { + self::assertSame('DROP DATABASE mydb (FORCE)', drop()->database('mydb')->force()->toSql()); + } + + public function test_drop_database_force_sets_option_in_ast() : void + { + $ast = DropDatabaseBuilder::create('mydb')->force()->toAst(); + + self::assertCount(1, $ast->getOptions()); + + $defElem = $ast->getOptions()[0]->getDefElem(); + self::assertNotNull($defElem); + self::assertSame('force', $defElem->getDefname()); + } + + public function test_drop_database_if_exists() : void + { + self::assertSame('DROP DATABASE IF EXISTS mydb', drop()->database('mydb')->ifExists()->toSql()); + } + + public function test_drop_database_if_exists_sets_missing_ok_in_ast() : void + { + self::assertTrue(DropDatabaseBuilder::create('mydb')->ifExists()->toAst()->getMissingOk()); + } + + public function test_drop_database_if_exists_with_force() : void + { + self::assertSame('DROP DATABASE IF EXISTS mydb (FORCE)', drop()->database('mydb')->ifExists()->force()->toSql()); + } + + public function test_drop_database_immutability() : void + { + $original = DropDatabaseBuilder::create('mydb'); + $modified = $original->ifExists(); + + self::assertFalse($original->toAst()->getMissingOk()); + self::assertTrue($modified->toAst()->getMissingOk()); + } + + public function test_drop_database_immutability_force() : void + { + $original = DropDatabaseBuilder::create('mydb'); + $withForce = $original->force(); + + self::assertCount(0, $original->toAst()->getOptions()); + self::assertCount(1, $withForce->toAst()->getOptions()); + } + + public function test_drop_database_sets_name_in_ast() : void + { + self::assertSame('mydb', DropDatabaseBuilder::create('mydb')->toAst()->getDbname()); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Domain/DomainBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Domain/DomainBuilderTest.php index 4089bf7219..7c03b92f6e 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Domain/DomainBuilderTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Domain/DomainBuilderTest.php @@ -4,8 +4,11 @@ namespace Flow\PostgreSql\Tests\Unit\QueryBuilder\Schema\Domain; -use function Flow\PostgreSql\DSL\data_type_text; +use function Flow\PostgreSql\DSL\{alter, col, column_type_text, create, drop, literal}; + use Flow\PostgreSql\Protobuf\AST\{AlterDomainStmt, ConstrType, CreateDomainStmt, DropBehavior, DropStmt, ObjectType}; +use Flow\PostgreSql\QueryBuilder\Condition\OperatorCondition; +use Flow\PostgreSql\QueryBuilder\Schema\ColumnType; use Flow\PostgreSql\QueryBuilder\Schema\Domain\{AlterDomainBuilder, CreateDomainBuilder, DropDomainBuilder}; use PHPUnit\Framework\TestCase; @@ -22,7 +25,7 @@ protected function setUp() : void public function test_alter_domain_add_constraint() : void { $builder = AlterDomainBuilder::create('email') - ->addConstraint('valid_email', "VALUE ~ '^.+@.+$'"); + ->addConstraint('valid_email', new OperatorCondition(col('VALUE'), '~', literal('^.+@.+$'))); $ast = $builder->toAst(); @@ -62,6 +65,17 @@ public function test_alter_domain_drop_constraint() : void self::assertSame('valid_email', $ast->getName()); } + public function test_alter_domain_drop_constraint_cascade_to_sql() : void + { + self::assertSame( + 'ALTER DOMAIN email DROP CONSTRAINT valid_email CASCADE', + alter()->domain('email') + ->dropConstraint('valid_email') + ->cascade() + ->toSql() + ); + } + public function test_alter_domain_drop_default() : void { $builder = AlterDomainBuilder::create('email') @@ -96,7 +110,7 @@ public function test_alter_domain_restrict() : void public function test_alter_domain_set_default() : void { $builder = AlterDomainBuilder::create('email') - ->setDefault("'default@example.com'"); + ->setDefault(literal('default@example.com')); $ast = $builder->toAst(); @@ -128,7 +142,7 @@ public function test_alter_domain_validate_constraint() : void public function test_create_domain_ast_type() : void { $builder = CreateDomainBuilder::create('email') - ->as(data_type_text()); + ->as(column_type_text()); $ast = $builder->toAst(); @@ -138,7 +152,7 @@ public function test_create_domain_ast_type() : void public function test_create_domain_sets_name() : void { $builder = CreateDomainBuilder::create('email') - ->as(data_type_text()); + ->as(column_type_text()); $ast = $builder->toAst(); $domainname = $ast->getDomainname(); @@ -149,7 +163,7 @@ public function test_create_domain_sets_name() : void public function test_create_domain_sets_type() : void { $builder = CreateDomainBuilder::create('email') - ->as(data_type_text()); + ->as(column_type_text()); $ast = $builder->toAst(); $typeName = $ast->getTypeName(); @@ -158,11 +172,21 @@ public function test_create_domain_sets_type() : void self::assertCount(2, $typeName->getNames()); } + public function test_create_domain_simple_to_sql() : void + { + self::assertSame( + 'CREATE DOMAIN email AS pg_catalog.text', + create()->domain('email') + ->as(ColumnType::text()) + ->toSql() + ); + } + public function test_create_domain_with_check() : void { $builder = CreateDomainBuilder::create('email') - ->as(data_type_text()) - ->check("VALUE ~ '^.+@.+$'"); + ->as(column_type_text()) + ->check(new OperatorCondition(col('VALUE'), '~', literal('^.+@.+$'))); $ast = $builder->toAst(); $constraints = $ast->getConstraints(); @@ -177,7 +201,7 @@ public function test_create_domain_with_check() : void public function test_create_domain_with_collation() : void { $builder = CreateDomainBuilder::create('email') - ->as(data_type_text()) + ->as(column_type_text()) ->collate('en_US'); $ast = $builder->toAst(); @@ -188,8 +212,8 @@ public function test_create_domain_with_collation() : void public function test_create_domain_with_default() : void { $builder = CreateDomainBuilder::create('email') - ->as(data_type_text()) - ->default("'default@example.com'"); + ->as(column_type_text()) + ->default(literal('default@example.com')); $ast = $builder->toAst(); $constraints = $ast->getConstraints(); @@ -204,9 +228,9 @@ public function test_create_domain_with_default() : void public function test_create_domain_with_multiple_constraints() : void { $builder = CreateDomainBuilder::create('email') - ->as(data_type_text()) + ->as(column_type_text()) ->notNull() - ->check("VALUE ~ '^.+@.+$'"); + ->check(new OperatorCondition(col('VALUE'), '~', literal('^.+@.+$'))); $ast = $builder->toAst(); $constraints = $ast->getConstraints(); @@ -217,9 +241,9 @@ public function test_create_domain_with_multiple_constraints() : void public function test_create_domain_with_named_constraint() : void { $builder = CreateDomainBuilder::create('email') - ->as(data_type_text()) + ->as(column_type_text()) ->constraint('valid_email') - ->check("VALUE ~ '^.+@.+$'"); + ->check(new OperatorCondition(col('VALUE'), '~', literal('^.+@.+$'))); $ast = $builder->toAst(); $constraints = $ast->getConstraints(); @@ -234,7 +258,7 @@ public function test_create_domain_with_named_constraint() : void public function test_create_domain_with_not_null() : void { $builder = CreateDomainBuilder::create('email') - ->as(data_type_text()) + ->as(column_type_text()) ->notNull(); $ast = $builder->toAst(); @@ -250,7 +274,7 @@ public function test_create_domain_with_not_null() : void public function test_create_domain_with_null() : void { $builder = CreateDomainBuilder::create('email') - ->as(data_type_text()) + ->as(column_type_text()) ->null(); $ast = $builder->toAst(); @@ -266,7 +290,7 @@ public function test_create_domain_with_null() : void public function test_create_domain_with_schema() : void { $builder = CreateDomainBuilder::create('public.email') - ->as(data_type_text()); + ->as(column_type_text()); $ast = $builder->toAst(); $domainname = $ast->getDomainname(); @@ -304,6 +328,17 @@ public function test_drop_domain_if_exists() : void self::assertTrue($ast->getMissingOk()); } + public function test_drop_domain_if_exists_cascade_to_sql() : void + { + self::assertSame( + 'DROP DOMAIN IF EXISTS email CASCADE', + drop()->domain('email') + ->ifExists() + ->cascade() + ->toSql() + ); + } + public function test_drop_domain_immutability() : void { $original = DropDomainBuilder::create('email'); @@ -322,6 +357,15 @@ public function test_drop_domain_multiple_domains() : void self::assertCount(3, $ast->getObjects()); } + public function test_drop_domain_multiple_to_sql() : void + { + self::assertSame( + 'DROP DOMAIN email, phone, url', + drop()->domain('email', 'phone', 'url') + ->toSql() + ); + } + public function test_drop_domain_restrict() : void { $builder = DropDomainBuilder::create('email') @@ -331,4 +375,13 @@ public function test_drop_domain_restrict() : void self::assertSame(DropBehavior::DROP_RESTRICT, $ast->getBehavior()); } + + public function test_drop_domain_simple_to_sql() : void + { + self::assertSame( + 'DROP DOMAIN email', + drop()->domain('email') + ->toSql() + ); + } } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Extension/ExtensionBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Extension/ExtensionBuilderTest.php index 3f569a211a..9d5ff23c39 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Extension/ExtensionBuilderTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Extension/ExtensionBuilderTest.php @@ -4,6 +4,7 @@ namespace Flow\PostgreSql\Tests\Unit\QueryBuilder\Schema\Extension; +use function Flow\PostgreSql\DSL\{alter, create, drop}; use Flow\PostgreSql\Protobuf\AST\{AlterExtensionContentsStmt, AlterExtensionStmt, CreateExtensionStmt, DropBehavior, DropStmt, ObjectType}; use Flow\PostgreSql\QueryBuilder\Schema\Extension\{AlterExtensionBuilder, CreateExtensionBuilder, DropExtensionBuilder}; use PHPUnit\Framework\TestCase; @@ -29,6 +30,11 @@ public function test_alter_extension_add_function_ast_type() : void self::assertSame(1, $ast->getAction()); } + public function test_alter_extension_add_function_to_sql() : void + { + self::assertSame('ALTER EXTENSION postgis ADD FUNCTION st_distance', alter()->extension('postgis')->addFunction('st_distance')->toSql()); + } + public function test_alter_extension_add_table_ast_type() : void { $builder = AlterExtensionBuilder::create('postgis') @@ -41,6 +47,11 @@ public function test_alter_extension_add_table_ast_type() : void self::assertSame(1, $ast->getAction()); } + public function test_alter_extension_add_table_to_sql() : void + { + self::assertSame('ALTER EXTENSION postgis ADD TABLE spatial_ref_sys', alter()->extension('postgis')->addTable('spatial_ref_sys')->toSql()); + } + public function test_alter_extension_drop_function_ast_type() : void { $builder = AlterExtensionBuilder::create('postgis') @@ -53,6 +64,11 @@ public function test_alter_extension_drop_function_ast_type() : void self::assertSame(-1, $ast->getAction()); } + public function test_alter_extension_drop_function_to_sql() : void + { + self::assertSame('ALTER EXTENSION postgis DROP FUNCTION st_distance', alter()->extension('postgis')->dropFunction('st_distance')->toSql()); + } + public function test_alter_extension_drop_table_ast_type() : void { $builder = AlterExtensionBuilder::create('postgis') @@ -65,6 +81,11 @@ public function test_alter_extension_drop_table_ast_type() : void self::assertSame(-1, $ast->getAction()); } + public function test_alter_extension_drop_table_to_sql() : void + { + self::assertSame('ALTER EXTENSION postgis DROP TABLE spatial_ref_sys', alter()->extension('postgis')->dropTable('spatial_ref_sys')->toSql()); + } + public function test_alter_extension_update_ast_type() : void { $builder = AlterExtensionBuilder::create('postgis') @@ -103,6 +124,16 @@ public function test_alter_extension_update_to_sets_version() : void self::assertSame('new_version', $defElem->getDefname()); } + public function test_alter_extension_update_to_sql() : void + { + self::assertSame('ALTER EXTENSION postgis UPDATE', alter()->extension('postgis')->update()->toSql()); + } + + public function test_alter_extension_update_to_version_to_sql() : void + { + self::assertSame('ALTER EXTENSION postgis UPDATE TO "3.1"', alter()->extension('postgis')->updateTo('3.1')->toSql()); + } + public function test_create_extension_ast_type() : void { $builder = CreateExtensionBuilder::create('uuid-ossp'); @@ -127,6 +158,11 @@ public function test_create_extension_cascade_sets_option() : void self::assertSame('cascade', $defElem->getDefname()); } + public function test_create_extension_full_to_sql() : void + { + self::assertSame('CREATE EXTENSION IF NOT EXISTS postgis SCHEMA public VERSION "3.0" CASCADE', create()->extension('postgis')->ifNotExists()->schema('public')->version('3.0')->cascade()->toSql()); + } + public function test_create_extension_if_not_exists_sets_flag() : void { $builder = CreateExtensionBuilder::create('postgis') @@ -137,6 +173,11 @@ public function test_create_extension_if_not_exists_sets_flag() : void self::assertTrue($ast->getIfNotExists()); } + public function test_create_extension_if_not_exists_to_sql() : void + { + self::assertSame('CREATE EXTENSION IF NOT EXISTS postgis', create()->extension('postgis')->ifNotExists()->toSql()); + } + public function test_create_extension_immutability() : void { $original = CreateExtensionBuilder::create('postgis'); @@ -170,6 +211,11 @@ public function test_create_extension_sets_name() : void self::assertSame('postgis', $ast->getExtname()); } + public function test_create_extension_simple_to_sql() : void + { + self::assertSame('CREATE EXTENSION "uuid-ossp"', create()->extension('uuid-ossp')->toSql()); + } + public function test_create_extension_version_sets_option() : void { $builder = CreateExtensionBuilder::create('postgis') @@ -185,6 +231,21 @@ public function test_create_extension_version_sets_option() : void self::assertSame('new_version', $defElem->getDefname()); } + public function test_create_extension_with_cascade_to_sql() : void + { + self::assertSame('CREATE EXTENSION postgis CASCADE', create()->extension('postgis')->cascade()->toSql()); + } + + public function test_create_extension_with_schema_to_sql() : void + { + self::assertSame('CREATE EXTENSION postgis SCHEMA public', create()->extension('postgis')->schema('public')->toSql()); + } + + public function test_create_extension_with_version_to_sql() : void + { + self::assertSame('CREATE EXTENSION postgis VERSION "3.0"', create()->extension('postgis')->version('3.0')->toSql()); + } + public function test_drop_extension_ast_type() : void { $builder = DropExtensionBuilder::create('postgis'); @@ -205,6 +266,16 @@ public function test_drop_extension_cascade_sets_behavior() : void self::assertSame(DropBehavior::DROP_CASCADE, $ast->getBehavior()); } + public function test_drop_extension_cascade_to_sql() : void + { + self::assertSame('DROP EXTENSION postgis CASCADE', drop()->extension('postgis')->cascade()->toSql()); + } + + public function test_drop_extension_if_exists_cascade_to_sql() : void + { + self::assertSame('DROP EXTENSION IF EXISTS postgis CASCADE', drop()->extension('postgis')->ifExists()->cascade()->toSql()); + } + public function test_drop_extension_if_exists_sets_flag() : void { $builder = DropExtensionBuilder::create('postgis') @@ -215,6 +286,11 @@ public function test_drop_extension_if_exists_sets_flag() : void self::assertTrue($ast->getMissingOk()); } + public function test_drop_extension_if_exists_to_sql() : void + { + self::assertSame('DROP EXTENSION IF EXISTS postgis', drop()->extension('postgis')->ifExists()->toSql()); + } + public function test_drop_extension_immutability() : void { $original = DropExtensionBuilder::create('postgis'); @@ -233,6 +309,11 @@ public function test_drop_extension_multiple_extensions() : void self::assertCount(3, $ast->getObjects()); } + public function test_drop_extension_multiple_to_sql() : void + { + self::assertSame('DROP EXTENSION postgis, pg_trgm, "uuid-ossp"', drop()->extension('postgis', 'pg_trgm', 'uuid-ossp')->toSql()); + } + public function test_drop_extension_restrict_sets_behavior() : void { $builder = DropExtensionBuilder::create('postgis') @@ -243,6 +324,11 @@ public function test_drop_extension_restrict_sets_behavior() : void self::assertSame(DropBehavior::DROP_RESTRICT, $ast->getBehavior()); } + public function test_drop_extension_restrict_to_sql() : void + { + self::assertSame('DROP EXTENSION postgis', drop()->extension('postgis')->restrict()->toSql()); + } + public function test_drop_extension_sets_name() : void { $builder = DropExtensionBuilder::create('postgis'); @@ -251,4 +337,9 @@ public function test_drop_extension_sets_name() : void self::assertCount(1, $ast->getObjects()); } + + public function test_drop_extension_simple_to_sql() : void + { + self::assertSame('DROP EXTENSION postgis', drop()->extension('postgis')->toSql()); + } } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Function/FunctionArgumentTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Function/FunctionArgumentTest.php index c8f17d57e6..0a4fd9a854 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Function/FunctionArgumentTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Function/FunctionArgumentTest.php @@ -4,7 +4,7 @@ namespace Flow\PostgreSql\Tests\Unit\QueryBuilder\Schema\Function; -use Flow\PostgreSql\QueryBuilder\Schema\DataType; +use Flow\PostgreSql\QueryBuilder\Schema\ColumnType; use Flow\PostgreSql\QueryBuilder\Schema\Function\{ArgumentMode, FunctionArgument}; use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; @@ -14,9 +14,9 @@ final class FunctionArgumentTest extends TestCase #[Test] public function test_function_argument_basic() : void { - $arg = FunctionArgument::of(DataType::integer()); + $arg = FunctionArgument::of(ColumnType::integer()); - self::assertInstanceOf(DataType::class, $arg->type); + self::assertInstanceOf(ColumnType::class, $arg->type); self::assertNull($arg->name); self::assertSame(ArgumentMode::IN, $arg->mode); self::assertNull($arg->default); @@ -25,7 +25,7 @@ public function test_function_argument_basic() : void #[Test] public function test_function_argument_in_mode() : void { - $arg = FunctionArgument::of(DataType::text())->in(); + $arg = FunctionArgument::of(ColumnType::text())->in(); self::assertSame(ArgumentMode::IN, $arg->mode); } @@ -33,7 +33,7 @@ public function test_function_argument_in_mode() : void #[Test] public function test_function_argument_inout_mode() : void { - $arg = FunctionArgument::of(DataType::text())->inout(); + $arg = FunctionArgument::of(ColumnType::text())->inout(); self::assertSame(ArgumentMode::INOUT, $arg->mode); } @@ -41,16 +41,16 @@ public function test_function_argument_inout_mode() : void #[Test] public function test_function_argument_named() : void { - $arg = FunctionArgument::of(DataType::text())->named('username'); + $arg = FunctionArgument::of(ColumnType::text())->named('username'); self::assertSame('username', $arg->name); - self::assertInstanceOf(DataType::class, $arg->type); + self::assertInstanceOf(ColumnType::class, $arg->type); } #[Test] public function test_function_argument_out_mode() : void { - $arg = FunctionArgument::of(DataType::integer())->out(); + $arg = FunctionArgument::of(ColumnType::integer())->out(); self::assertSame(ArgumentMode::OUT, $arg->mode); } @@ -58,7 +58,7 @@ public function test_function_argument_out_mode() : void #[Test] public function test_function_argument_variadic_mode() : void { - $arg = FunctionArgument::of(DataType::text())->variadic(); + $arg = FunctionArgument::of(ColumnType::text())->variadic(); self::assertSame(ArgumentMode::VARIADIC, $arg->mode); } @@ -66,7 +66,7 @@ public function test_function_argument_variadic_mode() : void #[Test] public function test_function_argument_with_default() : void { - $arg = FunctionArgument::of(DataType::integer())->default('0'); + $arg = FunctionArgument::of(ColumnType::integer())->default('0'); self::assertSame('0', $arg->default); } @@ -74,12 +74,12 @@ public function test_function_argument_with_default() : void #[Test] public function test_function_argument_with_mode_and_name_and_default() : void { - $arg = FunctionArgument::of(DataType::text()) + $arg = FunctionArgument::of(ColumnType::text()) ->named('value') ->out() ->default('null'); - self::assertInstanceOf(DataType::class, $arg->type); + self::assertInstanceOf(ColumnType::class, $arg->type); self::assertSame('value', $arg->name); self::assertSame(ArgumentMode::OUT, $arg->mode); self::assertSame('null', $arg->default); diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/FunctionBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Function/FunctionBuilderTest.php similarity index 58% rename from src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/FunctionBuilderTest.php rename to src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Function/FunctionBuilderTest.php index 62b4b187b4..e7d607c73c 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/FunctionBuilderTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Function/FunctionBuilderTest.php @@ -2,118 +2,119 @@ declare(strict_types=1); -namespace Flow\PostgreSql\Tests\Integration\QueryBuilder; +namespace Flow\PostgreSql\Tests\Unit\QueryBuilder\Schema\Function; -use function Flow\PostgreSql\DSL\{alter, call, create, data_type_integer, data_type_text, do_block, drop, func_arg}; +use function Flow\PostgreSql\DSL\{alter, call, column_type_integer, column_type_text, create, do_block, drop, func_arg}; use Flow\PostgreSql\QueryBuilder\Schema\Function\ParallelSafety; +use PHPUnit\Framework\TestCase; -final class FunctionBuilderTest extends PGQueryTestCase +final class FunctionBuilderTest extends TestCase { public function test_alter_function_immutable() : void { $builder = alter()->function('my_func') - ->arguments(func_arg(data_type_integer())) + ->arguments(func_arg(column_type_integer())) ->immutable(); - $this->assertAlterFunctionQuery($builder, 'ALTER FUNCTION my_func(int) IMMUTABLE'); + self::assertSame('ALTER FUNCTION my_func(int) IMMUTABLE', $builder->toSql()); } public function test_alter_function_parallel_safe() : void { $builder = alter()->function('my_func') - ->arguments(func_arg(data_type_integer())) + ->arguments(func_arg(column_type_integer())) ->parallel(ParallelSafety::SAFE); - $this->assertAlterFunctionQuery($builder, 'ALTER FUNCTION my_func(int) PARALLEL safe'); + self::assertSame('ALTER FUNCTION my_func(int) PARALLEL safe', $builder->toSql()); } public function test_alter_function_rename() : void { $builder = alter()->function('old_name') - ->arguments(func_arg(data_type_text())) + ->arguments(func_arg(column_type_text())) ->renameTo('new_name'); - $this->assertAlterFunctionRenameQuery($builder, 'ALTER FUNCTION old_name(pg_catalog.text) RENAME TO new_name'); + self::assertSame('ALTER FUNCTION old_name(pg_catalog.text) RENAME TO new_name', $builder->toSql()); } public function test_alter_procedure_rename() : void { $builder = alter()->procedure('old_proc') - ->arguments(func_arg(data_type_integer())) + ->arguments(func_arg(column_type_integer())) ->renameTo('new_proc'); - $this->assertAlterProcedureRenameQuery($builder, 'ALTER PROCEDURE old_proc(int) RENAME TO new_proc'); + self::assertSame('ALTER PROCEDURE old_proc(int) RENAME TO new_proc', $builder->toSql()); } public function test_call_procedure() : void { $builder = call('update_stats'); - $this->assertCallQuery($builder, 'CALL update_stats()'); + self::assertSame('CALL update_stats()', $builder->toSql()); } public function test_call_procedure_with_args() : void { $builder = call('update_stats')->with(123, 'test'); - $this->assertCallQuery($builder, "CALL update_stats(123, 'test')"); + self::assertSame("CALL update_stats(123, 'test')", $builder->toSql()); } public function test_create_function_plpgsql() : void { $builder = create()->function('increment') - ->arguments(func_arg(data_type_integer())->named('val')) - ->returns(data_type_integer()) + ->arguments(func_arg(column_type_integer())->named('val')) + ->returns(column_type_integer()) ->language('plpgsql') ->as('BEGIN RETURN val + 1; END;'); - $this->assertCreateFunctionQuery( - $builder, - 'CREATE FUNCTION increment(IN val int) RETURNS int LANGUAGE plpgsql AS $$BEGIN RETURN val + 1; END;$$' + self::assertSame( + 'CREATE FUNCTION increment(IN val int) RETURNS int LANGUAGE plpgsql AS $$BEGIN RETURN val + 1; END;$$', + $builder->toSql() ); } public function test_create_function_returns_table() : void { $builder = create()->function('get_users') - ->returnsTable(['id' => data_type_integer(), 'name' => data_type_text()]) + ->returnsTable(['id' => column_type_integer(), 'name' => column_type_text()]) ->language('sql') ->as('SELECT id, name FROM users'); - $this->assertCreateFunctionQuery( - $builder, - 'CREATE FUNCTION get_users() RETURNS TABLE (id int, name pg_catalog.text) LANGUAGE sql AS $$SELECT id, name FROM users$$' + self::assertSame( + 'CREATE FUNCTION get_users() RETURNS TABLE (id int, name pg_catalog.text) LANGUAGE sql AS $$SELECT id, name FROM users$$', + $builder->toSql() ); } public function test_create_function_simple() : void { $builder = create()->function('add_numbers') - ->arguments(func_arg(data_type_integer())->named('a'), func_arg(data_type_integer())->named('b')) - ->returns(data_type_integer()) + ->arguments(func_arg(column_type_integer())->named('a'), func_arg(column_type_integer())->named('b')) + ->returns(column_type_integer()) ->language('sql') ->as('SELECT a + b'); - $this->assertCreateFunctionQuery( - $builder, - 'CREATE FUNCTION add_numbers(IN a int, IN b int) RETURNS int LANGUAGE sql AS $$SELECT a + b$$' + self::assertSame( + 'CREATE FUNCTION add_numbers(IN a int, IN b int) RETURNS int LANGUAGE sql AS $$SELECT a + b$$', + $builder->toSql() ); } public function test_create_function_with_options() : void { $builder = create()->function('compute') - ->arguments(func_arg(data_type_integer())->named('x')) - ->returns(data_type_integer()) + ->arguments(func_arg(column_type_integer())->named('x')) + ->returns(column_type_integer()) ->language('sql') ->immutable() ->parallel(ParallelSafety::SAFE) ->strict() ->as('SELECT x * 2'); - $this->assertCreateFunctionQuery( - $builder, - 'CREATE FUNCTION compute(IN x int) RETURNS int LANGUAGE sql IMMUTABLE PARALLEL safe RETURNS NULL ON NULL INPUT AS $$SELECT x * 2$$' + self::assertSame( + 'CREATE FUNCTION compute(IN x int) RETURNS int LANGUAGE sql IMMUTABLE PARALLEL safe RETURNS NULL ON NULL INPUT AS $$SELECT x * 2$$', + $builder->toSql() ); } @@ -121,26 +122,26 @@ public function test_create_function_with_or_replace() : void { $builder = create()->function('my_func') ->orReplace() - ->returns(data_type_integer()) + ->returns(column_type_integer()) ->language('sql') ->as('SELECT 1'); - $this->assertCreateFunctionQuery( - $builder, - 'CREATE OR REPLACE FUNCTION my_func() RETURNS int LANGUAGE sql AS $$SELECT 1$$' + self::assertSame( + 'CREATE OR REPLACE FUNCTION my_func() RETURNS int LANGUAGE sql AS $$SELECT 1$$', + $builder->toSql() ); } public function test_create_procedure() : void { $builder = create()->procedure('update_stats') - ->arguments(func_arg(data_type_integer())->named('user_id')) + ->arguments(func_arg(column_type_integer())->named('user_id')) ->language('plpgsql') ->as('BEGIN UPDATE stats SET count = count + 1 WHERE id = user_id; END;'); - $this->assertCreateProcedureQuery( - $builder, - 'CREATE PROCEDURE update_stats(IN user_id int) LANGUAGE plpgsql AS $$BEGIN UPDATE stats SET count = count + 1 WHERE id = user_id; END;$$' + self::assertSame( + 'CREATE PROCEDURE update_stats(IN user_id int) LANGUAGE plpgsql AS $$BEGIN UPDATE stats SET count = count + 1 WHERE id = user_id; END;$$', + $builder->toSql() ); } @@ -151,9 +152,9 @@ public function test_create_procedure_with_or_replace() : void ->language('sql') ->as('SELECT 1'); - $this->assertCreateProcedureQuery( - $builder, - 'CREATE OR REPLACE PROCEDURE my_proc() LANGUAGE sql AS $$SELECT 1$$' + self::assertSame( + 'CREATE OR REPLACE PROCEDURE my_proc() LANGUAGE sql AS $$SELECT 1$$', + $builder->toSql() ); } @@ -161,47 +162,47 @@ public function test_do_block() : void { $builder = do_block('BEGIN RAISE NOTICE $$Hello$$; END;'); - $this->assertDoQuery($builder, 'DO $outer$BEGIN RAISE NOTICE $$Hello$$; END;$outer$ LANGUAGE plpgsql'); + self::assertSame('DO $outer$BEGIN RAISE NOTICE $$Hello$$; END;$outer$ LANGUAGE plpgsql', $builder->toSql()); } public function test_do_block_with_language() : void { $builder = do_block('SELECT 1')->language('sql'); - $this->assertDoQuery($builder, 'DO $$SELECT 1$$ LANGUAGE sql'); + self::assertSame('DO $$SELECT 1$$ LANGUAGE sql', $builder->toSql()); } public function test_drop_function() : void { $builder = drop()->function('my_func'); - $this->assertDropFunctionQuery($builder, 'DROP FUNCTION my_func'); + self::assertSame('DROP FUNCTION my_func', $builder->toSql()); } public function test_drop_function_if_exists_cascade() : void { $builder = drop()->function('my_func') ->ifExists() - ->arguments(func_arg(data_type_integer()), func_arg(data_type_text())) + ->arguments(func_arg(column_type_integer()), func_arg(column_type_text())) ->cascade(); - $this->assertDropFunctionQuery($builder, 'DROP FUNCTION IF EXISTS my_func(int, pg_catalog.text) CASCADE'); + self::assertSame('DROP FUNCTION IF EXISTS my_func(int, pg_catalog.text) CASCADE', $builder->toSql()); } public function test_drop_procedure() : void { $builder = drop()->procedure('my_proc'); - $this->assertDropProcedureQuery($builder, 'DROP PROCEDURE my_proc'); + self::assertSame('DROP PROCEDURE my_proc', $builder->toSql()); } public function test_drop_procedure_if_exists() : void { $builder = drop()->procedure('my_proc') ->ifExists() - ->arguments(func_arg(data_type_integer())) + ->arguments(func_arg(column_type_integer())) ->cascade(); - $this->assertDropProcedureQuery($builder, 'DROP PROCEDURE IF EXISTS my_proc(int) CASCADE'); + self::assertSame('DROP PROCEDURE IF EXISTS my_proc(int) CASCADE', $builder->toSql()); } } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/IndexBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Index/IndexBuilderTest.php similarity index 71% rename from src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/IndexBuilderTest.php rename to src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Index/IndexBuilderTest.php index ced07255b7..0af88aa73e 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/IndexBuilderTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Index/IndexBuilderTest.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\PostgreSql\Tests\Integration\QueryBuilder; +namespace Flow\PostgreSql\Tests\Unit\QueryBuilder\Schema\Index; use function Flow\PostgreSql\DSL\{alter, col, @@ -19,16 +19,18 @@ reindex_schema, reindex_table}; -final class IndexBuilderTest extends PGQueryTestCase +use PHPUnit\Framework\TestCase; + +final class IndexBuilderTest extends TestCase { public function test_alter_index_rename() : void { $builder = alter()->index('idx_old') ->renameTo('idx_new'); - $this->assertAlterIndexRenameQuery( - $builder, - 'ALTER INDEX idx_old RENAME TO idx_new' + self::assertSame( + 'ALTER INDEX idx_old RENAME TO idx_new', + $builder->toSql() ); } @@ -38,9 +40,9 @@ public function test_alter_index_rename_if_exists() : void ->ifExists() ->renameTo('idx_new'); - $this->assertAlterIndexRenameQuery( - $builder, - 'ALTER INDEX IF EXISTS idx_old RENAME TO idx_new' + self::assertSame( + 'ALTER INDEX IF EXISTS idx_old RENAME TO idx_new', + $builder->toSql() ); } @@ -49,9 +51,9 @@ public function test_alter_index_rename_with_schema() : void $builder = alter()->index('idx_old', 'public') ->renameTo('idx_new'); - $this->assertAlterIndexRenameQuery( - $builder, - 'ALTER INDEX public.idx_old RENAME TO idx_new' + self::assertSame( + 'ALTER INDEX public.idx_old RENAME TO idx_new', + $builder->toSql() ); } @@ -60,9 +62,9 @@ public function test_alter_index_set_tablespace() : void $builder = alter()->index('idx_users_email') ->setTablespace('fast_storage'); - $this->assertAlterIndexTablespaceQuery( - $builder, - 'ALTER INDEX idx_users_email SET TABLESPACE fast_storage' + self::assertSame( + 'ALTER INDEX idx_users_email SET TABLESPACE fast_storage', + $builder->toSql() ); } @@ -72,9 +74,9 @@ public function test_alter_index_set_tablespace_if_exists() : void ->ifExists() ->setTablespace('fast_storage'); - $this->assertAlterIndexTablespaceQuery( - $builder, - 'ALTER INDEX IF EXISTS idx_users_email SET TABLESPACE fast_storage' + self::assertSame( + 'ALTER INDEX IF EXISTS idx_users_email SET TABLESPACE fast_storage', + $builder->toSql() ); } @@ -85,9 +87,9 @@ public function test_create_index_concurrently() : void ->on('users') ->columns('email'); - $this->assertCreateIndexQuery( - $builder, - 'CREATE INDEX CONCURRENTLY idx_users_email ON users (email)' + self::assertSame( + 'CREATE INDEX CONCURRENTLY idx_users_email ON users (email)', + $builder->toSql() ); } @@ -98,9 +100,9 @@ public function test_create_index_if_not_exists() : void ->on('users') ->columns('email'); - $this->assertCreateIndexQuery( - $builder, - 'CREATE INDEX IF NOT EXISTS idx_users_email ON users (email)' + self::assertSame( + 'CREATE INDEX IF NOT EXISTS idx_users_email ON users (email)', + $builder->toSql() ); } @@ -110,9 +112,9 @@ public function test_create_index_simple() : void ->on('users') ->columns('email'); - $this->assertCreateIndexQuery( - $builder, - 'CREATE INDEX idx_users_email ON users (email)' + self::assertSame( + 'CREATE INDEX idx_users_email ON users (email)', + $builder->toSql() ); } @@ -123,9 +125,9 @@ public function test_create_index_unique() : void ->on('users') ->columns('email'); - $this->assertCreateIndexQuery( - $builder, - 'CREATE UNIQUE INDEX idx_users_email ON users (email)' + self::assertSame( + 'CREATE UNIQUE INDEX idx_users_email ON users (email)', + $builder->toSql() ); } @@ -138,9 +140,9 @@ public function test_create_index_unique_concurrently_if_not_exists() : void ->on('users') ->columns('email'); - $this->assertCreateIndexQuery( - $builder, - 'CREATE UNIQUE INDEX CONCURRENTLY IF NOT EXISTS idx_users_email ON users (email)' + self::assertSame( + 'CREATE UNIQUE INDEX CONCURRENTLY IF NOT EXISTS idx_users_email ON users (email)', + $builder->toSql() ); } @@ -151,9 +153,9 @@ public function test_create_index_with_btree_method() : void ->using(index_method_btree()) ->columns('email'); - $this->assertCreateIndexQuery( - $builder, - 'CREATE INDEX idx_users_email ON users USING btree (email)' + self::assertSame( + 'CREATE INDEX idx_users_email ON users USING btree (email)', + $builder->toSql() ); } @@ -163,9 +165,9 @@ public function test_create_index_with_desc_order() : void ->on('users') ->columns(index_col('created_at')->desc()); - $this->assertCreateIndexQuery( - $builder, - 'CREATE INDEX idx_users_created_at ON users (created_at DESC)' + self::assertSame( + 'CREATE INDEX idx_users_created_at ON users (created_at DESC)', + $builder->toSql() ); } @@ -176,9 +178,9 @@ public function test_create_index_with_gin_method() : void ->using(index_method_gin()) ->columns('content'); - $this->assertCreateIndexQuery( - $builder, - 'CREATE INDEX idx_documents_content ON documents USING gin (content)' + self::assertSame( + 'CREATE INDEX idx_documents_content ON documents USING gin (content)', + $builder->toSql() ); } @@ -189,9 +191,9 @@ public function test_create_index_with_hash_method() : void ->using(index_method_hash()) ->columns('email'); - $this->assertCreateIndexQuery( - $builder, - 'CREATE INDEX idx_users_email ON users USING hash (email)' + self::assertSame( + 'CREATE INDEX idx_users_email ON users USING hash (email)', + $builder->toSql() ); } @@ -202,9 +204,9 @@ public function test_create_index_with_include() : void ->columns('email') ->include('name', 'created_at'); - $this->assertCreateIndexQuery( - $builder, - 'CREATE INDEX idx_users_email ON users (email) INCLUDE (name, created_at)' + self::assertSame( + 'CREATE INDEX idx_users_email ON users (email) INCLUDE (name, created_at)', + $builder->toSql() ); } @@ -214,9 +216,9 @@ public function test_create_index_with_multiple_columns() : void ->on('users') ->columns('name', 'email'); - $this->assertCreateIndexQuery( - $builder, - 'CREATE INDEX idx_users_name_email ON users (name, email)' + self::assertSame( + 'CREATE INDEX idx_users_name_email ON users (name, email)', + $builder->toSql() ); } @@ -226,9 +228,9 @@ public function test_create_index_with_nulls_first() : void ->on('users') ->columns(index_col('created_at')->desc()->nullsFirst()); - $this->assertCreateIndexQuery( - $builder, - 'CREATE INDEX idx_users_created_at ON users (created_at DESC NULLS FIRST)' + self::assertSame( + 'CREATE INDEX idx_users_created_at ON users (created_at DESC NULLS FIRST)', + $builder->toSql() ); } @@ -238,9 +240,9 @@ public function test_create_index_with_nulls_last() : void ->on('users') ->columns(index_col('created_at')->nullsLast()); - $this->assertCreateIndexQuery( - $builder, - 'CREATE INDEX idx_users_created_at ON users (created_at NULLS LAST)' + self::assertSame( + 'CREATE INDEX idx_users_created_at ON users (created_at NULLS LAST)', + $builder->toSql() ); } @@ -252,9 +254,9 @@ public function test_create_index_with_nulls_not_distinct() : void ->columns('email') ->nullsNotDistinct(); - $this->assertCreateIndexQuery( - $builder, - 'CREATE UNIQUE INDEX idx_users_email ON users (email) NULLS NOT DISTINCT' + self::assertSame( + 'CREATE UNIQUE INDEX idx_users_email ON users (email) NULLS NOT DISTINCT', + $builder->toSql() ); } @@ -264,9 +266,9 @@ public function test_create_index_with_on_only() : void ->onOnly('users') ->columns('email'); - $this->assertCreateIndexQuery( - $builder, - 'CREATE INDEX idx_users_email ON ONLY users (email)' + self::assertSame( + 'CREATE INDEX idx_users_email ON ONLY users (email)', + $builder->toSql() ); } @@ -276,9 +278,9 @@ public function test_create_index_with_schema() : void ->on('users', 'public') ->columns('email'); - $this->assertCreateIndexQuery( - $builder, - 'CREATE INDEX idx_users_email ON public.users (email)' + self::assertSame( + 'CREATE INDEX idx_users_email ON public.users (email)', + $builder->toSql() ); } @@ -289,9 +291,9 @@ public function test_create_index_with_tablespace() : void ->columns('email') ->tablespace('fast_storage'); - $this->assertCreateIndexQuery( - $builder, - 'CREATE INDEX idx_users_email ON users (email) TABLESPACE fast_storage' + self::assertSame( + 'CREATE INDEX idx_users_email ON users (email) TABLESPACE fast_storage', + $builder->toSql() ); } @@ -302,9 +304,9 @@ public function test_create_partial_index() : void ->columns('email') ->where(eq(col('active'), literal(true))); - $this->assertCreateIndexQuery( - $builder, - 'CREATE INDEX idx_users_active_email ON users (email) WHERE active = true' + self::assertSame( + 'CREATE INDEX idx_users_active_email ON users (email) WHERE active = true', + $builder->toSql() ); } @@ -313,9 +315,9 @@ public function test_drop_index_cascade() : void $builder = drop()->index('idx_users_email') ->cascade(); - $this->assertDropIndexQuery( - $builder, - 'DROP INDEX idx_users_email CASCADE' + self::assertSame( + 'DROP INDEX idx_users_email CASCADE', + $builder->toSql() ); } @@ -324,9 +326,9 @@ public function test_drop_index_concurrently() : void $builder = drop()->index('idx_users_email') ->concurrently(); - $this->assertDropIndexQuery( - $builder, - 'DROP INDEX CONCURRENTLY idx_users_email' + self::assertSame( + 'DROP INDEX CONCURRENTLY idx_users_email', + $builder->toSql() ); } @@ -335,9 +337,9 @@ public function test_drop_index_if_exists() : void $builder = drop()->index('idx_users_email') ->ifExists(); - $this->assertDropIndexQuery( - $builder, - 'DROP INDEX IF EXISTS idx_users_email' + self::assertSame( + 'DROP INDEX IF EXISTS idx_users_email', + $builder->toSql() ); } @@ -347,9 +349,9 @@ public function test_drop_index_if_exists_cascade() : void ->ifExists() ->cascade(); - $this->assertDropIndexQuery( - $builder, - 'DROP INDEX IF EXISTS idx_users_email CASCADE' + self::assertSame( + 'DROP INDEX IF EXISTS idx_users_email CASCADE', + $builder->toSql() ); } @@ -357,9 +359,9 @@ public function test_drop_index_multiple() : void { $builder = drop()->index('idx_users_email', 'idx_users_name', 'idx_orders_date'); - $this->assertDropIndexQuery( - $builder, - 'DROP INDEX idx_users_email, idx_users_name, idx_orders_date' + self::assertSame( + 'DROP INDEX idx_users_email, idx_users_name, idx_orders_date', + $builder->toSql() ); } @@ -368,9 +370,9 @@ public function test_drop_index_restrict() : void $builder = drop()->index('idx_users_email') ->restrict(); - $this->assertDropIndexQuery( - $builder, - 'DROP INDEX idx_users_email' + self::assertSame( + 'DROP INDEX idx_users_email', + $builder->toSql() ); } @@ -378,9 +380,9 @@ public function test_drop_index_simple() : void { $builder = drop()->index('idx_users_email'); - $this->assertDropIndexQuery( - $builder, - 'DROP INDEX idx_users_email' + self::assertSame( + 'DROP INDEX idx_users_email', + $builder->toSql() ); } @@ -388,9 +390,9 @@ public function test_drop_index_with_schema() : void { $builder = drop()->index('public.idx_users_email'); - $this->assertDropIndexQuery( - $builder, - 'DROP INDEX public.idx_users_email' + self::assertSame( + 'DROP INDEX public.idx_users_email', + $builder->toSql() ); } @@ -398,9 +400,9 @@ public function test_reindex_database() : void { $builder = reindex_database('mydb'); - $this->assertReindexQuery( - $builder, - 'REINDEX DATABASE mydb' + self::assertSame( + 'REINDEX DATABASE mydb', + $builder->toSql() ); } @@ -408,9 +410,9 @@ public function test_reindex_index() : void { $builder = reindex_index('idx_users_email'); - $this->assertReindexQuery( - $builder, - 'REINDEX INDEX idx_users_email' + self::assertSame( + 'REINDEX INDEX idx_users_email', + $builder->toSql() ); } @@ -419,9 +421,9 @@ public function test_reindex_index_concurrently() : void $builder = reindex_index('idx_users_email') ->concurrently(); - $this->assertReindexQuery( - $builder, - 'REINDEX (CONCURRENTLY) INDEX idx_users_email' + self::assertSame( + 'REINDEX (CONCURRENTLY) INDEX idx_users_email', + $builder->toSql() ); } @@ -430,9 +432,9 @@ public function test_reindex_index_with_tablespace() : void $builder = reindex_index('idx_users_email') ->tablespace('fast_storage'); - $this->assertReindexQuery( - $builder, - 'REINDEX (TABLESPACE fast_storage) INDEX idx_users_email' + self::assertSame( + 'REINDEX (TABLESPACE fast_storage) INDEX idx_users_email', + $builder->toSql() ); } @@ -440,9 +442,9 @@ public function test_reindex_schema() : void { $builder = reindex_schema('public'); - $this->assertReindexQuery( - $builder, - 'REINDEX SCHEMA public' + self::assertSame( + 'REINDEX SCHEMA public', + $builder->toSql() ); } @@ -450,9 +452,9 @@ public function test_reindex_table() : void { $builder = reindex_table('users'); - $this->assertReindexQuery( - $builder, - 'REINDEX TABLE users' + self::assertSame( + 'REINDEX TABLE users', + $builder->toSql() ); } @@ -461,9 +463,9 @@ public function test_reindex_table_concurrently() : void $builder = reindex_table('users') ->concurrently(); - $this->assertReindexQuery( - $builder, - 'REINDEX (CONCURRENTLY) TABLE users' + self::assertSame( + 'REINDEX (CONCURRENTLY) TABLE users', + $builder->toSql() ); } @@ -472,9 +474,9 @@ public function test_reindex_table_verbose() : void $builder = reindex_table('users') ->verbose(); - $this->assertReindexQuery( - $builder, - 'REINDEX (VERBOSE) TABLE users' + self::assertSame( + 'REINDEX (VERBOSE) TABLE users', + $builder->toSql() ); } @@ -482,9 +484,9 @@ public function test_reindex_table_with_schema() : void { $builder = reindex_table('public.users'); - $this->assertReindexQuery( - $builder, - 'REINDEX TABLE public.users' + self::assertSame( + 'REINDEX TABLE public.users', + $builder->toSql() ); } } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Index/IndexColumnTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Index/IndexColumnTest.php index ab98976f99..0112d121af 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Index/IndexColumnTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Index/IndexColumnTest.php @@ -4,9 +4,10 @@ namespace Flow\PostgreSql\Tests\Unit\QueryBuilder\Schema\Index; +use function Flow\PostgreSql\DSL\{col, func}; use Flow\PostgreSql\Protobuf\AST\{IndexElem, SortByDir, SortByNulls}; -use Flow\PostgreSql\QueryBuilder\Expression\RawExpression; use Flow\PostgreSql\QueryBuilder\Schema\Index\IndexColumn; + use PHPUnit\Framework\TestCase; final class IndexColumnTest extends TestCase @@ -79,7 +80,7 @@ public function test_desc_sets_ordering() : void public function test_expression_creates_index_elem() : void { - $column = IndexColumn::expression(new RawExpression('lower(name)')); + $column = IndexColumn::expression(func('lower', [col('name')])); $ast = $column->toAst(); diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Role/RoleBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Role/RoleBuilderTest.php index d6868c870e..8a9218e5f7 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Role/RoleBuilderTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Role/RoleBuilderTest.php @@ -4,7 +4,9 @@ namespace Flow\PostgreSql\Tests\Unit\QueryBuilder\Schema\Role; +use function Flow\PostgreSql\DSL\{alter, create, drop, grant, grant_role, reassign_owned, reset_role, revoke, revoke_role, set_role}; use Flow\PostgreSql\Protobuf\AST\{AlterRoleStmt, CreateRoleStmt, DropRoleStmt, ObjectType, RenameStmt, RoleSpecType, RoleStmtType}; +use Flow\PostgreSql\QueryBuilder\Schema\Grant\TablePrivilege; use Flow\PostgreSql\QueryBuilder\Schema\Role\{AlterRoleBuilder, CreateRoleBuilder, DropRoleBuilder}; use PHPUnit\Framework\TestCase; @@ -49,6 +51,16 @@ public function test_alter_role_rename_sets_names() : void self::assertSame('new_name', $ast->getNewname()); } + public function test_alter_role_rename_to_sql() : void + { + self::assertSame('ALTER ROLE old_name RENAME TO new_name', alter()->role('old_name')->renameTo('new_name')->toSql()); + } + + public function test_alter_role_set_options_to_sql() : void + { + self::assertSame('ALTER ROLE admin WITH SUPERUSER', alter()->role('admin')->superuser()->toSql()); + } + public function test_alter_role_sets_role_spec() : void { $builder = AlterRoleBuilder::create('admin') @@ -62,6 +74,11 @@ public function test_alter_role_sets_role_spec() : void self::assertSame('admin', $roleSpec->getRolename()); } + public function test_alter_role_with_multiple_options_to_sql() : void + { + self::assertSame('ALTER ROLE admin WITH NOSUPERUSER CREATEDB', alter()->role('admin')->noSuperuser()->createDb()->toSql()); + } + public function test_create_role_ast_type() : void { $builder = CreateRoleBuilder::create('admin'); @@ -90,6 +107,11 @@ public function test_create_role_sets_name() : void self::assertSame('admin', $ast->getRole()); } + public function test_create_role_simple_to_sql() : void + { + self::assertSame('CREATE ROLE admin', create()->role('admin')->toSql()); + } + public function test_create_role_with_login_option() : void { $builder = CreateRoleBuilder::create('app_user') @@ -105,6 +127,11 @@ public function test_create_role_with_login_option() : void self::assertSame('canlogin', $defElem->getDefname()); } + public function test_create_role_with_login_to_sql() : void + { + self::assertSame('CREATE ROLE app_user WITH LOGIN', create()->role('app_user')->login()->toSql()); + } + public function test_create_role_with_multiple_options() : void { $builder = CreateRoleBuilder::create('admin') @@ -118,6 +145,11 @@ public function test_create_role_with_multiple_options() : void self::assertCount(3, $options); } + public function test_create_role_with_options_to_sql() : void + { + self::assertSame('CREATE ROLE admin WITH SUPERUSER LOGIN', create()->role('admin')->superuser()->login()->toSql()); + } + public function test_create_role_with_password_option() : void { $builder = CreateRoleBuilder::create('admin') @@ -148,6 +180,21 @@ public function test_create_role_with_superuser_option() : void self::assertSame('superuser', $defElem->getDefname()); } + public function test_create_user_with_password_to_sql() : void + { + self::assertSame("CREATE ROLE app_user WITH LOGIN PASSWORD 'secret'", create()->role('app_user')->login()->withPassword('secret')->toSql()); + } + + public function test_drop_owned_by_cascade_to_sql() : void + { + self::assertSame('DROP OWNED BY role1 CASCADE', drop()->owned('role1')->cascade()->toSql()); + } + + public function test_drop_owned_by_to_sql() : void + { + self::assertSame('DROP OWNED BY role1', drop()->owned('role1')->toSql()); + } + public function test_drop_role_ast_type() : void { $builder = DropRoleBuilder::create('admin'); @@ -167,6 +214,11 @@ public function test_drop_role_if_exists_sets_flag() : void self::assertTrue($ast->getMissingOk()); } + public function test_drop_role_if_exists_to_sql() : void + { + self::assertSame('DROP ROLE IF EXISTS admin', drop()->role('admin')->ifExists()->toSql()); + } + public function test_drop_role_immutability() : void { $original = DropRoleBuilder::create('admin'); @@ -185,6 +237,11 @@ public function test_drop_role_multiple_roles() : void self::assertCount(3, $ast->getRoles()); } + public function test_drop_role_multiple_to_sql() : void + { + self::assertSame('DROP ROLE role1, role2', drop()->role('role1', 'role2')->toSql()); + } + public function test_drop_role_sets_role_names() : void { $builder = DropRoleBuilder::create('admin'); @@ -199,4 +256,74 @@ public function test_drop_role_sets_role_names() : void self::assertSame(RoleSpecType::ROLESPEC_CSTRING, $roleSpec->getRoletype()); self::assertSame('admin', $roleSpec->getRolename()); } + + public function test_drop_role_simple_to_sql() : void + { + self::assertSame('DROP ROLE admin', drop()->role('admin')->toSql()); + } + + public function test_grant_all_on_table_to_sql() : void + { + self::assertSame('GRANT ALL ON users TO admin', grant(TablePrivilege::ALL)->onTable('users')->to('admin')->toSql()); + } + + public function test_grant_on_all_tables_in_schema_to_sql() : void + { + self::assertSame('GRANT select ON ALL TABLES IN SCHEMA public TO admin', grant(TablePrivilege::SELECT)->onAllTablesInSchema('public')->to('admin')->toSql()); + } + + public function test_grant_role_to_role_to_sql() : void + { + self::assertSame('GRANT admin TO user1', grant_role('admin')->to('user1')->toSql()); + } + + public function test_grant_role_with_admin_option_to_sql() : void + { + self::assertSame('GRANT admin TO user1 WITH ADMIN OPTION', grant_role('admin')->to('user1')->withAdminOption()->toSql()); + } + + public function test_grant_select_on_table_to_sql() : void + { + self::assertSame('GRANT select ON users TO app_user', grant(TablePrivilege::SELECT)->onTable('users')->to('app_user')->toSql()); + } + + public function test_grant_with_grant_option_to_sql() : void + { + self::assertSame('GRANT select ON users TO app_user WITH GRANT OPTION', grant(TablePrivilege::SELECT)->onTable('users')->to('app_user')->withGrantOption()->toSql()); + } + + public function test_reassign_owned_by_to_sql() : void + { + self::assertSame('REASSIGN OWNED BY old_role TO new_role', reassign_owned('old_role')->to('new_role')->toSql()); + } + + public function test_reset_role_to_sql() : void + { + self::assertSame('RESET role', reset_role()->toSql()); + } + + public function test_revoke_role_cascade_to_sql() : void + { + self::assertSame('REVOKE admin FROM user1 CASCADE', revoke_role('admin')->from('user1')->cascade()->toSql()); + } + + public function test_revoke_role_from_role_to_sql() : void + { + self::assertSame('REVOKE admin FROM user1', revoke_role('admin')->from('user1')->toSql()); + } + + public function test_revoke_select_on_table_to_sql() : void + { + self::assertSame('REVOKE select ON users FROM app_user', revoke(TablePrivilege::SELECT)->onTable('users')->from('app_user')->toSql()); + } + + public function test_revoke_with_cascade_to_sql() : void + { + self::assertSame('REVOKE select ON users FROM app_user CASCADE', revoke(TablePrivilege::SELECT)->onTable('users')->from('app_user')->cascade()->toSql()); + } + + public function test_set_role_to_sql() : void + { + self::assertSame('SET role TO admin', set_role('admin')->toSql()); + } } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/RuleBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Rule/RuleBuilderTest.php similarity index 60% rename from src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/RuleBuilderTest.php rename to src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Rule/RuleBuilderTest.php index 973aa6097b..c72b07054a 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/RuleBuilderTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Rule/RuleBuilderTest.php @@ -2,16 +2,13 @@ declare(strict_types=1); -namespace Flow\PostgreSql\Tests\Integration\QueryBuilder; +namespace Flow\PostgreSql\Tests\Unit\QueryBuilder\Schema\Rule; -use function Flow\PostgreSql\DSL\{create, drop}; -use Flow\PostgreSql\Tests\Integration\QueryBuilder\Assertions\QueryBuilderAssertions; +use function Flow\PostgreSql\DSL\{col, create, drop, eq, literal}; use PHPUnit\Framework\TestCase; final class RuleBuilderTest extends TestCase { - use QueryBuilderAssertions; - public function test_create_rule_do_also_insert() : void { $builder = create()->rule('audit_insert') @@ -19,7 +16,7 @@ public function test_create_rule_do_also_insert() : void ->to('users') ->doAlso("INSERT INTO audit_log (action) VALUES ('insert')"); - $this->assertCreateRuleQuery($builder, "CREATE RULE audit_insert AS ON INSERT TO users DO INSERT INTO audit_log (action) VALUES ('insert')"); + self::assertSame("CREATE RULE audit_insert AS ON INSERT TO users DO INSERT INTO audit_log (action) VALUES ('insert')", $builder->toSql()); } public function test_create_rule_do_instead_delete() : void @@ -29,7 +26,7 @@ public function test_create_rule_do_instead_delete() : void ->to('users') ->doInstead('UPDATE users SET deleted = true WHERE id = OLD.id'); - $this->assertCreateRuleQuery($builder, 'CREATE RULE soft_delete AS ON DELETE TO users DO INSTEAD UPDATE users SET deleted = true WHERE id = old.id'); + self::assertSame('CREATE RULE soft_delete AS ON DELETE TO users DO INSTEAD UPDATE users SET deleted = true WHERE id = old.id', $builder->toSql()); } public function test_create_rule_do_nothing() : void @@ -39,7 +36,7 @@ public function test_create_rule_do_nothing() : void ->to('users') ->doNothing(); - $this->assertCreateRuleQuery($builder, 'CREATE RULE prevent_delete AS ON DELETE TO users DO NOTHING'); + self::assertSame('CREATE RULE prevent_delete AS ON DELETE TO users DO NOTHING', $builder->toSql()); } public function test_create_rule_on_select() : void @@ -49,7 +46,7 @@ public function test_create_rule_on_select() : void ->to('old_table') ->doInstead('SELECT * FROM new_table'); - $this->assertCreateRuleQuery($builder, 'CREATE RULE redirect_select AS ON SELECT TO old_table DO INSTEAD SELECT * FROM new_table'); + self::assertSame('CREATE RULE redirect_select AS ON SELECT TO old_table DO INSTEAD SELECT * FROM new_table', $builder->toSql()); } public function test_create_rule_on_update() : void @@ -59,7 +56,7 @@ public function test_create_rule_on_update() : void ->to('users') ->doAlso("INSERT INTO update_log (table_name) VALUES ('users')"); - $this->assertCreateRuleQuery($builder, "CREATE RULE track_update AS ON UPDATE TO users DO INSERT INTO update_log (table_name) VALUES ('users')"); + self::assertSame("CREATE RULE track_update AS ON UPDATE TO users DO INSERT INTO update_log (table_name) VALUES ('users')", $builder->toSql()); } public function test_create_rule_or_replace() : void @@ -70,7 +67,7 @@ public function test_create_rule_or_replace() : void ->to('users') ->doNothing(); - $this->assertCreateRuleQuery($builder, 'CREATE OR REPLACE RULE prevent_delete AS ON DELETE TO users DO NOTHING'); + self::assertSame('CREATE OR REPLACE RULE prevent_delete AS ON DELETE TO users DO NOTHING', $builder->toSql()); } public function test_create_rule_with_schema() : void @@ -80,7 +77,7 @@ public function test_create_rule_with_schema() : void ->to('public.users') ->doNothing(); - $this->assertCreateRuleQuery($builder, 'CREATE RULE prevent_delete AS ON DELETE TO public.users DO NOTHING'); + self::assertSame('CREATE RULE prevent_delete AS ON DELETE TO public.users DO NOTHING', $builder->toSql()); } public function test_create_rule_with_where_condition() : void @@ -88,10 +85,10 @@ public function test_create_rule_with_where_condition() : void $builder = create()->rule('protect_admin') ->asOnDelete() ->to('users') - ->where('OLD.role = \'admin\'') + ->where(eq(col('role', 'old'), literal('admin'))) ->doNothing(); - $this->assertCreateRuleQuery($builder, "CREATE RULE protect_admin AS ON DELETE TO users WHERE old.role = 'admin' DO NOTHING"); + self::assertSame("CREATE RULE protect_admin AS ON DELETE TO users WHERE old.role = 'admin' DO NOTHING", $builder->toSql()); } public function test_drop_rule() : void @@ -99,7 +96,7 @@ public function test_drop_rule() : void $builder = drop()->rule('prevent_delete') ->on('users'); - $this->assertDropRuleQuery($builder, 'DROP RULE prevent_delete ON users'); + self::assertSame('DROP RULE prevent_delete ON users', $builder->toSql()); } public function test_drop_rule_cascade() : void @@ -108,7 +105,7 @@ public function test_drop_rule_cascade() : void ->on('users') ->cascade(); - $this->assertDropRuleQuery($builder, 'DROP RULE prevent_delete ON users CASCADE'); + self::assertSame('DROP RULE prevent_delete ON users CASCADE', $builder->toSql()); } public function test_drop_rule_if_exists() : void @@ -117,7 +114,7 @@ public function test_drop_rule_if_exists() : void ->ifExists() ->on('users'); - $this->assertDropRuleQuery($builder, 'DROP RULE IF EXISTS prevent_delete ON users'); + self::assertSame('DROP RULE IF EXISTS prevent_delete ON users', $builder->toSql()); } public function test_drop_rule_with_schema() : void @@ -126,6 +123,6 @@ public function test_drop_rule_with_schema() : void ->on('public.users') ->restrict(); - $this->assertDropRuleQuery($builder, 'DROP RULE prevent_delete ON public.users'); + self::assertSame('DROP RULE prevent_delete ON public.users', $builder->toSql()); } } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Schema/SchemaBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Schema/SchemaBuilderTest.php index 43fb8c2e97..6cae74dd9d 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Schema/SchemaBuilderTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Schema/SchemaBuilderTest.php @@ -4,6 +4,7 @@ namespace Flow\PostgreSql\Tests\Unit\QueryBuilder\Schema\Schema; +use function Flow\PostgreSql\DSL\{alter, create, drop}; use Flow\PostgreSql\Protobuf\AST\{AlterOwnerStmt, CreateSchemaStmt, DropBehavior, DropStmt, ObjectType, RenameStmt, RoleSpecType}; use Flow\PostgreSql\QueryBuilder\Schema\Schema\{AlterSchemaBuilder, CreateSchemaBuilder, DropSchemaBuilder}; use PHPUnit\Framework\TestCase; @@ -41,6 +42,11 @@ public function test_alter_schema_owner_sets_new_owner() : void self::assertSame('admin_user', $newOwner->getRolename()); } + public function test_alter_schema_owner_to_sql() : void + { + self::assertSame('ALTER SCHEMA my_schema OWNER TO new_owner', alter()->schema('my_schema')->ownerTo('new_owner')->toSql()); + } + public function test_alter_schema_rename_ast_type() : void { $builder = AlterSchemaBuilder::create('old_schema') @@ -63,6 +69,11 @@ public function test_alter_schema_rename_sets_names() : void self::assertSame('new_schema', $ast->getNewname()); } + public function test_alter_schema_rename_to_sql() : void + { + self::assertSame('ALTER SCHEMA old_schema RENAME TO new_schema', alter()->schema('old_schema')->renameTo('new_schema')->toSql()); + } + public function test_create_schema_ast_type() : void { $builder = CreateSchemaBuilder::create('my_schema'); @@ -95,6 +106,16 @@ public function test_create_schema_if_not_exists_sets_flag() : void self::assertTrue($ast->getIfNotExists()); } + public function test_create_schema_if_not_exists_to_sql() : void + { + self::assertSame('CREATE SCHEMA IF NOT EXISTS my_schema', create()->schema('my_schema')->ifNotExists()->toSql()); + } + + public function test_create_schema_if_not_exists_with_authorization_to_sql() : void + { + self::assertSame('CREATE SCHEMA IF NOT EXISTS my_schema AUTHORIZATION admin_user', create()->schema('my_schema')->ifNotExists()->authorization('admin_user')->toSql()); + } + public function test_create_schema_immutability() : void { $original = CreateSchemaBuilder::create('my_schema'); @@ -113,6 +134,16 @@ public function test_create_schema_sets_name() : void self::assertSame('my_schema', $ast->getSchemaname()); } + public function test_create_schema_simple_to_sql() : void + { + self::assertSame('CREATE SCHEMA my_schema', create()->schema('my_schema')->toSql()); + } + + public function test_create_schema_with_authorization_to_sql() : void + { + self::assertSame('CREATE SCHEMA my_schema AUTHORIZATION admin_user', create()->schema('my_schema')->authorization('admin_user')->toSql()); + } + public function test_drop_schema_ast_type() : void { $builder = DropSchemaBuilder::create('my_schema'); @@ -133,6 +164,16 @@ public function test_drop_schema_cascade_sets_behavior() : void self::assertSame(DropBehavior::DROP_CASCADE, $ast->getBehavior()); } + public function test_drop_schema_cascade_to_sql() : void + { + self::assertSame('DROP SCHEMA my_schema CASCADE', drop()->schema('my_schema')->cascade()->toSql()); + } + + public function test_drop_schema_if_exists_cascade_to_sql() : void + { + self::assertSame('DROP SCHEMA IF EXISTS my_schema CASCADE', drop()->schema('my_schema')->ifExists()->cascade()->toSql()); + } + public function test_drop_schema_if_exists_sets_flag() : void { $builder = DropSchemaBuilder::create('my_schema') @@ -143,6 +184,11 @@ public function test_drop_schema_if_exists_sets_flag() : void self::assertTrue($ast->getMissingOk()); } + public function test_drop_schema_if_exists_to_sql() : void + { + self::assertSame('DROP SCHEMA IF EXISTS my_schema', drop()->schema('my_schema')->ifExists()->toSql()); + } + public function test_drop_schema_immutability() : void { $original = DropSchemaBuilder::create('my_schema'); @@ -161,6 +207,11 @@ public function test_drop_schema_multiple_schemas() : void self::assertCount(3, $ast->getObjects()); } + public function test_drop_schema_multiple_to_sql() : void + { + self::assertSame('DROP SCHEMA schema1, schema2', drop()->schema('schema1', 'schema2')->toSql()); + } + public function test_drop_schema_restrict_sets_behavior() : void { $builder = DropSchemaBuilder::create('my_schema') @@ -170,4 +221,14 @@ public function test_drop_schema_restrict_sets_behavior() : void self::assertSame(DropBehavior::DROP_RESTRICT, $ast->getBehavior()); } + + public function test_drop_schema_restrict_to_sql() : void + { + self::assertSame('DROP SCHEMA my_schema', drop()->schema('my_schema')->restrict()->toSql()); + } + + public function test_drop_schema_simple_to_sql() : void + { + self::assertSame('DROP SCHEMA my_schema', drop()->schema('my_schema')->toSql()); + } } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/TriggerBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Trigger/TriggerBuilderTest.php similarity index 61% rename from src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/TriggerBuilderTest.php rename to src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Trigger/TriggerBuilderTest.php index 3a60dc7455..43348b4bd8 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/TriggerBuilderTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Trigger/TriggerBuilderTest.php @@ -2,23 +2,20 @@ declare(strict_types=1); -namespace Flow\PostgreSql\Tests\Integration\QueryBuilder; +namespace Flow\PostgreSql\Tests\Unit\QueryBuilder\Schema\Trigger; -use function Flow\PostgreSql\DSL\{alter, create, drop, raw_cond}; +use function Flow\PostgreSql\DSL\{alter, col, create, drop, eq, literal}; use Flow\PostgreSql\QueryBuilder\Schema\Trigger\TriggerEvent; -use Flow\PostgreSql\Tests\Integration\QueryBuilder\Assertions\QueryBuilderAssertions; use PHPUnit\Framework\TestCase; final class TriggerBuilderTest extends TestCase { - use QueryBuilderAssertions; - public function test_alter_table_disable_trigger() : void { $builder = alter()->table('users') ->disableTrigger('audit_trigger'); - $this->assertAlterTableQuery($builder, 'ALTER TABLE users DISABLE TRIGGER audit_trigger'); + self::assertSame('ALTER TABLE users DISABLE TRIGGER audit_trigger', $builder->toSql()); } public function test_alter_table_disable_trigger_all() : void @@ -26,7 +23,7 @@ public function test_alter_table_disable_trigger_all() : void $builder = alter()->table('users') ->disableTriggerAll(); - $this->assertAlterTableQuery($builder, 'ALTER TABLE users DISABLE TRIGGER ALL'); + self::assertSame('ALTER TABLE users DISABLE TRIGGER ALL', $builder->toSql()); } public function test_alter_table_disable_trigger_user() : void @@ -34,7 +31,7 @@ public function test_alter_table_disable_trigger_user() : void $builder = alter()->table('users') ->disableTriggerUser(); - $this->assertAlterTableQuery($builder, 'ALTER TABLE users DISABLE TRIGGER USER'); + self::assertSame('ALTER TABLE users DISABLE TRIGGER USER', $builder->toSql()); } public function test_alter_table_enable_trigger() : void @@ -42,7 +39,7 @@ public function test_alter_table_enable_trigger() : void $builder = alter()->table('users') ->enableTrigger('audit_trigger'); - $this->assertAlterTableQuery($builder, 'ALTER TABLE users ENABLE TRIGGER audit_trigger'); + self::assertSame('ALTER TABLE users ENABLE TRIGGER audit_trigger', $builder->toSql()); } public function test_alter_table_enable_trigger_all() : void @@ -50,7 +47,7 @@ public function test_alter_table_enable_trigger_all() : void $builder = alter()->table('users') ->enableTriggerAll(); - $this->assertAlterTableQuery($builder, 'ALTER TABLE users ENABLE TRIGGER ALL'); + self::assertSame('ALTER TABLE users ENABLE TRIGGER ALL', $builder->toSql()); } public function test_alter_table_enable_trigger_always() : void @@ -58,7 +55,7 @@ public function test_alter_table_enable_trigger_always() : void $builder = alter()->table('users') ->enableTriggerAlways('audit_trigger'); - $this->assertAlterTableQuery($builder, 'ALTER TABLE users ENABLE ALWAYS TRIGGER audit_trigger'); + self::assertSame('ALTER TABLE users ENABLE ALWAYS TRIGGER audit_trigger', $builder->toSql()); } public function test_alter_table_enable_trigger_replica() : void @@ -66,7 +63,7 @@ public function test_alter_table_enable_trigger_replica() : void $builder = alter()->table('users') ->enableTriggerReplica('audit_trigger'); - $this->assertAlterTableQuery($builder, 'ALTER TABLE users ENABLE REPLICA TRIGGER audit_trigger'); + self::assertSame('ALTER TABLE users ENABLE REPLICA TRIGGER audit_trigger', $builder->toSql()); } public function test_alter_table_enable_trigger_user() : void @@ -74,7 +71,7 @@ public function test_alter_table_enable_trigger_user() : void $builder = alter()->table('users') ->enableTriggerUser(); - $this->assertAlterTableQuery($builder, 'ALTER TABLE users ENABLE TRIGGER USER'); + self::assertSame('ALTER TABLE users ENABLE TRIGGER USER', $builder->toSql()); } public function test_alter_trigger_depends_on_extension() : void @@ -83,7 +80,7 @@ public function test_alter_trigger_depends_on_extension() : void ->on('users') ->dependsOnExtension('my_extension'); - $this->assertAlterTriggerDependsQuery($builder, 'ALTER TRIGGER my_trigger ON users DEPENDS ON EXTENSION my_extension'); + self::assertSame('ALTER TRIGGER my_trigger ON users DEPENDS ON EXTENSION my_extension', $builder->toSql()); } public function test_alter_trigger_no_depends_on_extension() : void @@ -92,7 +89,7 @@ public function test_alter_trigger_no_depends_on_extension() : void ->on('users') ->noDependsOnExtension('my_extension'); - $this->assertAlterTriggerDependsQuery($builder, 'ALTER TRIGGER my_trigger ON users NO DEPENDS ON EXTENSION my_extension'); + self::assertSame('ALTER TRIGGER my_trigger ON users NO DEPENDS ON EXTENSION my_extension', $builder->toSql()); } public function test_alter_trigger_rename() : void @@ -101,7 +98,7 @@ public function test_alter_trigger_rename() : void ->on('users') ->renameTo('new_trigger'); - $this->assertAlterTriggerRenameQuery($builder, 'ALTER TRIGGER old_trigger ON users RENAME TO new_trigger'); + self::assertSame('ALTER TRIGGER old_trigger ON users RENAME TO new_trigger', $builder->toSql()); } public function test_create_trigger_after_insert() : void @@ -111,7 +108,7 @@ public function test_create_trigger_after_insert() : void ->on('users') ->execute('audit_function'); - $this->assertCreateTriggerQuery($builder, 'CREATE TRIGGER audit_trigger AFTER INSERT ON users EXECUTE FUNCTION audit_function()'); + self::assertSame('CREATE TRIGGER audit_trigger AFTER INSERT ON users EXECUTE FUNCTION audit_function()', $builder->toSql()); } public function test_create_trigger_after_insert_or_update() : void @@ -122,7 +119,7 @@ public function test_create_trigger_after_insert_or_update() : void ->forEachRow() ->execute('audit_function'); - $this->assertCreateTriggerQuery($builder, 'CREATE TRIGGER audit_trigger AFTER INSERT OR UPDATE ON users FOR EACH ROW EXECUTE FUNCTION audit_function()'); + self::assertSame('CREATE TRIGGER audit_trigger AFTER INSERT OR UPDATE ON users FOR EACH ROW EXECUTE FUNCTION audit_function()', $builder->toSql()); } public function test_create_trigger_after_update_of_columns() : void @@ -133,7 +130,7 @@ public function test_create_trigger_after_update_of_columns() : void ->forEachRow() ->execute('track_changes_function'); - $this->assertCreateTriggerQuery($builder, 'CREATE TRIGGER track_changes AFTER UPDATE OF status, updated_at ON orders FOR EACH ROW EXECUTE FUNCTION track_changes_function()'); + self::assertSame('CREATE TRIGGER track_changes AFTER UPDATE OF status, updated_at ON orders FOR EACH ROW EXECUTE FUNCTION track_changes_function()', $builder->toSql()); } public function test_create_trigger_before_delete_with_when() : void @@ -142,10 +139,10 @@ public function test_create_trigger_before_delete_with_when() : void ->before(TriggerEvent::DELETE) ->on('users') ->forEachRow() - ->when(raw_cond('OLD.protected = true')) + ->when(eq(col('protected', 'old'), literal(true))) ->execute('raise_exception'); - $this->assertCreateTriggerQuery($builder, 'CREATE TRIGGER prevent_delete BEFORE DELETE ON users FOR EACH ROW WHEN (old.protected = true) EXECUTE FUNCTION raise_exception()'); + self::assertSame('CREATE TRIGGER prevent_delete BEFORE DELETE ON users FOR EACH ROW WHEN (old.protected = true) EXECUTE FUNCTION raise_exception()', $builder->toSql()); } public function test_create_trigger_constraint_deferrable() : void @@ -160,7 +157,7 @@ public function test_create_trigger_constraint_deferrable() : void ->forEachRow() ->execute('check_fk'); - $this->assertCreateTriggerQuery($builder, 'CREATE CONSTRAINT TRIGGER fk_trigger AFTER INSERT ON orders FROM users DEFERRABLE INITIALLY DEFERRED FOR EACH ROW EXECUTE FUNCTION check_fk()'); + self::assertSame('CREATE CONSTRAINT TRIGGER fk_trigger AFTER INSERT ON orders FROM users DEFERRABLE INITIALLY DEFERRED FOR EACH ROW EXECUTE FUNCTION check_fk()', $builder->toSql()); } public function test_create_trigger_instead_of_on_view() : void @@ -171,7 +168,7 @@ public function test_create_trigger_instead_of_on_view() : void ->forEachRow() ->execute('insert_to_users'); - $this->assertCreateTriggerQuery($builder, 'CREATE TRIGGER view_insert INSTEAD OF INSERT ON users_view FOR EACH ROW EXECUTE FUNCTION insert_to_users()'); + self::assertSame('CREATE TRIGGER view_insert INSTEAD OF INSERT ON users_view FOR EACH ROW EXECUTE FUNCTION insert_to_users()', $builder->toSql()); } public function test_create_trigger_or_replace() : void @@ -182,7 +179,7 @@ public function test_create_trigger_or_replace() : void ->on('users') ->execute('audit_function'); - $this->assertCreateTriggerQuery($builder, 'CREATE OR REPLACE TRIGGER audit_trigger AFTER INSERT ON users EXECUTE FUNCTION audit_function()'); + self::assertSame('CREATE OR REPLACE TRIGGER audit_trigger AFTER INSERT ON users EXECUTE FUNCTION audit_function()', $builder->toSql()); } public function test_create_trigger_with_referencing() : void @@ -193,7 +190,7 @@ public function test_create_trigger_with_referencing() : void ->referencingNewTableAs('inserted_rows') ->execute('process_batch'); - $this->assertCreateTriggerQuery($builder, 'CREATE TRIGGER statement_trigger AFTER INSERT ON users REFERENCING NEW TABLE inserted_rows EXECUTE FUNCTION process_batch()'); + self::assertSame('CREATE TRIGGER statement_trigger AFTER INSERT ON users REFERENCING NEW TABLE inserted_rows EXECUTE FUNCTION process_batch()', $builder->toSql()); } public function test_create_trigger_with_schema() : void @@ -203,7 +200,7 @@ public function test_create_trigger_with_schema() : void ->on('public.users') ->execute('audit_function'); - $this->assertCreateTriggerQuery($builder, 'CREATE TRIGGER audit_trigger AFTER INSERT ON public.users EXECUTE FUNCTION audit_function()'); + self::assertSame('CREATE TRIGGER audit_trigger AFTER INSERT ON public.users EXECUTE FUNCTION audit_function()', $builder->toSql()); } public function test_drop_trigger() : void @@ -211,7 +208,7 @@ public function test_drop_trigger() : void $builder = drop()->trigger('audit_trigger') ->on('users'); - $this->assertDropTriggerQuery($builder, 'DROP TRIGGER audit_trigger ON users'); + self::assertSame('DROP TRIGGER audit_trigger ON users', $builder->toSql()); } public function test_drop_trigger_cascade() : void @@ -220,7 +217,7 @@ public function test_drop_trigger_cascade() : void ->on('users') ->cascade(); - $this->assertDropTriggerQuery($builder, 'DROP TRIGGER audit_trigger ON users CASCADE'); + self::assertSame('DROP TRIGGER audit_trigger ON users CASCADE', $builder->toSql()); } public function test_drop_trigger_if_exists() : void @@ -229,7 +226,7 @@ public function test_drop_trigger_if_exists() : void ->ifExists() ->on('users'); - $this->assertDropTriggerQuery($builder, 'DROP TRIGGER IF EXISTS audit_trigger ON users'); + self::assertSame('DROP TRIGGER IF EXISTS audit_trigger ON users', $builder->toSql()); } public function test_drop_trigger_with_schema() : void @@ -238,6 +235,6 @@ public function test_drop_trigger_with_schema() : void ->on('public.users') ->restrict(); - $this->assertDropTriggerQuery($builder, 'DROP TRIGGER audit_trigger ON public.users'); + self::assertSame('DROP TRIGGER audit_trigger ON public.users', $builder->toSql()); } } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Type/TypeAttributeTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Type/TypeAttributeTest.php index ab3e9994be..6b60a7242c 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Type/TypeAttributeTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Type/TypeAttributeTest.php @@ -4,7 +4,7 @@ namespace Flow\PostgreSql\Tests\Unit\QueryBuilder\Schema\Type; -use Flow\PostgreSql\QueryBuilder\Schema\DataType; +use Flow\PostgreSql\QueryBuilder\Schema\ColumnType; use Flow\PostgreSql\QueryBuilder\Schema\Type\TypeAttribute; use PHPUnit\Framework\TestCase; @@ -12,27 +12,27 @@ final class TypeAttributeTest extends TestCase { public function test_type_attribute_basic() : void { - $attr = TypeAttribute::of('name', DataType::text()); + $attr = TypeAttribute::of('name', ColumnType::text()); self::assertSame('name', $attr->name); - self::assertInstanceOf(DataType::class, $attr->type); + self::assertInstanceOf(ColumnType::class, $attr->type); self::assertNull($attr->collation); } public function test_type_attribute_different_types() : void { - $intAttr = TypeAttribute::of('count', DataType::integer()); - $boolAttr = TypeAttribute::of('active', DataType::boolean()); - $numericAttr = TypeAttribute::of('price', DataType::numeric(10, 2)); + $intAttr = TypeAttribute::of('count', ColumnType::integer()); + $boolAttr = TypeAttribute::of('active', ColumnType::boolean()); + $numericAttr = TypeAttribute::of('price', ColumnType::numeric(10, 2)); - self::assertInstanceOf(DataType::class, $intAttr->type); - self::assertInstanceOf(DataType::class, $boolAttr->type); - self::assertInstanceOf(DataType::class, $numericAttr->type); + self::assertInstanceOf(ColumnType::class, $intAttr->type); + self::assertInstanceOf(ColumnType::class, $boolAttr->type); + self::assertInstanceOf(ColumnType::class, $numericAttr->type); } public function test_type_attribute_immutability() : void { - $original = TypeAttribute::of('name', DataType::text()); + $original = TypeAttribute::of('name', ColumnType::text()); $modified = $original->collate('en_US'); self::assertNull($original->collation); @@ -41,11 +41,11 @@ public function test_type_attribute_immutability() : void public function test_type_attribute_with_collation() : void { - $attr = TypeAttribute::of('name', DataType::text()) + $attr = TypeAttribute::of('name', ColumnType::text()) ->collate('en_US'); self::assertSame('name', $attr->name); - self::assertInstanceOf(DataType::class, $attr->type); + self::assertInstanceOf(ColumnType::class, $attr->type); self::assertSame('en_US', $attr->collation); } } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Type/TypeBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Type/TypeBuilderTest.php index 3017e996cd..cb8e3a8ee6 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Type/TypeBuilderTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Type/TypeBuilderTest.php @@ -4,7 +4,7 @@ namespace Flow\PostgreSql\Tests\Unit\QueryBuilder\Schema\Type; -use function Flow\PostgreSql\DSL\{data_type_text, data_type_varchar}; +use function Flow\PostgreSql\DSL\{alter, column_type_text, column_type_varchar, create, drop, type_attr}; use Flow\PostgreSql\Protobuf\AST\{AlterEnumStmt, CompositeTypeStmt, CreateEnumStmt, CreateRangeStmt, DropBehavior, DropStmt, ObjectType}; use Flow\PostgreSql\QueryBuilder\Schema\Type\{AlterEnumTypeBuilder, CreateCompositeTypeBuilder, CreateEnumTypeBuilder, CreateRangeTypeBuilder, DropTypeBuilder, TypeAttribute}; @@ -54,6 +54,17 @@ public function test_alter_enum_type_add_value_before() : void self::assertFalse($ast->getNewValIsAfter()); } + public function test_alter_enum_type_add_value_if_not_exists_to_sql() : void + { + self::assertSame( + "ALTER TYPE status ADD VALUE IF NOT EXISTS 'archived'", + alter()->enumType('status') + ->addValue('archived') + ->ifNotExists() + ->toSql() + ); + } + public function test_alter_enum_type_ast_type() : void { $builder = AlterEnumTypeBuilder::create('status') @@ -89,7 +100,7 @@ public function test_alter_enum_type_rename_value() : void public function test_create_composite_type_ast_type() : void { $builder = CreateCompositeTypeBuilder::create('address') - ->attributes(TypeAttribute::of('street', data_type_text())); + ->attributes(TypeAttribute::of('street', column_type_text())); $ast = $builder->toAst(); @@ -100,9 +111,9 @@ public function test_create_composite_type_sets_attributes() : void { $builder = CreateCompositeTypeBuilder::create('address') ->attributes( - TypeAttribute::of('street', data_type_text()), - TypeAttribute::of('city', data_type_text()), - TypeAttribute::of('zip', data_type_varchar(50)) + TypeAttribute::of('street', column_type_text()), + TypeAttribute::of('city', column_type_text()), + TypeAttribute::of('zip', column_type_varchar(50)) ); $ast = $builder->toAst(); @@ -114,7 +125,7 @@ public function test_create_composite_type_sets_attributes() : void public function test_create_composite_type_sets_name() : void { $builder = CreateCompositeTypeBuilder::create('address') - ->attributes(TypeAttribute::of('street', data_type_text())); + ->attributes(TypeAttribute::of('street', column_type_text())); $ast = $builder->toAst(); $typevar = $ast->getTypevar(); @@ -123,10 +134,24 @@ public function test_create_composite_type_sets_name() : void self::assertSame('address', $typevar->getRelname()); } + public function test_create_composite_type_simple_to_sql() : void + { + self::assertSame( + 'CREATE TYPE address AS (street pg_catalog.text, city pg_catalog.text, zip pg_catalog.text)', + create()->compositeType('address') + ->attributes( + type_attr('street', column_type_text()), + type_attr('city', column_type_text()), + type_attr('zip', column_type_text()) + ) + ->toSql() + ); + } + public function test_create_composite_type_with_collation() : void { $builder = CreateCompositeTypeBuilder::create('address') - ->attributes(TypeAttribute::of('name', data_type_text())->collate('en_US')); + ->attributes(TypeAttribute::of('name', column_type_text())->collate('en_US')); $ast = $builder->toAst(); $coldeflist = $ast->getColdeflist(); @@ -141,7 +166,7 @@ public function test_create_composite_type_with_collation() : void public function test_create_composite_type_with_schema() : void { $builder = CreateCompositeTypeBuilder::create('public.address') - ->attributes(TypeAttribute::of('street', data_type_text())); + ->attributes(TypeAttribute::of('street', column_type_text())); $ast = $builder->toAst(); $typevar = $ast->getTypevar(); @@ -183,6 +208,16 @@ public function test_create_enum_type_sets_name() : void self::assertCount(1, $typeName); } + public function test_create_enum_type_simple_to_sql() : void + { + self::assertSame( + "CREATE TYPE status AS ENUM ('pending', 'active', 'closed')", + create()->enumType('status') + ->labels('pending', 'active', 'closed') + ->toSql() + ); + } + public function test_create_enum_type_with_schema() : void { $builder = CreateEnumTypeBuilder::create('public.status') @@ -230,6 +265,27 @@ public function test_create_range_type_sets_subtype() : void self::assertSame('subtype', $defElem->getDefname()); } + public function test_create_range_type_simple_to_sql() : void + { + self::assertSame( + 'CREATE TYPE floatrange AS RANGE (subtype = float8)', + create()->rangeType('floatrange') + ->subtype('float8') + ->toSql() + ); + } + + public function test_create_range_type_with_collation_to_sql() : void + { + self::assertSame( + "CREATE TYPE textrange AS RANGE (subtype = text, \"collation\" = 'en_US')", + create()->rangeType('textrange') + ->subtype('text') + ->collation('en_US') + ->toSql() + ); + } + public function test_create_range_type_with_options() : void { $builder = CreateRangeTypeBuilder::create('floatrange') @@ -284,6 +340,17 @@ public function test_drop_type_if_exists() : void self::assertTrue($ast->getMissingOk()); } + public function test_drop_type_if_exists_cascade_to_sql() : void + { + self::assertSame( + 'DROP TYPE IF EXISTS address CASCADE', + drop()->type('address') + ->ifExists() + ->cascade() + ->toSql() + ); + } + public function test_drop_type_immutability() : void { $original = DropTypeBuilder::create('address'); @@ -293,6 +360,15 @@ public function test_drop_type_immutability() : void self::assertTrue($modified->toAst()->getMissingOk()); } + public function test_drop_type_multiple_to_sql() : void + { + self::assertSame( + 'DROP TYPE address, status, floatrange', + drop()->type('address', 'status', 'floatrange') + ->toSql() + ); + } + public function test_drop_type_multiple_types() : void { $builder = DropTypeBuilder::create('address', 'status', 'priority'); @@ -311,4 +387,13 @@ public function test_drop_type_restrict() : void self::assertSame(DropBehavior::DROP_RESTRICT, $ast->getBehavior()); } + + public function test_drop_type_simple_to_sql() : void + { + self::assertSame( + 'DROP TYPE address', + drop()->type('address') + ->toSql() + ); + } } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/View/ViewBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/View/ViewBuilderTest.php index d64085c25b..ef0f4fa5f1 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/View/ViewBuilderTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/View/ViewBuilderTest.php @@ -4,7 +4,7 @@ namespace Flow\PostgreSql\Tests\Unit\QueryBuilder\Schema\View; -use function Flow\PostgreSql\DSL\{star, table}; +use function Flow\PostgreSql\DSL\{alter, col, create, drop, eq, literal, refresh_materialized_view, select, star, table}; use Flow\PostgreSql\Protobuf\AST\{AlterObjectSchemaStmt, AlterTableStmt, CreateTableAsStmt, DropStmt, ObjectType, RefreshMatViewStmt, RenameStmt, ViewStmt}; use Flow\PostgreSql\QueryBuilder\Schema\View\AlterMaterializedView\AlterMaterializedViewBuilder; use Flow\PostgreSql\QueryBuilder\Schema\View\AlterView\AlterViewBuilder; @@ -25,6 +25,38 @@ protected function setUp() : void } } + public function test_alter_materialized_view_owner_to_to_sql() : void + { + self::assertSame( + 'ALTER MATERIALIZED VIEW my_matview OWNER TO new_owner', + alter()->materializedView('my_matview')->ownerTo('new_owner')->toSql() + ); + } + + public function test_alter_materialized_view_rename_if_exists_to_sql() : void + { + self::assertSame( + 'ALTER MATERIALIZED VIEW IF EXISTS old_matview RENAME TO new_matview', + alter()->materializedView('old_matview')->ifExists()->renameTo('new_matview')->toSql() + ); + } + + public function test_alter_materialized_view_rename_to_sql() : void + { + self::assertSame( + 'ALTER MATERIALIZED VIEW old_matview RENAME TO new_matview', + alter()->materializedView('old_matview')->renameTo('new_matview')->toSql() + ); + } + + public function test_alter_materialized_view_set_schema_to_sql() : void + { + self::assertSame( + 'ALTER MATERIALIZED VIEW my_matview SET SCHEMA archive', + alter()->materializedView('my_matview')->setSchema('archive')->toSql() + ); + } + public function test_alter_materialized_view_set_tablespace_ast_type() : void { $builder = AlterMaterializedViewBuilder::create('my_matview') @@ -46,6 +78,22 @@ public function test_alter_materialized_view_set_tablespace_if_exists_sets_flag( self::assertTrue($ast->getMissingOk()); } + public function test_alter_materialized_view_set_tablespace_if_exists_to_sql() : void + { + self::assertSame( + 'ALTER MATERIALIZED VIEW IF EXISTS my_matview SET TABLESPACE fast_storage', + alter()->materializedView('my_matview')->ifExists()->setTablespace('fast_storage')->toSql() + ); + } + + public function test_alter_materialized_view_set_tablespace_to_sql() : void + { + self::assertSame( + 'ALTER MATERIALIZED VIEW my_matview SET TABLESPACE fast_storage', + alter()->materializedView('my_matview')->setTablespace('fast_storage')->toSql() + ); + } + public function test_alter_view_owner_to_ast_type() : void { $builder = AlterViewBuilder::create('my_view') @@ -57,6 +105,14 @@ public function test_alter_view_owner_to_ast_type() : void self::assertSame(ObjectType::OBJECT_VIEW, $ast->getObjtype()); } + public function test_alter_view_owner_to_to_sql() : void + { + self::assertSame( + 'ALTER VIEW my_view OWNER TO new_owner', + alter()->view('my_view')->ownerTo('new_owner')->toSql() + ); + } + public function test_alter_view_rename_ast_type() : void { $builder = AlterViewBuilder::create('old_view') @@ -78,6 +134,30 @@ public function test_alter_view_rename_if_exists_sets_flag() : void self::assertTrue($ast->getMissingOk()); } + public function test_alter_view_rename_if_exists_to_sql() : void + { + self::assertSame( + 'ALTER VIEW IF EXISTS old_view RENAME TO new_view', + alter()->view('old_view')->ifExists()->renameTo('new_view')->toSql() + ); + } + + public function test_alter_view_rename_to_sql() : void + { + self::assertSame( + 'ALTER VIEW old_view RENAME TO new_view', + alter()->view('old_view')->renameTo('new_view')->toSql() + ); + } + + public function test_alter_view_rename_with_schema_to_sql() : void + { + self::assertSame( + 'ALTER VIEW public.old_view RENAME TO new_view', + alter()->view('public.old_view')->renameTo('new_view')->toSql() + ); + } + public function test_alter_view_set_schema_ast_type() : void { $builder = AlterViewBuilder::create('my_view') @@ -89,6 +169,22 @@ public function test_alter_view_set_schema_ast_type() : void self::assertSame('archive', $ast->getNewschema()); } + public function test_alter_view_set_schema_if_exists_to_sql() : void + { + self::assertSame( + 'ALTER VIEW IF EXISTS my_view SET SCHEMA archive', + alter()->view('my_view')->ifExists()->setSchema('archive')->toSql() + ); + } + + public function test_alter_view_set_schema_to_sql() : void + { + self::assertSame( + 'ALTER VIEW my_view SET SCHEMA archive', + alter()->view('my_view')->setSchema('archive')->toSql() + ); + } + public function test_create_materialized_view_ast_type() : void { $builder = CreateMaterializedViewBuilder::create('my_matview') @@ -111,6 +207,17 @@ public function test_create_materialized_view_if_not_exists_sets_flag() : void self::assertTrue($ast->getIfNotExists()); } + public function test_create_materialized_view_if_not_exists_to_sql() : void + { + self::assertSame( + 'CREATE MATERIALIZED VIEW IF NOT EXISTS user_stats AS SELECT * FROM users', + create()->materializedView('user_stats') + ->ifNotExists() + ->as(select(star())->from(table('users'))) + ->toSql() + ); + } + public function test_create_materialized_view_parses_schema_from_name() : void { $builder = CreateMaterializedViewBuilder::create('analytics.my_matview') @@ -126,6 +233,27 @@ public function test_create_materialized_view_parses_schema_from_name() : void self::assertSame('my_matview', $rel->getRelname()); } + public function test_create_materialized_view_to_sql() : void + { + self::assertSame( + 'CREATE MATERIALIZED VIEW user_stats AS SELECT * FROM users', + create()->materializedView('user_stats') + ->as(select(star())->from(table('users'))) + ->toSql() + ); + } + + public function test_create_materialized_view_using_access_method_to_sql() : void + { + self::assertSame( + 'CREATE MATERIALIZED VIEW user_stats USING heap AS SELECT * FROM users', + create()->materializedView('user_stats') + ->using('heap') + ->as(select(star())->from(table('users'))) + ->toSql() + ); + } + public function test_create_materialized_view_with_columns() : void { $builder = CreateMaterializedViewBuilder::create('my_matview') @@ -139,6 +267,17 @@ public function test_create_materialized_view_with_columns() : void self::assertCount(2, $into->getColNames()); } + public function test_create_materialized_view_with_data_to_sql() : void + { + self::assertSame( + 'CREATE MATERIALIZED VIEW user_stats AS SELECT * FROM users', + create()->materializedView('user_stats') + ->as(select()->select(star())->from(table('users'))) + ->withData() + ->toSql() + ); + } + public function test_create_materialized_view_with_no_data_sets_flag() : void { $builder = CreateMaterializedViewBuilder::create('my_matview') @@ -152,6 +291,27 @@ public function test_create_materialized_view_with_no_data_sets_flag() : void self::assertTrue($into->getSkipData()); } + public function test_create_materialized_view_with_no_data_to_sql() : void + { + self::assertSame( + 'CREATE MATERIALIZED VIEW user_stats AS SELECT * FROM users WITH NO DATA', + create()->materializedView('user_stats') + ->as(select()->select(star())->from(table('users'))) + ->withNoData() + ->toSql() + ); + } + + public function test_create_materialized_view_with_schema_to_sql() : void + { + self::assertSame( + 'CREATE MATERIALIZED VIEW analytics.user_stats AS SELECT * FROM users', + create()->materializedView('analytics.user_stats') + ->as(select(star())->from(table('users'))) + ->toSql() + ); + } + public function test_create_materialized_view_with_tablespace() : void { $builder = CreateMaterializedViewBuilder::create('my_matview') @@ -165,6 +325,40 @@ public function test_create_materialized_view_with_tablespace() : void self::assertSame('fast_storage', $into->getTableSpaceName()); } + public function test_create_or_replace_view_to_sql() : void + { + self::assertSame( + 'CREATE OR REPLACE VIEW active_users AS SELECT * FROM users', + create()->view('active_users') + ->orReplace() + ->as(select(star())->from(table('users'))) + ->toSql() + ); + } + + public function test_create_recursive_view_outputs_as_regular_view_to_sql() : void + { + self::assertSame( + 'CREATE VIEW subordinates (id, name, manager_id) AS SELECT id, name, manager_id FROM employees', + create()->view('subordinates') + ->recursive() + ->columns('id', 'name', 'manager_id') + ->as(select(col('id'), col('name'), col('manager_id'))->from(table('employees'))) + ->toSql() + ); + } + + public function test_create_temporary_view_to_sql() : void + { + self::assertSame( + 'CREATE TEMPORARY VIEW temp_users AS SELECT * FROM users', + create()->view('temp_users') + ->temporary() + ->as(select(star())->from(table('users'))) + ->toSql() + ); + } + public function test_create_view_ast_type() : void { $builder = CreateViewBuilder::create('my_view') @@ -211,6 +405,38 @@ public function test_create_view_parses_schema_from_name() : void self::assertSame('my_view', $view->getRelname()); } + public function test_create_view_simple_to_sql() : void + { + self::assertSame( + 'CREATE VIEW active_users AS SELECT * FROM users', + create()->view('active_users') + ->as(select(star())->from(table('users'))) + ->toSql() + ); + } + + public function test_create_view_with_cascaded_check_option_to_sql() : void + { + self::assertSame( + 'CREATE VIEW active_users AS SELECT * FROM users WITH CHECK OPTION', + create()->view('active_users') + ->as(select()->select(star())->from(table('users'))) + ->withCascadedCheckOption() + ->toSql() + ); + } + + public function test_create_view_with_check_option_to_sql() : void + { + self::assertSame( + 'CREATE VIEW active_users AS SELECT * FROM users WHERE active = true WITH CHECK OPTION', + create()->view('active_users') + ->as(select(star())->from(table('users'))->where(eq(col('active'), literal(true)))) + ->withCheckOption() + ->toSql() + ); + } + public function test_create_view_with_columns() : void { $builder = CreateViewBuilder::create('my_view') @@ -222,6 +448,27 @@ public function test_create_view_with_columns() : void self::assertCount(3, $ast->getAliases()); } + public function test_create_view_with_local_check_option_to_sql() : void + { + self::assertSame( + 'CREATE VIEW active_users AS SELECT * FROM users WITH LOCAL CHECK OPTION', + create()->view('active_users') + ->as(select()->select(star())->from(table('users'))) + ->withLocalCheckOption() + ->toSql() + ); + } + + public function test_create_view_with_schema_to_sql() : void + { + self::assertSame( + 'CREATE VIEW public.active_users AS SELECT * FROM users', + create()->view('public.active_users') + ->as(select(star())->from(table('users'))) + ->toSql() + ); + } + public function test_drop_materialized_view_ast_type() : void { $builder = DropMaterializedViewBuilder::create('my_matview'); @@ -232,6 +479,22 @@ public function test_drop_materialized_view_ast_type() : void self::assertSame(ObjectType::OBJECT_MATVIEW, $ast->getRemoveType()); } + public function test_drop_materialized_view_if_exists_cascade_to_sql() : void + { + self::assertSame( + 'DROP MATERIALIZED VIEW IF EXISTS user_stats CASCADE', + drop()->materializedView('user_stats')->ifExists()->cascade()->toSql() + ); + } + + public function test_drop_materialized_view_simple_to_sql() : void + { + self::assertSame( + 'DROP MATERIALIZED VIEW user_stats', + drop()->materializedView('user_stats')->toSql() + ); + } + public function test_drop_view_ast_type() : void { $builder = DropViewBuilder::create('my_view'); @@ -242,6 +505,22 @@ public function test_drop_view_ast_type() : void self::assertSame(ObjectType::OBJECT_VIEW, $ast->getRemoveType()); } + public function test_drop_view_cascade_to_sql() : void + { + self::assertSame( + 'DROP VIEW active_users CASCADE', + drop()->view('active_users')->cascade()->toSql() + ); + } + + public function test_drop_view_if_exists_cascade_to_sql() : void + { + self::assertSame( + 'DROP VIEW IF EXISTS active_users CASCADE', + drop()->view('active_users')->ifExists()->cascade()->toSql() + ); + } + public function test_drop_view_if_exists_sets_flag() : void { $builder = DropViewBuilder::create('my_view') @@ -252,6 +531,22 @@ public function test_drop_view_if_exists_sets_flag() : void self::assertTrue($ast->getMissingOk()); } + public function test_drop_view_if_exists_to_sql() : void + { + self::assertSame( + 'DROP VIEW IF EXISTS active_users', + drop()->view('active_users')->ifExists()->toSql() + ); + } + + public function test_drop_view_multiple_to_sql() : void + { + self::assertSame( + 'DROP VIEW view1, view2, view3', + drop()->view('view1', 'view2', 'view3')->toSql() + ); + } + public function test_drop_view_multiple_views() : void { $builder = DropViewBuilder::create('view1', 'view2', 'view3'); @@ -261,6 +556,14 @@ public function test_drop_view_multiple_views() : void self::assertCount(3, $ast->getObjects()); } + public function test_drop_view_simple_to_sql() : void + { + self::assertSame( + 'DROP VIEW active_users', + drop()->view('active_users')->toSql() + ); + } + public function test_refresh_materialized_view_ast_type() : void { $builder = RefreshMaterializedViewBuilder::create('my_matview'); @@ -280,6 +583,22 @@ public function test_refresh_materialized_view_concurrently_sets_flag() : void self::assertTrue($ast->getConcurrent()); } + public function test_refresh_materialized_view_concurrently_to_sql() : void + { + self::assertSame( + 'REFRESH MATERIALIZED VIEW CONCURRENTLY user_stats', + refresh_materialized_view('user_stats')->concurrently()->toSql() + ); + } + + public function test_refresh_materialized_view_concurrently_with_data_to_sql() : void + { + self::assertSame( + 'REFRESH MATERIALIZED VIEW CONCURRENTLY user_stats', + refresh_materialized_view('user_stats')->concurrently()->withData()->toSql() + ); + } + public function test_refresh_materialized_view_parses_schema_from_name() : void { $builder = RefreshMaterializedViewBuilder::create('analytics.my_matview'); @@ -292,6 +611,22 @@ public function test_refresh_materialized_view_parses_schema_from_name() : void self::assertSame('my_matview', $relation->getRelname()); } + public function test_refresh_materialized_view_simple_to_sql() : void + { + self::assertSame( + 'REFRESH MATERIALIZED VIEW user_stats', + refresh_materialized_view('user_stats')->toSql() + ); + } + + public function test_refresh_materialized_view_with_data_to_sql() : void + { + self::assertSame( + 'REFRESH MATERIALIZED VIEW user_stats', + refresh_materialized_view('user_stats')->withData()->toSql() + ); + } + public function test_refresh_materialized_view_with_no_data_sets_flag() : void { $builder = RefreshMaterializedViewBuilder::create('my_matview') @@ -301,4 +636,20 @@ public function test_refresh_materialized_view_with_no_data_sets_flag() : void self::assertTrue($ast->getSkipData()); } + + public function test_refresh_materialized_view_with_no_data_to_sql() : void + { + self::assertSame( + 'REFRESH MATERIALIZED VIEW user_stats WITH NO DATA', + refresh_materialized_view('user_stats')->withNoData()->toSql() + ); + } + + public function test_refresh_materialized_view_with_schema_to_sql() : void + { + self::assertSame( + 'REFRESH MATERIALIZED VIEW analytics.user_stats', + refresh_materialized_view('analytics.user_stats')->toSql() + ); + } } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Select/SelectBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Select/SelectBuilderTest.php index 4c18c5f972..72f153a1b5 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Select/SelectBuilderTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Select/SelectBuilderTest.php @@ -4,8 +4,68 @@ namespace Flow\PostgreSql\Tests\Unit\QueryBuilder\Select; +use function Flow\PostgreSql\DSL\{ + agg_avg, + agg_count, + agg_max, + agg_min, + agg_sum, + all_, + and_, + any_, + array_expr, + asc, + between, + binary_expr, + case_when, + cast, + coalesce, + col, + column_type_integer, + column_type_text, + cte, + current_date, + current_time, + current_timestamp, + derived, + desc, + distinct_from, + eq, + exists, + func, + ge, + greatest, + gt, + in_, + is_null, + is_true, + lateral, + le, + least, + like, + literal, + lt, + ne, + not_, + nullif, + or_, + order_by, + param, + row_expr, + select, + similar_to, + star, + sub_select, + table, + table_func, + when, + window_def, + window_func, + with +}; + use Flow\PostgreSql\Protobuf\AST\SelectStmt; -use Flow\PostgreSql\QueryBuilder\Clause\{OrderBy, SortDirection}; +use Flow\PostgreSql\QueryBuilder\Clause\{CTEMaterialization, NullsPosition, OrderBy, SortDirection}; use Flow\PostgreSql\QueryBuilder\Condition\{Comparison, ComparisonOperator}; use Flow\PostgreSql\QueryBuilder\Expression\{AggregateCall, Column, Literal, Star}; use Flow\PostgreSql\QueryBuilder\Select\SelectBuilder; @@ -185,6 +245,16 @@ public function test_select_distinct_on() : void self::assertCount(1, $distinctClause); } + public function test_select_except_all_to_sql() : void + { + self::assertSame( + 'SELECT id FROM all_users EXCEPT ALL SELECT id FROM banned_users', + select()->select(col('id'))->from(table('all_users')) + ->exceptAll(select()->select(col('id'))->from(table('banned_users'))) + ->toSql() + ); + } + public function test_select_from_multiple_tables() : void { $query = SelectBuilder::create() @@ -198,6 +268,16 @@ public function test_select_from_multiple_tables() : void self::assertCount(2, $fromClause); } + public function test_select_intersect_all_to_sql() : void + { + self::assertSame( + 'SELECT id FROM users INTERSECT ALL SELECT id FROM admins', + select()->select(col('id'))->from(table('users')) + ->intersectAll(select()->select(col('id'))->from(table('admins'))) + ->toSql() + ); + } + public function test_select_only_limit() : void { $query = SelectBuilder::create() @@ -241,6 +321,146 @@ public function test_select_star() : void self::assertCount(1, $targetList); } + public function test_select_with_aggregates_to_sql() : void + { + self::assertSame( + 'SELECT category, count(*), sum(amount), avg(price), min(created_at), max(updated_at) FROM orders GROUP BY category', + select() + ->select( + col('category'), + agg_count(), + agg_sum(col('amount')), + agg_avg(col('price')), + agg_min(col('created_at')), + agg_max(col('updated_at')) + ) + ->from(table('orders')) + ->groupBy(col('category')) + ->toSql() + ); + } + + public function test_select_with_aliased_columns_to_sql() : void + { + self::assertSame( + 'SELECT first_name AS fname, last_name AS lname FROM users', + select() + ->select(col('first_name')->as('fname'), col('last_name')->as('lname')) + ->from(table('users')) + ->toSql() + ); + } + + public function test_select_with_all_to_sql() : void + { + self::assertSame( + 'SELECT * FROM products WHERE price > ALL (SELECT price FROM budget_products)', + select() + ->select(star()) + ->from(table('products')) + ->where(all_(col('price'), ComparisonOperator::GT, select()->select(col('price'))->from(table('budget_products')))) + ->toSql() + ); + } + + public function test_select_with_any_to_sql() : void + { + self::assertSame( + 'SELECT * FROM products WHERE price > ANY (SELECT price FROM discounted_products)', + select() + ->select(star()) + ->from(table('products')) + ->where(any_(col('price'), ComparisonOperator::GT, select()->select(col('price'))->from(table('discounted_products')))) + ->toSql() + ); + } + + public function test_select_with_array_constructor_to_sql() : void + { + self::assertSame( + 'SELECT ARRAY[1, 2, 3] AS numbers FROM users', + select() + ->select(array_expr([literal(1), literal(2), literal(3)])->as('numbers')) + ->from(table('users')) + ->toSql() + ); + } + + public function test_select_with_array_expression_to_sql() : void + { + self::assertSame( + 'SELECT * FROM users WHERE id IN (1, 2, 3)', + select() + ->select(star()) + ->from(table('users')) + ->where(in_(col('id'), [literal(1), literal(2), literal(3)])) + ->toSql() + ); + } + + public function test_select_with_between_condition_to_sql() : void + { + self::assertSame( + 'SELECT * FROM products WHERE price BETWEEN 10 AND 100', + select() + ->select(star()) + ->from(table('products')) + ->where(between(col('price'), literal(10), literal(100))) + ->toSql() + ); + } + + public function test_select_with_case_expression_to_sql() : void + { + self::assertSame( + "SELECT name, CASE WHEN price > 100 THEN 'expensive' WHEN price > 50 THEN 'moderate' ELSE 'cheap' END AS price_category FROM products", + select() + ->select( + col('name'), + case_when([ + when(binary_expr(col('price'), '>', literal(100)), literal('expensive')), + when(binary_expr(col('price'), '>', literal(50)), literal('moderate')), + ], literal('cheap'))->as('price_category') + ) + ->from(table('products')) + ->toSql() + ); + } + + public function test_select_with_coalesce_to_sql() : void + { + self::assertSame( + "SELECT id, COALESCE(nickname, name, 'Anonymous') AS display_name FROM users", + select() + ->select( + col('id'), + coalesce(col('nickname'), col('name'), literal('Anonymous'))->as('display_name') + ) + ->from(table('users')) + ->toSql() + ); + } + + public function test_select_with_complex_and_or_conditions_to_sql() : void + { + self::assertSame( + "SELECT * FROM users WHERE status = 'active' AND (age >= 18 OR guardian_approved = true)", + select() + ->select(star()) + ->from(table('users')) + ->where( + and_( + eq(col('status'), literal('active')), + or_( + ge(col('age'), literal(18)), + eq(col('guardian_approved'), literal(true)) + ) + ) + ) + ->toSql() + ); + } + public function test_select_with_cross_join() : void { $query = SelectBuilder::create() @@ -254,6 +474,93 @@ public function test_select_with_cross_join() : void self::assertNotNull($fromClause); } + public function test_select_with_cte_materialized_to_sql() : void + { + self::assertSame( + 'WITH active_users AS MATERIALIZED (SELECT id, name FROM users WHERE active = true) SELECT * FROM active_users', + with(cte('active_users', select()->select(col('id'), col('name'))->from(table('users'))->where(eq(col('active'), literal(true))), [], CTEMaterialization::MATERIALIZED)) + ->select(star()) + ->from(table('active_users')) + ->toSql() + ); + } + + public function test_select_with_cte_not_materialized_to_sql() : void + { + self::assertSame( + 'WITH active_users AS NOT MATERIALIZED (SELECT id, name FROM users WHERE active = true) SELECT * FROM active_users', + with(cte('active_users', select()->select(col('id'), col('name'))->from(table('users'))->where(eq(col('active'), literal(true))), [], CTEMaterialization::NOT_MATERIALIZED)) + ->select(star()) + ->from(table('active_users')) + ->toSql() + ); + } + + public function test_select_with_cte_to_sql() : void + { + self::assertSame( + 'WITH active_users AS (SELECT id, name FROM users WHERE active = true) SELECT * FROM active_users', + with( + cte('active_users', select()->select(col('id'), col('name'))->from(table('users'))->where(eq(col('active'), literal(true)))) + ) + ->select(star()) + ->from(table('active_users')) + ->toSql() + ); + } + + public function test_select_with_derived_table_join_to_sql() : void + { + self::assertSame( + 'SELECT users.name, order_stats.order_count FROM users JOIN (SELECT user_id, count(*) AS order_count FROM orders GROUP BY user_id) order_stats ON users.id = order_stats.user_id', + select() + ->select(col('users.name'), col('order_stats.order_count')) + ->from(table('users')) + ->join( + derived( + select()->select(col('user_id'), agg_count()->as('order_count'))->from(table('orders'))->groupBy(col('user_id')), + 'order_stats' + ), + eq(col('users.id'), col('order_stats.user_id')) + ) + ->toSql() + ); + } + + public function test_select_with_derived_table_to_sql() : void + { + self::assertSame( + 'SELECT u.name, o.total FROM users u LEFT JOIN (SELECT user_id, sum(amount) AS total FROM orders GROUP BY user_id) o ON u.id = o.user_id', + select() + ->select(col('u.name'), col('o.total')) + ->from(table('users')->as('u')) + ->leftJoin( + derived( + select()->select(col('user_id'), agg_sum(col('amount'))->as('total'))->from(table('orders'))->groupBy(col('user_id')), + 'o' + ), + eq(col('u.id'), col('o.user_id')) + ) + ->toSql() + ); + } + + public function test_select_with_distinct_count_to_sql() : void + { + self::assertSame( + 'SELECT count(DISTINCT user_id) AS unique_users FROM orders', + select()->select(agg_count(col('user_id'), true)->as('unique_users'))->from(table('orders'))->toSql() + ); + } + + public function test_select_with_distinct_to_sql() : void + { + self::assertSame( + 'SELECT DISTINCT city FROM users', + select()->selectDistinct(col('city'))->from(table('users'))->toSql() + ); + } + public function test_select_with_except() : void { $query1 = SelectBuilder::create() @@ -272,6 +579,20 @@ public function test_select_with_except() : void self::assertNotNull($ast->getRarg()); } + public function test_select_with_exists_to_sql() : void + { + self::assertSame( + 'SELECT * FROM users WHERE EXISTS (SELECT 1 FROM orders WHERE orders.user_id = users.id)', + select() + ->select(star()) + ->from(table('users')) + ->where(exists( + select()->select(literal(1))->from(table('orders'))->where(eq(col('orders.user_id'), col('users.id'))) + )) + ->toSql() + ); + } + public function test_select_with_for_key_share() : void { $query = SelectBuilder::create() @@ -344,6 +665,32 @@ public function test_select_with_full_join() : void self::assertNotNull($fromClause); } + public function test_select_with_function_call_to_sql() : void + { + self::assertSame( + 'SELECT name, upper(name) AS upper_name, length(name) AS name_length FROM users', + select() + ->select( + col('name'), + func('upper', [col('name')])->as('upper_name'), + func('length', [col('name')])->as('name_length') + ) + ->from(table('users')) + ->toSql() + ); + } + + public function test_select_with_greatest_to_sql() : void + { + self::assertSame( + 'SELECT id, GREATEST(a, b, c) AS max_value FROM numbers', + select() + ->select(col('id'), greatest(col('a'), col('b'), col('c'))->as('max_value')) + ->from(table('numbers')) + ->toSql() + ); + } + public function test_select_with_group_by_having() : void { $query = SelectBuilder::create() @@ -361,6 +708,18 @@ public function test_select_with_group_by_having() : void self::assertNotNull($havingClause); } + public function test_select_with_in_condition_to_sql() : void + { + self::assertSame( + "SELECT * FROM users WHERE status IN ('active', 'pending', 'verified')", + select() + ->select(star()) + ->from(table('users')) + ->where(in_(col('status'), [literal('active'), literal('pending'), literal('verified')])) + ->toSql() + ); + } + public function test_select_with_inner_join() : void { $query = SelectBuilder::create() @@ -395,6 +754,30 @@ public function test_select_with_intersect() : void self::assertNotNull($ast->getRarg()); } + public function test_select_with_is_distinct_from_to_sql() : void + { + self::assertSame( + 'SELECT * FROM users WHERE status IS DISTINCT FROM NULL', + select()->select(star())->from(table('users'))->where(distinct_from(col('status'), literal(null)))->toSql() + ); + } + + public function test_select_with_is_not_distinct_from_to_sql() : void + { + self::assertSame( + "SELECT * FROM users WHERE status IS NOT DISTINCT FROM 'active'", + select()->select(star())->from(table('users'))->where(distinct_from(col('status'), literal('active'), true))->toSql() + ); + } + + public function test_select_with_is_null_condition_to_sql() : void + { + self::assertSame( + 'SELECT * FROM users WHERE deleted_at IS NULL', + select()->select(star())->from(table('users'))->where(is_null(col('deleted_at')))->toSql() + ); + } + public function test_select_with_join() : void { $query = SelectBuilder::create() @@ -412,6 +795,94 @@ public function test_select_with_join() : void self::assertCount(1, $fromClause); } + public function test_select_with_lateral_join_to_sql() : void + { + self::assertSame( + 'SELECT u.name, recent.id FROM users u LEFT JOIN LATERAL (SELECT * FROM orders WHERE orders.user_id = u.id ORDER BY created_at DESC LIMIT 3) recent ON true', + select() + ->select(col('u.name'), col('recent.id')) + ->from(table('users')->as('u')) + ->leftJoin( + lateral(derived( + select()->select(star())->from(table('orders'))->where(eq(col('orders.user_id'), col('u.id')))->orderBy(desc(col('created_at')))->limit(3), + 'recent' + )), + is_true(literal(true)) + ) + ->toSql() + ); + } + + public function test_select_with_lateral_subquery_to_sql() : void + { + self::assertSame( + 'SELECT users.name, recent_orders.order_id FROM users CROSS JOIN LATERAL (SELECT order_id FROM orders WHERE orders.user_id = users.id ORDER BY created_at DESC LIMIT 5) recent_orders', + select() + ->select(col('users.name'), col('recent_orders.order_id')) + ->from(table('users')) + ->crossJoin(lateral(derived( + select()->select(col('order_id'))->from(table('orders'))->where(eq(col('orders.user_id'), col('users.id')))->orderBy(desc(col('created_at')))->limit(5), + 'recent_orders' + ))) + ->toSql() + ); + } + + public function test_select_with_least_to_sql() : void + { + self::assertSame( + 'SELECT id, LEAST(a, b, c) AS min_value FROM numbers', + select() + ->select(col('id'), least(col('a'), col('b'), col('c'))->as('min_value')) + ->from(table('numbers')) + ->toSql() + ); + } + + public function test_select_with_left_join_to_sql() : void + { + self::assertSame( + 'SELECT u.name, o.total FROM users u LEFT JOIN orders o ON u.id = o.user_id', + select() + ->select(col('u.name'), col('o.total')) + ->from(table('users')->as('u')) + ->leftJoin(table('orders')->as('o'), eq(col('u.id'), col('o.user_id'))) + ->toSql() + ); + } + + public function test_select_with_like_condition_to_sql() : void + { + self::assertSame( + "SELECT * FROM users WHERE email LIKE '%@example.com'", + select()->select(star())->from(table('users'))->where(like(col('email'), literal('%@example.com')))->toSql() + ); + } + + public function test_select_with_limit_offset_to_sql() : void + { + self::assertSame( + 'SELECT * FROM users ORDER BY id ASC LIMIT 10 OFFSET 20', + select()->select(star())->from(table('users'))->orderBy(asc(col('id')))->limit(10)->offset(20)->toSql() + ); + } + + public function test_select_with_multiple_conditions_to_sql() : void + { + self::assertSame( + "SELECT * FROM users WHERE active = true AND age >= 18 AND status <> 'banned'", + select() + ->select(star()) + ->from(table('users')) + ->where(and_( + eq(col('active'), literal(true)), + ge(col('age'), literal(18)), + ne(col('status'), literal('banned')) + )) + ->toSql() + ); + } + public function test_select_with_multiple_joins() : void { $query = SelectBuilder::create() @@ -432,6 +903,33 @@ public function test_select_with_multiple_joins() : void self::assertNotNull($fromClause); } + public function test_select_with_not_condition_to_sql() : void + { + self::assertSame( + "SELECT * FROM users WHERE NOT status = 'banned'", + select()->select(star())->from(table('users'))->where(not_(eq(col('status'), literal('banned'))))->toSql() + ); + } + + public function test_select_with_nullif_to_sql() : void + { + self::assertSame( + 'SELECT id, NULLIF(value, 0) AS safe_value FROM data', + select() + ->select(col('id'), nullif(col('value'), literal(0))->as('safe_value')) + ->from(table('data')) + ->toSql() + ); + } + + public function test_select_with_order_by_asc_desc_to_sql() : void + { + self::assertSame( + 'SELECT * FROM users ORDER BY last_name ASC, first_name DESC', + select()->select(star())->from(table('users'))->orderBy(asc(col('last_name')), desc(col('first_name')))->toSql() + ); + } + public function test_select_with_order_by_multiple_columns() : void { $query = SelectBuilder::create() @@ -449,6 +947,21 @@ public function test_select_with_order_by_multiple_columns() : void self::assertCount(2, $sortClause); } + public function test_select_with_order_by_nulls_first_last_to_sql() : void + { + self::assertSame( + 'SELECT * FROM products ORDER BY price ASC NULLS FIRST, name DESC NULLS LAST', + select() + ->select(star()) + ->from(table('products')) + ->orderBy( + order_by(col('price'), SortDirection::ASC, NullsPosition::FIRST), + order_by(col('name'), SortDirection::DESC, NullsPosition::LAST) + ) + ->toSql() + ); + } + public function test_select_with_order_limit_offset() : void { $query = SelectBuilder::create() @@ -469,6 +982,132 @@ public function test_select_with_order_limit_offset() : void self::assertNotNull($limitOffset); } + public function test_select_with_parameter_to_sql() : void + { + self::assertSame( + 'SELECT * FROM users WHERE id = $1', + select()->select(star())->from(table('users'))->where(eq(col('id'), param(1)))->toSql() + ); + } + + public function test_select_with_raw_expression_in_select_to_sql() : void + { + self::assertSame( + 'SELECT id, 1 + 1 AS two FROM users', + select()->select(col('id'), binary_expr(literal(1), '+', literal(1))->as('two'))->from(table('users'))->toSql() + ); + } + + public function test_select_with_raw_expression_to_sql() : void + { + self::assertSame( + 'SELECT *, 1 + 1 AS calculated FROM users', + select() + ->select(star(), binary_expr(literal(1), '+', literal(1))->as('calculated')) + ->from(table('users')) + ->toSql() + ); + } + + public function test_select_with_recursive_cte_window_functions_and_case_expression_to_sql() : void + { + $orgTreeAnchor = select() + ->select( + col('id'), + col('name'), + col('manager_id'), + literal(0)->as('level'), + cast(col('name'), column_type_text())->as('path') + ) + ->from(table('employees')) + ->where(is_null(col('manager_id'))); + + $orgTreeRecursive = select() + ->select( + col('e.id'), + col('e.name'), + col('e.manager_id'), + binary_expr(col('org_tree.level'), '+', literal(1)), + binary_expr( + binary_expr(col('org_tree.path'), '||', literal(' -> ')), + '||', + col('e.name') + ) + ) + ->from(table('employees')->as('e')) + ->join(table('org_tree'), eq(col('e.manager_id'), col('org_tree.id'))); + + $orgTreeQuery = $orgTreeAnchor->unionAll($orgTreeRecursive); + + $deptStats = select() + ->select( + col('department_id'), + agg_avg(col('salary')), + agg_max(col('salary')), + agg_count() + ) + ->from(table('employees')) + ->groupBy(col('department_id')); + + $rankedEmployees = select() + ->select( + col('e.id'), + col('e.name'), + col('e.department_id'), + col('e.salary'), + window_func('row_number', [], [col('e.department_id')], [desc(col('e.salary'))]), + func('round', [ + binary_expr( + binary_expr(col('e.salary'), '/', col('ds.max_salary')), + '*', + literal(100) + ), + literal(2), + ]) + ) + ->from(table('employees')->as('e')) + ->join(table('dept_stats')->as('ds'), eq(col('e.department_id'), col('ds.department_id'))); + + $query = with( + cte('org_tree', $orgTreeQuery, ['id', 'name', 'manager_id', 'level', 'path']), + cte('dept_stats', $deptStats, ['department_id', 'avg_salary', 'max_salary', 'employee_count']), + cte('ranked_employees', $rankedEmployees, ['id', 'name', 'department_id', 'salary', 'salary_rank', 'pct_of_max']) + ) + ->recursive() + ->select( + col('org_tree.name')->as('employee'), + col('org_tree.level'), + col('org_tree.path')->as('reporting_chain'), + col('d.name')->as('department'), + col('re.salary'), + col('re.salary_rank'), + col('re.pct_of_max'), + col('ds.avg_salary')->as('dept_avg'), + case_when([ + when(binary_expr(col('re.salary'), '>', col('ds.avg_salary')), literal('Above Average')), + ], literal('At/Below Average'))->as('salary_status') + ) + ->from(table('org_tree')) + ->join(table('ranked_employees')->as('re'), eq(col('org_tree.id'), col('re.id'))) + ->join(table('dept_stats')->as('ds'), eq(col('re.department_id'), col('ds.department_id'))) + ->join(table('departments')->as('d'), eq(col('re.department_id'), col('d.id'))) + ->where(and_( + le(col('org_tree.level'), literal(3)), + le(col('re.salary_rank'), literal(5)) + )) + ->orderBy( + asc(col('org_tree.level')), + asc(col('d.name')), + desc(col('re.salary')) + ); + + $expectedSql = <<<'SQL' + WITH RECURSIVE org_tree(id, name, manager_id, level, path) AS (SELECT id, name, manager_id, 0 AS level, name::pg_catalog.text AS path FROM employees WHERE manager_id IS NULL UNION ALL SELECT e.id, e.name, e.manager_id, org_tree.level + 1, (org_tree.path || ' -> ') || e.name FROM employees e JOIN org_tree ON e.manager_id = org_tree.id), dept_stats(department_id, avg_salary, max_salary, employee_count) AS (SELECT department_id, avg(salary), max(salary), count(*) FROM employees GROUP BY department_id), ranked_employees(id, name, department_id, salary, salary_rank, pct_of_max) AS (SELECT e.id, e.name, e.department_id, e.salary, row_number() OVER (PARTITION BY e.department_id ORDER BY e.salary DESC), round((e.salary / ds.max_salary) * 100, 2) FROM employees e JOIN dept_stats ds ON e.department_id = ds.department_id) SELECT org_tree.name AS employee, org_tree.level, org_tree.path AS reporting_chain, d.name AS department, re.salary, re.salary_rank, re.pct_of_max, ds.avg_salary AS dept_avg, CASE WHEN re.salary > ds.avg_salary THEN 'Above Average' ELSE 'At/Below Average' END AS salary_status FROM org_tree JOIN ranked_employees re ON org_tree.id = re.id JOIN dept_stats ds ON re.department_id = ds.department_id JOIN departments d ON re.department_id = d.id WHERE org_tree.level <= 3 AND re.salary_rank <= 5 ORDER BY org_tree.level ASC, d.name ASC, re.salary DESC + SQL; + + self::assertSame($expectedSql, $query->toSql()); + } + public function test_select_with_right_join() : void { $query = SelectBuilder::create() @@ -485,6 +1124,37 @@ public function test_select_with_right_join() : void self::assertNotNull($fromClause); } + public function test_select_with_row_expression_to_sql() : void + { + self::assertSame( + "SELECT * FROM users WHERE (first_name, last_name) = ('John', 'Doe')", + select() + ->select(star()) + ->from(table('users')) + ->where(eq( + row_expr([col('first_name'), col('last_name')]), + row_expr([literal('John'), literal('Doe')]) + )) + ->toSql() + ); + } + + public function test_select_with_scalar_subquery_to_sql() : void + { + self::assertSame( + 'SELECT name, (SELECT count(*) FROM orders WHERE orders.user_id = users.id) AS order_count FROM users', + select() + ->select( + col('name'), + sub_select( + select()->select(agg_count())->from(table('orders'))->where(eq(col('orders.user_id'), col('users.id'))) + )->as('order_count') + ) + ->from(table('users')) + ->toSql() + ); + } + public function test_select_with_schema_qualified_table() : void { $query = SelectBuilder::create() @@ -502,6 +1172,33 @@ public function test_select_with_schema_qualified_table() : void self::assertSame('public', $rangeVar->getSchemaname()); } + public function test_select_with_similar_to_to_sql() : void + { + self::assertSame( + "SELECT * FROM users WHERE name SIMILAR TO '%John%'", + select()->select(star())->from(table('users'))->where(similar_to(col('name'), literal('%John%')))->toSql() + ); + } + + public function test_select_with_table_function_to_sql() : void + { + self::assertSame( + 'SELECT value FROM generate_series(1, 10) value', + select()->select(col('value'))->from(table_func(func('generate_series', [literal(1), literal(10)]))->as('value'))->toSql() + ); + } + + public function test_select_with_type_cast_to_sql() : void + { + self::assertSame( + 'SELECT id, price::int AS price_int FROM products', + select() + ->select(col('id'), cast(col('price'), column_type_integer())->as('price_int')) + ->from(table('products')) + ->toSql() + ); + } + public function test_select_with_union() : void { $query1 = SelectBuilder::create() @@ -550,6 +1247,39 @@ public function test_select_with_where() : void self::assertNotNull($whereClause); } + public function test_select_with_where_comparison_operators_to_sql() : void + { + self::assertSame( + 'SELECT * FROM products WHERE price > 10 AND price < 100 AND quantity >= 1 AND weight <= 50', + select() + ->select(star()) + ->from(table('products')) + ->where(and_( + gt(col('price'), literal(10)), + lt(col('price'), literal(100)), + ge(col('quantity'), literal(1)), + le(col('weight'), literal(50)) + )) + ->toSql() + ); + } + + public function test_select_with_window_definition_to_sql() : void + { + self::assertSame( + 'SELECT department, salary, row_number() OVER (ORDER BY salary DESC) AS rank FROM employees WINDOW w AS (PARTITION BY department ORDER BY salary DESC)', + select() + ->select( + col('department'), + col('salary'), + window_func('row_number', [], [], [order_by(col('salary'), SortDirection::DESC)])->as('rank') + ) + ->from(table('employees')) + ->window(window_def('w', [col('department')], [order_by(col('salary'), SortDirection::DESC)])) + ->toSql() + ); + } + public function test_simple_select() : void { $query = SelectBuilder::create() @@ -567,4 +1297,55 @@ public function test_simple_select() : void self::assertNotNull($fromClause); self::assertCount(1, $fromClause); } + + public function test_simple_select_star_to_sql() : void + { + self::assertSame( + 'SELECT * FROM users', + select()->select(star())->from(table('users'))->toSql() + ); + } + + public function test_simple_select_with_where_to_sql() : void + { + self::assertSame( + 'SELECT * FROM users WHERE active = true', + select()->select(star())->from(table('users'))->where(eq(col('active'), literal(true)))->toSql() + ); + } + + public function test_sql_value_function_current_date_to_sql() : void + { + self::assertSame( + 'SELECT current_date AS today', + select()->select(current_date()->as('today'))->toSql() + ); + } + + public function test_sql_value_function_current_time_to_sql() : void + { + self::assertSame( + 'SELECT current_time AS now_time', + select()->select(current_time()->as('now_time'))->toSql() + ); + } + + public function test_sql_value_function_current_timestamp_to_sql() : void + { + self::assertSame( + 'SELECT current_timestamp AS now', + select()->select(current_timestamp()->as('now'))->toSql() + ); + } + + public function test_sql_value_functions_with_other_columns_to_sql() : void + { + self::assertSame( + 'SELECT id, name, current_timestamp AS created_at FROM users', + select() + ->select(col('id'), col('name'), current_timestamp()->as('created_at')) + ->from(table('users')) + ->toSql() + ); + } } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/TableBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Table/TableBuilderTest.php similarity index 61% rename from src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/TableBuilderTest.php rename to src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Table/TableBuilderTest.php index 240db50fa1..5904ea83da 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/TableBuilderTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Table/TableBuilderTest.php @@ -2,23 +2,25 @@ declare(strict_types=1); -namespace Flow\PostgreSql\Tests\Integration\QueryBuilder; +namespace Flow\PostgreSql\Tests\Unit\QueryBuilder\Table; use function Flow\PostgreSql\DSL\{ alter, check_constraint, col, column, + column_type_boolean, + column_type_integer, + column_type_serial, + column_type_text, + column_type_timestamp, + column_type_varchar, create, current_timestamp, - data_type_boolean, - data_type_integer, - data_type_serial, - data_type_text, - data_type_timestamp, - data_type_varchar, drop, foreign_key, + gt, + literal, primary_key, ref_action_cascade, ref_action_restrict, @@ -29,16 +31,18 @@ unique_constraint }; -final class TableBuilderTest extends PGQueryTestCase +use PHPUnit\Framework\TestCase; + +final class TableBuilderTest extends TestCase { public function test_alter_table_add_column() : void { $builder = alter()->table('users') - ->addColumn(column('email', data_type_varchar(255))->notNull()); + ->addColumn(column('email', column_type_varchar(255))->notNull()); - $this->assertAlterTableQuery( - $builder, - 'ALTER TABLE users ADD COLUMN email varchar(255) NOT NULL' + self::assertSame( + 'ALTER TABLE users ADD COLUMN email varchar(255) NOT NULL', + $builder->toSql() ); } @@ -47,20 +51,20 @@ public function test_alter_table_add_constraint() : void $builder = alter()->table('users') ->addConstraint(unique_constraint('email')->name('users_email_unique')); - $this->assertAlterTableQuery( - $builder, - 'ALTER TABLE users ADD CONSTRAINT users_email_unique UNIQUE (email)' + self::assertSame( + 'ALTER TABLE users ADD CONSTRAINT users_email_unique UNIQUE (email)', + $builder->toSql() ); } public function test_alter_table_alter_column_set_default() : void { $builder = alter()->table('users') - ->alterColumnSetDefault('status', "'active'"); + ->alterColumnSetDefault('status', literal('active')); - $this->assertAlterTableQuery( - $builder, - "ALTER TABLE users ALTER COLUMN status SET DEFAULT 'active'" + self::assertSame( + "ALTER TABLE users ALTER COLUMN status SET DEFAULT 'active'", + $builder->toSql() ); } @@ -69,20 +73,20 @@ public function test_alter_table_alter_column_set_not_null() : void $builder = alter()->table('users') ->alterColumnSetNotNull('email'); - $this->assertAlterTableQuery( - $builder, - 'ALTER TABLE users ALTER COLUMN email SET NOT NULL' + self::assertSame( + 'ALTER TABLE users ALTER COLUMN email SET NOT NULL', + $builder->toSql() ); } public function test_alter_table_alter_column_type() : void { $builder = alter()->table('users') - ->alterColumnType('name', data_type_text()); + ->alterColumnType('name', column_type_text()); - $this->assertAlterTableQuery( - $builder, - 'ALTER TABLE users ALTER COLUMN name TYPE pg_catalog.text' + self::assertSame( + 'ALTER TABLE users ALTER COLUMN name TYPE pg_catalog.text', + $builder->toSql() ); } @@ -91,9 +95,9 @@ public function test_alter_table_drop_column() : void $builder = alter()->table('users') ->dropColumn('temp_column'); - $this->assertAlterTableQuery( - $builder, - 'ALTER TABLE users DROP temp_column' + self::assertSame( + 'ALTER TABLE users DROP temp_column', + $builder->toSql() ); } @@ -102,9 +106,9 @@ public function test_alter_table_drop_column_cascade() : void $builder = alter()->table('users') ->dropColumn('temp_column', cascade: true); - $this->assertAlterTableQuery( - $builder, - 'ALTER TABLE users DROP temp_column CASCADE' + self::assertSame( + 'ALTER TABLE users DROP temp_column CASCADE', + $builder->toSql() ); } @@ -113,9 +117,9 @@ public function test_alter_table_drop_constraint() : void $builder = alter()->table('users') ->dropConstraint('users_email_unique'); - $this->assertAlterTableQuery( - $builder, - 'ALTER TABLE users DROP CONSTRAINT users_email_unique' + self::assertSame( + 'ALTER TABLE users DROP CONSTRAINT users_email_unique', + $builder->toSql() ); } @@ -123,24 +127,24 @@ public function test_alter_table_if_exists() : void { $builder = alter()->table('users') ->ifExists() - ->addColumn(column('email', data_type_varchar(255))); + ->addColumn(column('email', column_type_varchar(255))); - $this->assertAlterTableQuery( - $builder, - 'ALTER TABLE IF EXISTS users ADD COLUMN email varchar(255)' + self::assertSame( + 'ALTER TABLE IF EXISTS users ADD COLUMN email varchar(255)', + $builder->toSql() ); } public function test_alter_table_multiple_operations() : void { $builder = alter()->table('users') - ->addColumn(column('phone', data_type_varchar(20))) + ->addColumn(column('phone', column_type_varchar(20))) ->dropColumn('fax') ->alterColumnSetNotNull('email'); - $this->assertAlterTableQuery( - $builder, - 'ALTER TABLE users ADD COLUMN phone varchar(20), DROP fax, ALTER COLUMN email SET NOT NULL' + self::assertSame( + 'ALTER TABLE users ADD COLUMN phone varchar(20), DROP fax, ALTER COLUMN email SET NOT NULL', + $builder->toSql() ); } @@ -149,9 +153,9 @@ public function test_alter_table_rename_column() : void $builder = alter()->table('users') ->renameColumn('old_name', 'new_name'); - $this->assertRenameQuery( - $builder, - 'ALTER TABLE users RENAME COLUMN old_name TO new_name' + self::assertSame( + 'ALTER TABLE users RENAME COLUMN old_name TO new_name', + $builder->toSql() ); } @@ -161,9 +165,9 @@ public function test_alter_table_rename_column_if_exists() : void ->ifExists() ->renameColumn('old_name', 'new_name'); - $this->assertRenameQuery( - $builder, - 'ALTER TABLE IF EXISTS users RENAME COLUMN old_name TO new_name' + self::assertSame( + 'ALTER TABLE IF EXISTS users RENAME COLUMN old_name TO new_name', + $builder->toSql() ); } @@ -172,9 +176,9 @@ public function test_alter_table_rename_column_with_schema() : void $builder = alter()->table('users', 'public') ->renameColumn('old_name', 'new_name'); - $this->assertRenameQuery( - $builder, - 'ALTER TABLE public.users RENAME COLUMN old_name TO new_name' + self::assertSame( + 'ALTER TABLE public.users RENAME COLUMN old_name TO new_name', + $builder->toSql() ); } @@ -183,9 +187,9 @@ public function test_alter_table_rename_constraint() : void $builder = alter()->table('users') ->renameConstraint('old_constraint', 'new_constraint'); - $this->assertRenameQuery( - $builder, - 'ALTER TABLE users RENAME CONSTRAINT old_constraint TO new_constraint' + self::assertSame( + 'ALTER TABLE users RENAME CONSTRAINT old_constraint TO new_constraint', + $builder->toSql() ); } @@ -194,9 +198,9 @@ public function test_alter_table_rename_to() : void $builder = alter()->table('users') ->renameTo('users_archive'); - $this->assertRenameQuery( - $builder, - 'ALTER TABLE users RENAME TO users_archive' + self::assertSame( + 'ALTER TABLE users RENAME TO users_archive', + $builder->toSql() ); } @@ -205,9 +209,9 @@ public function test_alter_table_set_schema() : void $builder = alter()->table('users') ->setSchema('archive'); - $this->assertAlterObjectSchemaQuery( - $builder, - 'ALTER TABLE users SET SCHEMA archive' + self::assertSame( + 'ALTER TABLE users SET SCHEMA archive', + $builder->toSql() ); } @@ -217,20 +221,20 @@ public function test_alter_table_set_schema_if_exists() : void ->ifExists() ->setSchema('archive'); - $this->assertAlterObjectSchemaQuery( - $builder, - 'ALTER TABLE IF EXISTS users SET SCHEMA archive' + self::assertSame( + 'ALTER TABLE IF EXISTS users SET SCHEMA archive', + $builder->toSql() ); } public function test_alter_table_with_schema() : void { $builder = alter()->table('users', 'public') - ->addColumn(column('email', data_type_varchar(255))); + ->addColumn(column('email', column_type_varchar(255))); - $this->assertAlterTableQuery( - $builder, - 'ALTER TABLE public.users ADD COLUMN email varchar(255)' + self::assertSame( + 'ALTER TABLE public.users ADD COLUMN email varchar(255)', + $builder->toSql() ); } @@ -243,9 +247,9 @@ public function test_create_table_as_if_not_exists() : void $builder = create()->tableAs('users_backup', $selectBuilder) ->ifNotExists(); - $this->assertCreateTableAsQuery( - $builder, - 'CREATE TABLE IF NOT EXISTS users_backup AS SELECT id, name FROM users' + self::assertSame( + 'CREATE TABLE IF NOT EXISTS users_backup AS SELECT id, name FROM users', + $builder->toSql() ); } @@ -258,9 +262,9 @@ public function test_create_table_as_with_column_names() : void $builder = create()->tableAs('users_backup', $selectBuilder) ->columnNames('user_id', 'user_name'); - $this->assertCreateTableAsQuery( - $builder, - 'CREATE TABLE users_backup(user_id, user_name) AS SELECT id, name FROM users' + self::assertSame( + 'CREATE TABLE users_backup(user_id, user_name) AS SELECT id, name FROM users', + $builder->toSql() ); } @@ -273,9 +277,9 @@ public function test_create_table_as_with_no_data() : void $builder = create()->tableAs('users_backup', $selectBuilder) ->withNoData(); - $this->assertCreateTableAsQuery( - $builder, - 'CREATE TABLE users_backup AS SELECT id, name FROM users WITH NO DATA' + self::assertSame( + 'CREATE TABLE users_backup AS SELECT id, name FROM users WITH NO DATA', + $builder->toSql() ); } @@ -283,146 +287,146 @@ public function test_create_table_if_not_exists() : void { $builder = create()->table('users') ->ifNotExists() - ->column(column('id', data_type_serial())->primaryKey()) - ->column(column('name', data_type_varchar(100))); + ->column(column('id', column_type_serial())->primaryKey()) + ->column(column('name', column_type_varchar(100))); - $this->assertCreateTableQuery( - $builder, - 'CREATE TABLE IF NOT EXISTS users (id serial PRIMARY KEY, name varchar(100))' + self::assertSame( + 'CREATE TABLE IF NOT EXISTS users (id serial PRIMARY KEY, name varchar(100))', + $builder->toSql() ); } public function test_create_table_simple() : void { $builder = create()->table('users') - ->column(column('id', data_type_serial())->primaryKey()) - ->column(column('name', data_type_varchar(100))->notNull()); + ->column(column('id', column_type_serial())->primaryKey()) + ->column(column('name', column_type_varchar(100))->notNull()); - $this->assertCreateTableQuery( - $builder, - 'CREATE TABLE users (id serial PRIMARY KEY, name varchar(100) NOT NULL)' + self::assertSame( + 'CREATE TABLE users (id serial PRIMARY KEY, name varchar(100) NOT NULL)', + $builder->toSql() ); } public function test_create_table_with_check_constraint() : void { $builder = create()->table('products') - ->column(column('id', data_type_serial())->primaryKey()) - ->column(column('price', data_type_integer())) - ->constraint(check_constraint('price > 0')->name('positive_price')); + ->column(column('id', column_type_serial())->primaryKey()) + ->column(column('price', column_type_integer())) + ->constraint(check_constraint(gt(col('price'), literal(0)))->name('positive_price')); - $this->assertCreateTableQuery( - $builder, - 'CREATE TABLE products (id serial PRIMARY KEY, price int, CONSTRAINT positive_price CHECK (price > 0))' + self::assertSame( + 'CREATE TABLE products (id serial PRIMARY KEY, price int, CONSTRAINT positive_price CHECK (price > 0))', + $builder->toSql() ); } public function test_create_table_with_column_default() : void { $builder = create()->table('users') - ->column(column('id', data_type_serial())->primaryKey()) - ->column(column('active', data_type_boolean())->default(true)); + ->column(column('id', column_type_serial())->primaryKey()) + ->column(column('active', column_type_boolean())->default(true)); - $this->assertCreateTableQuery( - $builder, - 'CREATE TABLE users (id serial PRIMARY KEY, active boolean DEFAULT true)' + self::assertSame( + 'CREATE TABLE users (id serial PRIMARY KEY, active boolean DEFAULT true)', + $builder->toSql() ); } public function test_create_table_with_column_default_current_timestamp() : void { $builder = create()->table('audit_log') - ->column(column('id', data_type_serial())->primaryKey()) - ->column(column('message', data_type_text())->notNull()) - ->column(column('created_at', data_type_timestamp())->notNull()->default(current_timestamp())); + ->column(column('id', column_type_serial())->primaryKey()) + ->column(column('message', column_type_text())->notNull()) + ->column(column('created_at', column_type_timestamp())->notNull()->default(current_timestamp())); - $this->assertCreateTableQuery( - $builder, - 'CREATE TABLE audit_log (id serial PRIMARY KEY, message pg_catalog.text NOT NULL, created_at timestamp NOT NULL DEFAULT current_timestamp)' + self::assertSame( + 'CREATE TABLE audit_log (id serial PRIMARY KEY, message pg_catalog.text NOT NULL, created_at timestamp NOT NULL DEFAULT current_timestamp)', + $builder->toSql() ); } public function test_create_table_with_composite_primary_key() : void { $builder = create()->table('order_items') - ->column(column('order_id', data_type_integer())->notNull()) - ->column(column('product_id', data_type_integer())->notNull()) - ->column(column('quantity', data_type_integer())) + ->column(column('order_id', column_type_integer())->notNull()) + ->column(column('product_id', column_type_integer())->notNull()) + ->column(column('quantity', column_type_integer())) ->constraint(primary_key('order_id', 'product_id')); - $this->assertCreateTableQuery( - $builder, - 'CREATE TABLE order_items (order_id int NOT NULL, product_id int NOT NULL, quantity int, PRIMARY KEY (order_id, product_id))' + self::assertSame( + 'CREATE TABLE order_items (order_id int NOT NULL, product_id int NOT NULL, quantity int, PRIMARY KEY (order_id, product_id))', + $builder->toSql() ); } public function test_create_table_with_foreign_key() : void { $builder = create()->table('orders') - ->column(column('id', data_type_serial())->primaryKey()) - ->column(column('user_id', data_type_integer())->notNull()) + ->column(column('id', column_type_serial())->primaryKey()) + ->column(column('user_id', column_type_integer())->notNull()) ->constraint( foreign_key(['user_id'], 'users', ['id']) ->onDelete(ref_action_cascade()) ->onUpdate(ref_action_restrict()) ); - $this->assertCreateTableQuery( - $builder, - 'CREATE TABLE orders (id serial PRIMARY KEY, user_id int NOT NULL, FOREIGN KEY (user_id) REFERENCES users (id) ON UPDATE RESTRICT ON DELETE CASCADE)' + self::assertSame( + 'CREATE TABLE orders (id serial PRIMARY KEY, user_id int NOT NULL, FOREIGN KEY (user_id) REFERENCES users (id) ON UPDATE RESTRICT ON DELETE CASCADE)', + $builder->toSql() ); } public function test_create_table_with_foreign_key_set_null() : void { $builder = create()->table('comments') - ->column(column('id', data_type_serial())->primaryKey()) - ->column(column('user_id', data_type_integer())) + ->column(column('id', column_type_serial())->primaryKey()) + ->column(column('user_id', column_type_integer())) ->constraint( foreign_key(['user_id'], 'users', ['id']) ->onDelete(ref_action_set_null()) ); - $this->assertCreateTableQuery( - $builder, - 'CREATE TABLE comments (id serial PRIMARY KEY, user_id int, FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE SET NULL)' + self::assertSame( + 'CREATE TABLE comments (id serial PRIMARY KEY, user_id int, FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE SET NULL)', + $builder->toSql() ); } public function test_create_table_with_schema() : void { $builder = create()->table('users', 'public') - ->column(column('id', data_type_serial())->primaryKey()); + ->column(column('id', column_type_serial())->primaryKey()); - $this->assertCreateTableQuery( - $builder, - 'CREATE TABLE public.users (id serial PRIMARY KEY)' + self::assertSame( + 'CREATE TABLE public.users (id serial PRIMARY KEY)', + $builder->toSql() ); } public function test_create_table_with_timestamp() : void { $builder = create()->table('audit_log') - ->column(column('id', data_type_serial())->primaryKey()) - ->column(column('created_at', data_type_timestamp())->notNull()) - ->column(column('updated_at', data_type_timestamp())); + ->column(column('id', column_type_serial())->primaryKey()) + ->column(column('created_at', column_type_timestamp())->notNull()) + ->column(column('updated_at', column_type_timestamp())); - $this->assertCreateTableQuery( - $builder, - 'CREATE TABLE audit_log (id serial PRIMARY KEY, created_at timestamp NOT NULL, updated_at timestamp)' + self::assertSame( + 'CREATE TABLE audit_log (id serial PRIMARY KEY, created_at timestamp NOT NULL, updated_at timestamp)', + $builder->toSql() ); } public function test_create_table_with_unique_constraint() : void { $builder = create()->table('users') - ->column(column('id', data_type_serial())->primaryKey()) - ->column(column('email', data_type_varchar(255))->notNull()) + ->column(column('id', column_type_serial())->primaryKey()) + ->column(column('email', column_type_varchar(255))->notNull()) ->constraint(unique_constraint('email')); - $this->assertCreateTableQuery( - $builder, - 'CREATE TABLE users (id serial PRIMARY KEY, email varchar(255) NOT NULL, UNIQUE (email))' + self::assertSame( + 'CREATE TABLE users (id serial PRIMARY KEY, email varchar(255) NOT NULL, UNIQUE (email))', + $builder->toSql() ); } @@ -431,9 +435,9 @@ public function test_drop_table_cascade() : void $builder = drop()->table('users') ->cascade(); - $this->assertDropTableQuery( - $builder, - 'DROP TABLE users CASCADE' + self::assertSame( + 'DROP TABLE users CASCADE', + $builder->toSql() ); } @@ -442,9 +446,9 @@ public function test_drop_table_if_exists() : void $builder = drop()->table('users') ->ifExists(); - $this->assertDropTableQuery( - $builder, - 'DROP TABLE IF EXISTS users' + self::assertSame( + 'DROP TABLE IF EXISTS users', + $builder->toSql() ); } @@ -454,9 +458,9 @@ public function test_drop_table_if_exists_cascade() : void ->ifExists() ->cascade(); - $this->assertDropTableQuery( - $builder, - 'DROP TABLE IF EXISTS users CASCADE' + self::assertSame( + 'DROP TABLE IF EXISTS users CASCADE', + $builder->toSql() ); } @@ -464,9 +468,9 @@ public function test_drop_table_multiple_tables() : void { $builder = drop()->table('users', 'orders', 'products'); - $this->assertDropTableQuery( - $builder, - 'DROP TABLE users, orders, products' + self::assertSame( + 'DROP TABLE users, orders, products', + $builder->toSql() ); } @@ -475,9 +479,9 @@ public function test_drop_table_restrict() : void $builder = drop()->table('users') ->restrict(); - $this->assertDropTableQuery( - $builder, - 'DROP TABLE users' + self::assertSame( + 'DROP TABLE users', + $builder->toSql() ); } @@ -485,9 +489,9 @@ public function test_drop_table_simple() : void { $builder = drop()->table('users'); - $this->assertDropTableQuery( - $builder, - 'DROP TABLE users' + self::assertSame( + 'DROP TABLE users', + $builder->toSql() ); } @@ -495,9 +499,9 @@ public function test_drop_table_with_schema() : void { $builder = drop()->table('public.users'); - $this->assertDropTableQuery( - $builder, - 'DROP TABLE public.users' + self::assertSame( + 'DROP TABLE public.users', + $builder->toSql() ); } @@ -509,9 +513,9 @@ public function test_simple_create_table_as() : void $builder = create()->tableAs('users_backup', $selectBuilder); - $this->assertCreateTableAsQuery( - $builder, - 'CREATE TABLE users_backup AS SELECT id, name FROM users' + self::assertSame( + 'CREATE TABLE users_backup AS SELECT id, name FROM users', + $builder->toSql() ); } @@ -520,9 +524,9 @@ public function test_truncate_cascade() : void $builder = truncate_table('users') ->cascade(); - $this->assertTruncateQuery( - $builder, - 'TRUNCATE users CASCADE' + self::assertSame( + 'TRUNCATE users CASCADE', + $builder->toSql() ); } @@ -530,9 +534,9 @@ public function test_truncate_multiple_tables() : void { $builder = truncate_table('users', 'orders', 'products'); - $this->assertTruncateQuery( - $builder, - 'TRUNCATE users, orders, products' + self::assertSame( + 'TRUNCATE users, orders, products', + $builder->toSql() ); } @@ -541,9 +545,9 @@ public function test_truncate_restart_identity() : void $builder = truncate_table('users') ->restartIdentity(); - $this->assertTruncateQuery( - $builder, - 'TRUNCATE users RESTART IDENTITY' + self::assertSame( + 'TRUNCATE users RESTART IDENTITY', + $builder->toSql() ); } @@ -553,9 +557,9 @@ public function test_truncate_restart_identity_cascade() : void ->restartIdentity() ->cascade(); - $this->assertTruncateQuery( - $builder, - 'TRUNCATE users RESTART IDENTITY CASCADE' + self::assertSame( + 'TRUNCATE users RESTART IDENTITY CASCADE', + $builder->toSql() ); } @@ -564,9 +568,9 @@ public function test_truncate_restrict() : void $builder = truncate_table('users') ->restrict(); - $this->assertTruncateQuery( - $builder, - 'TRUNCATE users' + self::assertSame( + 'TRUNCATE users', + $builder->toSql() ); } @@ -574,9 +578,9 @@ public function test_truncate_simple() : void { $builder = truncate_table('users'); - $this->assertTruncateQuery( - $builder, - 'TRUNCATE users' + self::assertSame( + 'TRUNCATE users', + $builder->toSql() ); } @@ -584,9 +588,9 @@ public function test_truncate_with_schema() : void { $builder = truncate_table('public.users'); - $this->assertTruncateQuery( - $builder, - 'TRUNCATE public.users' + self::assertSame( + 'TRUNCATE public.users', + $builder->toSql() ); } } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/TransactionBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Transaction/TransactionBuilderTest.php similarity index 61% rename from src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/TransactionBuilderTest.php rename to src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Transaction/TransactionBuilderTest.php index 0abecc18ba..0a9802f97a 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/TransactionBuilderTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Transaction/TransactionBuilderTest.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\PostgreSql\Tests\Integration\QueryBuilder; +namespace Flow\PostgreSql\Tests\Unit\QueryBuilder\Transaction; use function Flow\PostgreSql\DSL\{ begin, @@ -19,16 +19,17 @@ }; use Flow\PostgreSql\QueryBuilder\Transaction\IsolationLevel; +use PHPUnit\Framework\TestCase; -final class TransactionBuilderTest extends PGQueryTestCase +final class TransactionBuilderTest extends TestCase { public function test_begin_basic() : void { $query = begin(); - $this->assertTransactionQueryEquals( - $query, - 'BEGIN' + self::assertSame( + 'BEGIN', + $query->toSql() ); } @@ -39,9 +40,9 @@ public function test_begin_with_all_options() : void ->readOnly() ->deferrable(); - $this->assertTransactionQueryEquals( - $query, - 'BEGIN ISOLATION LEVEL SERIALIZABLE, READ ONLY, DEFERRABLE' + self::assertSame( + 'BEGIN ISOLATION LEVEL SERIALIZABLE, READ ONLY, DEFERRABLE', + $query->toSql() ); } @@ -50,9 +51,9 @@ public function test_begin_with_deferrable() : void $query = begin() ->deferrable(); - $this->assertTransactionQueryEquals( - $query, - 'BEGIN DEFERRABLE' + self::assertSame( + 'BEGIN DEFERRABLE', + $query->toSql() ); } @@ -61,9 +62,9 @@ public function test_begin_with_isolation_level_read_committed() : void $query = begin() ->isolationLevel(IsolationLevel::READ_COMMITTED); - $this->assertTransactionQueryEquals( - $query, - 'BEGIN ISOLATION LEVEL READ COMMITTED' + self::assertSame( + 'BEGIN ISOLATION LEVEL READ COMMITTED', + $query->toSql() ); } @@ -72,9 +73,9 @@ public function test_begin_with_isolation_level_read_uncommitted() : void $query = begin() ->isolationLevel(IsolationLevel::READ_UNCOMMITTED); - $this->assertTransactionQueryEquals( - $query, - 'BEGIN ISOLATION LEVEL READ UNCOMMITTED' + self::assertSame( + 'BEGIN ISOLATION LEVEL READ UNCOMMITTED', + $query->toSql() ); } @@ -83,9 +84,9 @@ public function test_begin_with_isolation_level_repeatable_read() : void $query = begin() ->isolationLevel(IsolationLevel::REPEATABLE_READ); - $this->assertTransactionQueryEquals( - $query, - 'BEGIN ISOLATION LEVEL REPEATABLE READ' + self::assertSame( + 'BEGIN ISOLATION LEVEL REPEATABLE READ', + $query->toSql() ); } @@ -94,9 +95,9 @@ public function test_begin_with_isolation_level_serializable() : void $query = begin() ->isolationLevel(IsolationLevel::SERIALIZABLE); - $this->assertTransactionQueryEquals( - $query, - 'BEGIN ISOLATION LEVEL SERIALIZABLE' + self::assertSame( + 'BEGIN ISOLATION LEVEL SERIALIZABLE', + $query->toSql() ); } @@ -105,9 +106,9 @@ public function test_begin_with_not_deferrable() : void $query = begin() ->notDeferrable(); - $this->assertTransactionQueryEquals( - $query, - 'BEGIN NOT DEFERRABLE' + self::assertSame( + 'BEGIN NOT DEFERRABLE', + $query->toSql() ); } @@ -116,9 +117,9 @@ public function test_begin_with_read_only() : void $query = begin() ->readOnly(); - $this->assertTransactionQueryEquals( - $query, - 'BEGIN READ ONLY' + self::assertSame( + 'BEGIN READ ONLY', + $query->toSql() ); } @@ -127,9 +128,9 @@ public function test_begin_with_read_write() : void $query = begin() ->readWrite(); - $this->assertTransactionQueryEquals( - $query, - 'BEGIN READ WRITE' + self::assertSame( + 'BEGIN READ WRITE', + $query->toSql() ); } @@ -138,9 +139,9 @@ public function test_commit_and_chain() : void $query = commit() ->andChain(); - $this->assertTransactionQueryEquals( - $query, - 'COMMIT AND CHAIN' + self::assertSame( + 'COMMIT AND CHAIN', + $query->toSql() ); } @@ -148,9 +149,9 @@ public function test_commit_basic() : void { $query = commit(); - $this->assertTransactionQueryEquals( - $query, - 'COMMIT' + self::assertSame( + 'COMMIT', + $query->toSql() ); } @@ -158,9 +159,9 @@ public function test_commit_prepared() : void { $query = commit_prepared('my_transaction'); - $this->assertTransactionQueryEquals( - $query, - "COMMIT PREPARED 'my_transaction'" + self::assertSame( + "COMMIT PREPARED 'my_transaction'", + $query->toSql() ); } @@ -168,9 +169,9 @@ public function test_prepare_transaction() : void { $query = prepare_transaction('my_transaction'); - $this->assertTransactionQueryEquals( - $query, - "PREPARE TRANSACTION 'my_transaction'" + self::assertSame( + "PREPARE TRANSACTION 'my_transaction'", + $query->toSql() ); } @@ -178,9 +179,9 @@ public function test_release_savepoint() : void { $query = release_savepoint('my_savepoint'); - $this->assertTransactionQueryEquals( - $query, - 'RELEASE my_savepoint' + self::assertSame( + 'RELEASE my_savepoint', + $query->toSql() ); } @@ -189,9 +190,9 @@ public function test_rollback_and_chain() : void $query = rollback() ->andChain(); - $this->assertTransactionQueryEquals( - $query, - 'ROLLBACK AND CHAIN' + self::assertSame( + 'ROLLBACK AND CHAIN', + $query->toSql() ); } @@ -199,9 +200,9 @@ public function test_rollback_basic() : void { $query = rollback(); - $this->assertTransactionQueryEquals( - $query, - 'ROLLBACK' + self::assertSame( + 'ROLLBACK', + $query->toSql() ); } @@ -209,9 +210,9 @@ public function test_rollback_prepared() : void { $query = rollback_prepared('my_transaction'); - $this->assertTransactionQueryEquals( - $query, - "ROLLBACK PREPARED 'my_transaction'" + self::assertSame( + "ROLLBACK PREPARED 'my_transaction'", + $query->toSql() ); } @@ -220,9 +221,9 @@ public function test_rollback_to_savepoint() : void $query = rollback() ->toSavepoint('my_savepoint'); - $this->assertTransactionQueryEquals( - $query, - 'ROLLBACK TO SAVEPOINT my_savepoint' + self::assertSame( + 'ROLLBACK TO SAVEPOINT my_savepoint', + $query->toSql() ); } @@ -230,9 +231,9 @@ public function test_savepoint() : void { $query = savepoint('my_savepoint'); - $this->assertTransactionQueryEquals( - $query, - 'SAVEPOINT my_savepoint' + self::assertSame( + 'SAVEPOINT my_savepoint', + $query->toSql() ); } @@ -241,9 +242,9 @@ public function test_set_session_transaction() : void $query = set_session_transaction() ->isolationLevel(IsolationLevel::SERIALIZABLE); - $this->assertSetTransactionQueryEquals( - $query, - 'SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE' + self::assertSame( + 'SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE', + $query->toSql() ); } @@ -252,9 +253,9 @@ public function test_set_transaction_deferrable() : void $query = set_transaction() ->deferrable(); - $this->assertSetTransactionQueryEquals( - $query, - 'SET TRANSACTION DEFERRABLE' + self::assertSame( + 'SET TRANSACTION DEFERRABLE', + $query->toSql() ); } @@ -263,9 +264,9 @@ public function test_set_transaction_isolation_level() : void $query = set_transaction() ->isolationLevel(IsolationLevel::SERIALIZABLE); - $this->assertSetTransactionQueryEquals( - $query, - 'SET TRANSACTION ISOLATION LEVEL SERIALIZABLE' + self::assertSame( + 'SET TRANSACTION ISOLATION LEVEL SERIALIZABLE', + $query->toSql() ); } @@ -274,9 +275,9 @@ public function test_set_transaction_read_only() : void $query = set_transaction() ->readOnly(); - $this->assertSetTransactionQueryEquals( - $query, - 'SET TRANSACTION READ ONLY' + self::assertSame( + 'SET TRANSACTION READ ONLY', + $query->toSql() ); } @@ -285,9 +286,9 @@ public function test_set_transaction_read_write() : void $query = set_transaction() ->readWrite(); - $this->assertSetTransactionQueryEquals( - $query, - 'SET TRANSACTION READ WRITE' + self::assertSame( + 'SET TRANSACTION READ WRITE', + $query->toSql() ); } @@ -298,9 +299,9 @@ public function test_set_transaction_with_multiple_options() : void ->readOnly() ->deferrable(); - $this->assertSetTransactionQueryEquals( - $query, - 'SET TRANSACTION ISOLATION LEVEL SERIALIZABLE, READ ONLY, DEFERRABLE' + self::assertSame( + 'SET TRANSACTION ISOLATION LEVEL SERIALIZABLE, READ ONLY, DEFERRABLE', + $query->toSql() ); } @@ -308,9 +309,9 @@ public function test_start_transaction_basic() : void { $query = begin(); - $this->assertTransactionQueryEquals( - $query, - 'BEGIN' + self::assertSame( + 'BEGIN', + $query->toSql() ); } @@ -318,9 +319,9 @@ public function test_transaction_snapshot() : void { $query = transaction_snapshot('00000003-0000001A-1'); - $this->assertSetTransactionQueryEquals( - $query, - "SET TRANSACTION SNAPSHOT '00000003-0000001A-1'" + self::assertSame( + "SET TRANSACTION SNAPSHOT '00000003-0000001A-1'", + $query->toSql() ); } } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Update/UpdateBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Update/UpdateBuilderTest.php index 2dfb9d6738..74f2ff1e63 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Update/UpdateBuilderTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Update/UpdateBuilderTest.php @@ -4,6 +4,7 @@ namespace Flow\PostgreSql\Tests\Unit\QueryBuilder\Update; +use function Flow\PostgreSql\DSL\{col, eq, literal, param, select, sub_select, table, update}; use Flow\PostgreSql\{ParsedQuery, Parser}; use Flow\PostgreSql\Protobuf\AST\{Node, RawStmt, UpdateStmt}; use Flow\PostgreSql\QueryBuilder\Clause\{CTE, WithClause}; @@ -428,6 +429,16 @@ public function test_update_with_binary_expression_deparsed_output() : void self::assertSame('UPDATE counters SET count = count + 1', $deparsed); } + public function test_update_with_column_expression() : void + { + $query = update() + ->update('products') + ->set('price', col('price')) + ->where(eq(col('id'), literal(1))); + + self::assertSame('UPDATE products SET price = price WHERE id = 1', $query->toSql()); + } + public function test_update_with_column_reference() : void { $query = UpdateBuilder::create() @@ -528,6 +539,27 @@ public function test_update_with_multiple_from_tables() : void self::assertCount(2, $fromClause); } + public function test_update_with_multiple_set() : void + { + $query = update() + ->update('users') + ->set('name', literal('John')) + ->set('email', literal('john@example.com')) + ->where(eq(col('id'), literal(1))); + + self::assertSame("UPDATE users SET name = 'John', email = 'john@example.com' WHERE id = 1", $query->toSql()); + } + + public function test_update_with_parameters() : void + { + $query = update() + ->update('users') + ->set('name', param(1)) + ->where(eq(col('id'), param(2))); + + self::assertSame('UPDATE users SET name = $1 WHERE id = $2', $query->toSql()); + } + public function test_update_with_returning() : void { $query = UpdateBuilder::create() @@ -639,6 +671,34 @@ public function test_update_with_schema_round_trip() : void self::assertSame($originalRelation->getSchemaname(), $restoredRelation->getSchemaname()); } + public function test_update_with_set_all() : void + { + $query = update() + ->update('users') + ->setAll([ + 'name' => literal('John'), + 'email' => literal('john@example.com'), + ]) + ->where(eq(col('id'), literal(1))); + + self::assertSame("UPDATE users SET name = 'John', email = 'john@example.com' WHERE id = 1", $query->toSql()); + } + + public function test_update_with_subquery_in_set() : void + { + $subquery = select() + ->select(col('avg_price')) + ->from(table('price_stats')) + ->where(eq(col('category'), col('products.category'))); + + $query = update() + ->update('products') + ->set('price', sub_select($subquery)) + ->where(eq(col('id'), literal(1))); + + self::assertSame('UPDATE products SET price = (SELECT avg_price FROM price_stats WHERE category = products.category) WHERE id = 1', $query->toSql()); + } + public function test_update_with_where() : void { $query = UpdateBuilder::create() diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/UtilityBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Utility/UtilityBuilderTest.php similarity index 60% rename from src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/UtilityBuilderTest.php rename to src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Utility/UtilityBuilderTest.php index cbb5c27859..11ec05049c 100644 --- a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/UtilityBuilderTest.php +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Utility/UtilityBuilderTest.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Flow\PostgreSql\Tests\Integration\QueryBuilder; +namespace Flow\PostgreSql\Tests\Unit\QueryBuilder\Utility; use function Flow\PostgreSql\DSL\{ analyze, @@ -17,16 +17,17 @@ vacuum }; use Flow\PostgreSql\QueryBuilder\Utility\{CommentTarget, DiscardType, ExplainFormat, IndexCleanup, LockMode}; +use PHPUnit\Framework\TestCase; -final class UtilityBuilderTest extends PGQueryTestCase +final class UtilityBuilderTest extends TestCase { public function test_analyze_all_tables() : void { $builder = analyze(); - $this->assertAnalyzeQuery( - $builder, - 'ANALYZE' + self::assertSame( + 'ANALYZE', + $builder->toSql() ); } @@ -34,9 +35,9 @@ public function test_analyze_multiple_tables() : void { $builder = analyze()->tables('users', 'orders', 'products'); - $this->assertAnalyzeQuery( - $builder, - 'ANALYZE users, orders, products' + self::assertSame( + 'ANALYZE users, orders, products', + $builder->toSql() ); } @@ -44,9 +45,9 @@ public function test_analyze_single_table() : void { $builder = analyze()->table('users'); - $this->assertAnalyzeQuery( - $builder, - 'ANALYZE users' + self::assertSame( + 'ANALYZE users', + $builder->toSql() ); } @@ -54,9 +55,9 @@ public function test_analyze_skip_locked() : void { $builder = analyze()->skipLocked()->table('users'); - $this->assertAnalyzeQuery( - $builder, - 'ANALYZE (SKIP_LOCKED) users' + self::assertSame( + 'ANALYZE (SKIP_LOCKED) users', + $builder->toSql() ); } @@ -64,9 +65,9 @@ public function test_analyze_table_with_columns() : void { $builder = analyze()->table('users', 'email', 'name'); - $this->assertAnalyzeQuery( - $builder, - 'ANALYZE users(email, name)' + self::assertSame( + 'ANALYZE users(email, name)', + $builder->toSql() ); } @@ -74,9 +75,9 @@ public function test_analyze_verbose() : void { $builder = analyze()->verbose()->table('users'); - $this->assertAnalyzeQuery( - $builder, - 'ANALYZE (VERBOSE) users' + self::assertSame( + 'ANALYZE (VERBOSE) users', + $builder->toSql() ); } @@ -84,9 +85,9 @@ public function test_cluster_all_tables() : void { $builder = cluster(); - $this->assertClusterQuery( - $builder, - 'CLUSTER' + self::assertSame( + 'CLUSTER', + $builder->toSql() ); } @@ -94,9 +95,9 @@ public function test_cluster_single_table() : void { $builder = cluster()->table('users'); - $this->assertClusterQuery( - $builder, - 'CLUSTER users' + self::assertSame( + 'CLUSTER users', + $builder->toSql() ); } @@ -104,9 +105,9 @@ public function test_cluster_table_using_index() : void { $builder = cluster()->table('users')->using('idx_users_pkey'); - $this->assertClusterQuery( - $builder, - 'CLUSTER users USING idx_users_pkey' + self::assertSame( + 'CLUSTER users USING idx_users_pkey', + $builder->toSql() ); } @@ -114,9 +115,9 @@ public function test_cluster_table_with_schema() : void { $builder = cluster()->table('public.users'); - $this->assertClusterQuery( - $builder, - 'CLUSTER public.users' + self::assertSame( + 'CLUSTER public.users', + $builder->toSql() ); } @@ -124,9 +125,9 @@ public function test_cluster_verbose() : void { $builder = cluster()->verbose()->table('users'); - $this->assertClusterQuery( - $builder, - 'CLUSTER (VERBOSE) users' + self::assertSame( + 'CLUSTER (VERBOSE) users', + $builder->toSql() ); } @@ -134,9 +135,9 @@ public function test_comment_on_column() : void { $builder = comment(CommentTarget::COLUMN, 'users.email')->is('User email address'); - $this->assertCommentQuery( - $builder, - "COMMENT ON COLUMN users.email IS 'User email address'" + self::assertSame( + "COMMENT ON COLUMN users.email IS 'User email address'", + $builder->toSql() ); } @@ -144,9 +145,9 @@ public function test_comment_on_index() : void { $builder = comment(CommentTarget::INDEX, 'idx_users_email')->is('Email lookup index'); - $this->assertCommentQuery( - $builder, - "COMMENT ON INDEX idx_users_email IS 'Email lookup index'" + self::assertSame( + "COMMENT ON INDEX idx_users_email IS 'Email lookup index'", + $builder->toSql() ); } @@ -154,9 +155,9 @@ public function test_comment_on_schema() : void { $builder = comment(CommentTarget::SCHEMA, 'public')->is('Default schema'); - $this->assertCommentQuery( - $builder, - "COMMENT ON SCHEMA public IS 'Default schema'" + self::assertSame( + "COMMENT ON SCHEMA public IS 'Default schema'", + $builder->toSql() ); } @@ -164,9 +165,9 @@ public function test_comment_on_table() : void { $builder = comment(CommentTarget::TABLE, 'users')->is('User accounts table'); - $this->assertCommentQuery( - $builder, - "COMMENT ON TABLE users IS 'User accounts table'" + self::assertSame( + "COMMENT ON TABLE users IS 'User accounts table'", + $builder->toSql() ); } @@ -174,9 +175,9 @@ public function test_comment_remove() : void { $builder = comment(CommentTarget::TABLE, 'users')->isNull(); - $this->assertCommentQuery( - $builder, - 'COMMENT ON TABLE users IS NULL' + self::assertSame( + 'COMMENT ON TABLE users IS NULL', + $builder->toSql() ); } @@ -184,9 +185,9 @@ public function test_discard_all() : void { $builder = discard(DiscardType::ALL); - $this->assertDiscardQuery( - $builder, - 'DISCARD ALL' + self::assertSame( + 'DISCARD ALL', + $builder->toSql() ); } @@ -194,9 +195,9 @@ public function test_discard_plans() : void { $builder = discard(DiscardType::PLANS); - $this->assertDiscardQuery( - $builder, - 'DISCARD PLANS' + self::assertSame( + 'DISCARD PLANS', + $builder->toSql() ); } @@ -204,9 +205,9 @@ public function test_discard_sequences() : void { $builder = discard(DiscardType::SEQUENCES); - $this->assertDiscardQuery( - $builder, - 'DISCARD SEQUENCES' + self::assertSame( + 'DISCARD SEQUENCES', + $builder->toSql() ); } @@ -214,9 +215,9 @@ public function test_discard_temp() : void { $builder = discard(DiscardType::TEMP); - $this->assertDiscardQuery( - $builder, - 'DISCARD TEMP' + self::assertSame( + 'DISCARD TEMP', + $builder->toSql() ); } @@ -224,9 +225,9 @@ public function test_explain_analyze() : void { $builder = explain(select(star())->from(table('users')))->analyze(); - $this->assertExplainQuery( - $builder, - 'EXPLAIN (ANALYZE) SELECT * FROM users' + self::assertSame( + 'EXPLAIN (ANALYZE) SELECT * FROM users', + $builder->toSql() ); } @@ -234,9 +235,9 @@ public function test_explain_format_json() : void { $builder = explain(select(star())->from(table('users')))->format(ExplainFormat::JSON); - $this->assertExplainQuery( - $builder, - 'EXPLAIN (FORMAT "json") SELECT * FROM users' + self::assertSame( + 'EXPLAIN (FORMAT "json") SELECT * FROM users', + $builder->toSql() ); } @@ -244,9 +245,9 @@ public function test_explain_format_xml() : void { $builder = explain(select(star())->from(table('users')))->format(ExplainFormat::XML); - $this->assertExplainQuery( - $builder, - 'EXPLAIN (FORMAT xml) SELECT * FROM users' + self::assertSame( + 'EXPLAIN (FORMAT xml) SELECT * FROM users', + $builder->toSql() ); } @@ -254,9 +255,9 @@ public function test_explain_format_yaml() : void { $builder = explain(select(star())->from(table('users')))->format(ExplainFormat::YAML); - $this->assertExplainQuery( - $builder, - 'EXPLAIN (FORMAT yaml) SELECT * FROM users' + self::assertSame( + 'EXPLAIN (FORMAT yaml) SELECT * FROM users', + $builder->toSql() ); } @@ -269,9 +270,9 @@ public function test_explain_full_options() : void ->timing(true) ->format(ExplainFormat::JSON); - $this->assertExplainQuery( - $builder, - 'EXPLAIN (ANALYZE, VERBOSE, BUFFERS 1, TIMING 1, FORMAT "json") SELECT * FROM users' + self::assertSame( + 'EXPLAIN (ANALYZE, VERBOSE, BUFFERS 1, TIMING 1, FORMAT "json") SELECT * FROM users', + $builder->toSql() ); } @@ -279,9 +280,9 @@ public function test_explain_select() : void { $builder = explain(select(star())->from(table('users'))); - $this->assertExplainQuery( - $builder, - 'EXPLAIN SELECT * FROM users' + self::assertSame( + 'EXPLAIN SELECT * FROM users', + $builder->toSql() ); } @@ -289,9 +290,9 @@ public function test_explain_verbose() : void { $builder = explain(select(star())->from(table('users')))->verbose(); - $this->assertExplainQuery( - $builder, - 'EXPLAIN (VERBOSE) SELECT * FROM users' + self::assertSame( + 'EXPLAIN (VERBOSE) SELECT * FROM users', + $builder->toSql() ); } @@ -299,9 +300,9 @@ public function test_explain_with_buffers() : void { $builder = explain(select(star())->from(table('users')))->analyze()->buffers(true); - $this->assertExplainQuery( - $builder, - 'EXPLAIN (ANALYZE, BUFFERS 1) SELECT * FROM users' + self::assertSame( + 'EXPLAIN (ANALYZE, BUFFERS 1) SELECT * FROM users', + $builder->toSql() ); } @@ -309,9 +310,9 @@ public function test_explain_with_costs() : void { $builder = explain(select(star())->from(table('users')))->costs(true); - $this->assertExplainQuery( - $builder, - 'EXPLAIN (COSTS 1) SELECT * FROM users' + self::assertSame( + 'EXPLAIN (COSTS 1) SELECT * FROM users', + $builder->toSql() ); } @@ -319,9 +320,9 @@ public function test_explain_with_timing() : void { $builder = explain(select(star())->from(table('users')))->analyze()->timing(true); - $this->assertExplainQuery( - $builder, - 'EXPLAIN (ANALYZE, TIMING 1) SELECT * FROM users' + self::assertSame( + 'EXPLAIN (ANALYZE, TIMING 1) SELECT * FROM users', + $builder->toSql() ); } @@ -329,9 +330,9 @@ public function test_explain_without_costs() : void { $builder = explain(select(star())->from(table('users')))->costs(false); - $this->assertExplainQuery( - $builder, - 'EXPLAIN (COSTS 0) SELECT * FROM users' + self::assertSame( + 'EXPLAIN (COSTS 0) SELECT * FROM users', + $builder->toSql() ); } @@ -339,9 +340,9 @@ public function test_lock_multiple_tables() : void { $builder = lock_table('users', 'orders')->exclusive(); - $this->assertLockQuery( - $builder, - 'LOCK TABLE users, orders IN EXCLUSIVE MODE' + self::assertSame( + 'LOCK TABLE users, orders IN EXCLUSIVE MODE', + $builder->toSql() ); } @@ -349,9 +350,9 @@ public function test_lock_table_access_exclusive() : void { $builder = lock_table('users')->accessExclusive(); - $this->assertLockQuery( - $builder, - 'LOCK TABLE users' + self::assertSame( + 'LOCK TABLE users', + $builder->toSql() ); } @@ -359,9 +360,9 @@ public function test_lock_table_access_share() : void { $builder = lock_table('users')->accessShare(); - $this->assertLockQuery( - $builder, - 'LOCK TABLE users IN ACCESS SHARE MODE' + self::assertSame( + 'LOCK TABLE users IN ACCESS SHARE MODE', + $builder->toSql() ); } @@ -369,9 +370,9 @@ public function test_lock_table_default() : void { $builder = lock_table('users'); - $this->assertLockQuery( - $builder, - 'LOCK TABLE users' + self::assertSame( + 'LOCK TABLE users', + $builder->toSql() ); } @@ -379,9 +380,9 @@ public function test_lock_table_exclusive() : void { $builder = lock_table('users')->exclusive(); - $this->assertLockQuery( - $builder, - 'LOCK TABLE users IN EXCLUSIVE MODE' + self::assertSame( + 'LOCK TABLE users IN EXCLUSIVE MODE', + $builder->toSql() ); } @@ -389,9 +390,9 @@ public function test_lock_table_nowait() : void { $builder = lock_table('users')->exclusive()->nowait(); - $this->assertLockQuery( - $builder, - 'LOCK TABLE users IN EXCLUSIVE MODE NOWAIT' + self::assertSame( + 'LOCK TABLE users IN EXCLUSIVE MODE NOWAIT', + $builder->toSql() ); } @@ -399,9 +400,9 @@ public function test_lock_table_row_exclusive() : void { $builder = lock_table('users')->rowExclusive(); - $this->assertLockQuery( - $builder, - 'LOCK TABLE users IN ROW EXCLUSIVE MODE' + self::assertSame( + 'LOCK TABLE users IN ROW EXCLUSIVE MODE', + $builder->toSql() ); } @@ -409,9 +410,9 @@ public function test_lock_table_row_share() : void { $builder = lock_table('users')->rowShare(); - $this->assertLockQuery( - $builder, - 'LOCK TABLE users IN ROW SHARE MODE' + self::assertSame( + 'LOCK TABLE users IN ROW SHARE MODE', + $builder->toSql() ); } @@ -419,9 +420,9 @@ public function test_lock_table_share() : void { $builder = lock_table('users')->share(); - $this->assertLockQuery( - $builder, - 'LOCK TABLE users IN SHARE MODE' + self::assertSame( + 'LOCK TABLE users IN SHARE MODE', + $builder->toSql() ); } @@ -429,9 +430,9 @@ public function test_lock_table_share_row_exclusive() : void { $builder = lock_table('users')->shareRowExclusive(); - $this->assertLockQuery( - $builder, - 'LOCK TABLE users IN SHARE ROW EXCLUSIVE MODE' + self::assertSame( + 'LOCK TABLE users IN SHARE ROW EXCLUSIVE MODE', + $builder->toSql() ); } @@ -439,9 +440,9 @@ public function test_lock_table_share_update_exclusive() : void { $builder = lock_table('users')->shareUpdateExclusive(); - $this->assertLockQuery( - $builder, - 'LOCK TABLE users IN SHARE UPDATE EXCLUSIVE MODE' + self::assertSame( + 'LOCK TABLE users IN SHARE UPDATE EXCLUSIVE MODE', + $builder->toSql() ); } @@ -449,9 +450,9 @@ public function test_lock_table_with_mode_enum() : void { $builder = lock_table('users')->inMode(LockMode::EXCLUSIVE); - $this->assertLockQuery( - $builder, - 'LOCK TABLE users IN EXCLUSIVE MODE' + self::assertSame( + 'LOCK TABLE users IN EXCLUSIVE MODE', + $builder->toSql() ); } @@ -459,9 +460,9 @@ public function test_vacuum_all_tables() : void { $builder = vacuum(); - $this->assertVacuumQuery( - $builder, - 'VACUUM' + self::assertSame( + 'VACUUM', + $builder->toSql() ); } @@ -469,9 +470,9 @@ public function test_vacuum_analyze() : void { $builder = vacuum()->analyze()->tables('users'); - $this->assertVacuumQuery( - $builder, - 'VACUUM (ANALYZE) users' + self::assertSame( + 'VACUUM (ANALYZE) users', + $builder->toSql() ); } @@ -479,9 +480,9 @@ public function test_vacuum_disable_page_skipping() : void { $builder = vacuum()->disablePageSkipping()->table('users'); - $this->assertVacuumQuery( - $builder, - 'VACUUM (DISABLE_PAGE_SKIPPING) users' + self::assertSame( + 'VACUUM (DISABLE_PAGE_SKIPPING) users', + $builder->toSql() ); } @@ -489,9 +490,9 @@ public function test_vacuum_freeze() : void { $builder = vacuum()->freeze()->table('users'); - $this->assertVacuumQuery( - $builder, - 'VACUUM (FREEZE) users' + self::assertSame( + 'VACUUM (FREEZE) users', + $builder->toSql() ); } @@ -499,9 +500,9 @@ public function test_vacuum_full() : void { $builder = vacuum()->full()->tables('users'); - $this->assertVacuumQuery( - $builder, - 'VACUUM (FULL) users' + self::assertSame( + 'VACUUM (FULL) users', + $builder->toSql() ); } @@ -509,9 +510,9 @@ public function test_vacuum_full_analyze_verbose() : void { $builder = vacuum()->full()->analyze()->verbose()->table('users'); - $this->assertVacuumQuery( - $builder, - 'VACUUM (FULL, VERBOSE, ANALYZE) users' + self::assertSame( + 'VACUUM (FULL, VERBOSE, ANALYZE) users', + $builder->toSql() ); } @@ -519,9 +520,9 @@ public function test_vacuum_index_cleanup_off() : void { $builder = vacuum()->indexCleanup(IndexCleanup::OFF)->table('users'); - $this->assertVacuumQuery( - $builder, - 'VACUUM (INDEX_CLEANUP OFF) users' + self::assertSame( + 'VACUUM (INDEX_CLEANUP OFF) users', + $builder->toSql() ); } @@ -529,9 +530,9 @@ public function test_vacuum_index_cleanup_on() : void { $builder = vacuum()->indexCleanup(IndexCleanup::ON)->table('users'); - $this->assertVacuumQuery( - $builder, - 'VACUUM (INDEX_CLEANUP ON) users' + self::assertSame( + 'VACUUM (INDEX_CLEANUP ON) users', + $builder->toSql() ); } @@ -539,9 +540,9 @@ public function test_vacuum_multiple_tables() : void { $builder = vacuum()->tables('users', 'orders', 'products'); - $this->assertVacuumQuery( - $builder, - 'VACUUM users, orders, products' + self::assertSame( + 'VACUUM users, orders, products', + $builder->toSql() ); } @@ -549,9 +550,9 @@ public function test_vacuum_parallel() : void { $builder = vacuum()->parallel(4)->table('users'); - $this->assertVacuumQuery( - $builder, - 'VACUUM (PARALLEL 4) users' + self::assertSame( + 'VACUUM (PARALLEL 4) users', + $builder->toSql() ); } @@ -559,9 +560,9 @@ public function test_vacuum_process_main() : void { $builder = vacuum()->processMain(true)->table('users'); - $this->assertVacuumQuery( - $builder, - 'VACUUM (PROCESS_MAIN 1) users' + self::assertSame( + 'VACUUM (PROCESS_MAIN 1) users', + $builder->toSql() ); } @@ -569,9 +570,9 @@ public function test_vacuum_process_toast() : void { $builder = vacuum()->processToast(false)->table('users'); - $this->assertVacuumQuery( - $builder, - 'VACUUM (PROCESS_TOAST 0) users' + self::assertSame( + 'VACUUM (PROCESS_TOAST 0) users', + $builder->toSql() ); } @@ -579,9 +580,9 @@ public function test_vacuum_single_table() : void { $builder = vacuum()->table('users'); - $this->assertVacuumQuery( - $builder, - 'VACUUM users' + self::assertSame( + 'VACUUM users', + $builder->toSql() ); } @@ -589,9 +590,9 @@ public function test_vacuum_skip_locked() : void { $builder = vacuum()->skipLocked()->table('users'); - $this->assertVacuumQuery( - $builder, - 'VACUUM (SKIP_LOCKED) users' + self::assertSame( + 'VACUUM (SKIP_LOCKED) users', + $builder->toSql() ); } @@ -599,9 +600,9 @@ public function test_vacuum_table_with_columns() : void { $builder = vacuum()->table('users', 'email', 'name'); - $this->assertVacuumQuery( - $builder, - 'VACUUM users(email, name)' + self::assertSame( + 'VACUUM users(email, name)', + $builder->toSql() ); } @@ -609,9 +610,9 @@ public function test_vacuum_table_with_schema() : void { $builder = vacuum()->table('public.users'); - $this->assertVacuumQuery( - $builder, - 'VACUUM public.users' + self::assertSame( + 'VACUUM public.users', + $builder->toSql() ); } @@ -619,9 +620,9 @@ public function test_vacuum_truncate_false() : void { $builder = vacuum()->truncate(false)->table('users'); - $this->assertVacuumQuery( - $builder, - 'VACUUM (TRUNCATE 0) users' + self::assertSame( + 'VACUUM (TRUNCATE 0) users', + $builder->toSql() ); } @@ -629,9 +630,9 @@ public function test_vacuum_truncate_true() : void { $builder = vacuum()->truncate(true)->table('users'); - $this->assertVacuumQuery( - $builder, - 'VACUUM (TRUNCATE 1) users' + self::assertSame( + 'VACUUM (TRUNCATE 1) users', + $builder->toSql() ); } @@ -639,9 +640,9 @@ public function test_vacuum_verbose() : void { $builder = vacuum()->verbose()->table('users'); - $this->assertVacuumQuery( - $builder, - 'VACUUM (VERBOSE) users' + self::assertSame( + 'VACUUM (VERBOSE) users', + $builder->toSql() ); } } diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/CatalogTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/CatalogTest.php new file mode 100644 index 0000000000..8a9fa9790f --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/CatalogTest.php @@ -0,0 +1,907 @@ +all()); + self::assertSame('public', $catalog->all()[0]->name); + self::assertSame('audit', $catalog->all()[1]->name); + } + + public function test_empty_catalog() : void + { + $catalog = new Catalog([]); + + self::assertSame([], $catalog->all()); + self::assertSame([], $catalog->names()); + self::assertFalse($catalog->has('anything')); + } + + public function test_empty_catalog_normalize_and_from_array() : void + { + $catalog = new Catalog([]); + + $normalized = $catalog->normalize(); + + self::assertSame(['schemas' => []], $normalized); + self::assertSame([], Catalog::fromArray($normalized)->all()); + } + + public function test_from_array_catalog_with_empty_schema() : void + { + $catalog = Catalog::fromArray([ + 'schemas' => [ + ['name' => 'public'], + ['name' => 'audit'], + ], + ]); + + self::assertSame(['public', 'audit'], $catalog->names()); + self::assertSame([], $catalog->get('public')->tables); + } + + public function test_from_array_column_with_generated_expression() : void + { + $column = Column::fromArray([ + 'name' => 'full_name', + 'type' => ['name' => 'text', 'schema' => 'pg_catalog'], + 'nullable' => true, + 'is_generated' => true, + 'generation_expression' => "first_name || ' ' || last_name", + ]); + + self::assertTrue($column->isGenerated); + self::assertSame("first_name || ' ' || last_name", $column->generationExpression); + } + + public function test_from_array_column_with_identity_always() : void + { + $column = Column::fromArray([ + 'name' => 'id', + 'type' => ['name' => 'int8', 'schema' => 'pg_catalog'], + 'nullable' => false, + 'is_identity' => true, + 'identity_generation' => 'a', + ]); + + self::assertSame('id', $column->name); + self::assertTrue($column->isIdentity); + self::assertSame(IdentityGeneration::ALWAYS, $column->identityGeneration); + } + + public function test_from_array_column_with_identity_by_default() : void + { + $column = Column::fromArray([ + 'name' => 'id', + 'type' => ['name' => 'int8', 'schema' => 'pg_catalog'], + 'nullable' => false, + 'is_identity' => true, + 'identity_generation' => 'd', + ]); + + self::assertSame(IdentityGeneration::BY_DEFAULT, $column->identityGeneration); + } + + public function test_from_array_table_with_defaults_only() : void + { + $table = Table::fromArray([ + 'name' => 'users', + 'columns' => [ + ['name' => 'id', 'type' => ['name' => 'int4', 'schema' => 'pg_catalog'], 'nullable' => false], + ], + ]); + + self::assertSame('public', $table->schema); + self::assertSame('users', $table->name); + self::assertCount(1, $table->columns); + self::assertNull($table->primaryKey); + self::assertSame([], $table->indexes); + self::assertSame([], $table->foreignKeys); + self::assertFalse($table->unlogged); + self::assertNull($table->partitionStrategy); + self::assertNull($table->tablespace); + } + + public function test_get_returns_schema_by_name() : void + { + $catalog = new Catalog([ + schema('public'), + schema('audit'), + ]); + + self::assertSame('audit', $catalog->get('audit')->name); + } + + public function test_get_throws_when_schema_not_found() : void + { + $catalog = new Catalog([schema('public')]); + + $this->expectException(SchemaException::class); + $catalog->get('missing'); + } + + public function test_has_returns_false_for_missing_schema() : void + { + $catalog = new Catalog([schema('public')]); + + self::assertFalse($catalog->has('missing')); + } + + public function test_has_returns_true_for_existing_schema() : void + { + $catalog = new Catalog([schema('public')]); + + self::assertTrue($catalog->has('public')); + } + + public function test_merge_catalog_with_empty_catalog() : void + { + $catalog = new Catalog([schema('public', tables: [ + schema_table('users', [schema_column_integer('id', nullable: false)]), + ])]); + + $result = $catalog->merge(new Catalog([])); + + self::assertSame(['public'], $result->names()); + self::assertTrue($result->get('public')->hasTable('users')); + } + + public function test_merge_catalogs_with_different_schemas() : void + { + $first = new Catalog([schema('public', tables: [ + schema_table('users', [schema_column_integer('id', nullable: false)]), + ])]); + $second = new Catalog([schema('audit', tables: [ + schema_table('logs', [schema_column_integer('id', nullable: false)]), + ])]); + + $result = $first->merge($second); + + self::assertSame(['public', 'audit'], $result->names()); + self::assertTrue($result->get('public')->hasTable('users')); + self::assertTrue($result->get('audit')->hasTable('logs')); + } + + public function test_merge_catalogs_with_mixed_schemas_and_overlapping_tables() : void + { + $first = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', nullable: false)]), + schema_table('posts', [schema_column_integer('id', nullable: false)]), + ]), + schema('audit'), + ]); + $second = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_text('name')]), + ]), + schema('reporting', tables: [ + schema_table('reports', [schema_column_integer('id', nullable: false)]), + ]), + ]); + + $result = $first->merge($second); + + self::assertSame(['public', 'audit', 'reporting'], $result->names()); + self::assertTrue($result->get('public')->hasTable('users')); + self::assertTrue($result->get('public')->hasTable('posts')); + self::assertCount(1, $result->get('public')->table('users')->columns); + self::assertSame('name', $result->get('public')->table('users')->columns[0]->name); + self::assertTrue($result->has('reporting')); + } + + public function test_merge_catalogs_with_same_schema_merges_tables() : void + { + $first = new Catalog([schema('public', tables: [ + schema_table('users', [schema_column_integer('id', nullable: false)]), + ])]); + $second = new Catalog([schema('public', tables: [ + schema_table('posts', [schema_column_integer('id', nullable: false)]), + ])]); + + $result = $first->merge($second); + + self::assertSame(['public'], $result->names()); + self::assertTrue($result->get('public')->hasTable('users')); + self::assertTrue($result->get('public')->hasTable('posts')); + } + + public function test_merge_catalogs_with_same_table_later_overrides() : void + { + $first = new Catalog([schema('public', tables: [ + schema_table('users', [schema_column_integer('id', nullable: false)]), + ])]); + $second = new Catalog([schema('public', tables: [ + schema_table('users', [ + schema_column_integer('id', nullable: false), + schema_column_varchar('email', 255, nullable: false), + ]), + ])]); + + $result = $first->merge($second); + + self::assertCount(2, $result->get('public')->table('users')->columns); + } + + public function test_merge_empty_catalog_with_catalog() : void + { + $catalog = new Catalog([schema('public', tables: [ + schema_table('users', [schema_column_integer('id', nullable: false)]), + ])]); + + $result = (new Catalog([]))->merge($catalog); + + self::assertSame(['public'], $result->names()); + self::assertTrue($result->get('public')->hasTable('users')); + } + + public function test_merge_two_empty_catalogs() : void + { + $result = (new Catalog([]))->merge(new Catalog([])); + + self::assertSame([], $result->all()); + } + + public function test_names_returns_all_schema_names() : void + { + $catalog = new Catalog([ + schema('public'), + schema('audit'), + schema('staging'), + ]); + + self::assertSame(['public', 'audit', 'staging'], $catalog->names()); + } + + public function test_normalize_and_from_array_with_all_column_types() : void + { + $columns = [ + new Column('col_varchar', ColumnType::varchar(255), true), + new Column('col_numeric', ColumnType::numeric(10, 2), false), + new Column('col_text_arr', ColumnType::array(ColumnType::text()), true), + new Column('col_custom', ColumnType::custom('my_enum', 'my_schema'), true), + new Column('col_char', ColumnType::char(10), true), + new Column('col_timestamp', ColumnType::timestamp(6), true), + new Column('col_timestamptz', ColumnType::timestamptz(3), true), + new Column('col_time', ColumnType::time(0), true), + ]; + + $table = new Table('public', 'type_test', $columns); + $catalog = new Catalog([new Schema('public', [$table])]); + + $restored = Catalog::fromArray($catalog->normalize()); + + $restoredTable = $restored->get('public')->table('type_test'); + + foreach ($columns as $i => $originalColumn) { + self::assertTrue( + $originalColumn->type->isEqual($restoredTable->columns[$i]->type), + \sprintf('Column type mismatch for %s', $originalColumn->name), + ); + } + } + + public function test_normalize_and_from_array_with_all_index_methods() : void + { + $indexes = []; + + foreach (IndexMethod::cases() as $method) { + $indexes[] = new Index('idx_' . $method->value, ['col1'], method: $method); + } + + $table = new Table( + 'public', + 'index_test', + [new Column('col1', ColumnType::text(), true)], + indexes: $indexes, + ); + + $catalog = new Catalog([new Schema('public', [$table])]); + $restored = Catalog::fromArray($catalog->normalize()); + + $restoredIndexes = $restored->get('public')->table('index_test')->indexes; + + foreach (IndexMethod::cases() as $i => $method) { + self::assertSame($method, $restoredIndexes[$i]->method); + } + } + + public function test_normalize_and_from_array_with_all_referential_actions() : void + { + $foreignKeys = []; + + foreach (ReferentialAction::cases() as $action) { + $foreignKeys[] = new ForeignKey( + 'fk_' . $action->value, + ['col1'], + 'public', + 'ref_table', + ['id'], + onUpdate: $action, + onDelete: $action, + ); + } + + $table = new Table( + 'public', + 'fk_test', + [new Column('col1', ColumnType::integer(), false)], + foreignKeys: $foreignKeys, + ); + + $catalog = new Catalog([new Schema('public', [$table])]); + $restored = Catalog::fromArray($catalog->normalize()); + + $restoredFks = $restored->get('public')->table('fk_test')->foreignKeys; + + foreach (ReferentialAction::cases() as $i => $action) { + self::assertSame($action, $restoredFks[$i]->onUpdate); + self::assertSame($action, $restoredFks[$i]->onDelete); + } + } + + public function test_normalize_and_from_array_with_all_trigger_events() : void + { + $trigger = new Trigger( + 'trigger_all_events', + 'test_table', + TriggerTiming::AFTER, + [TriggerEvent::INSERT, TriggerEvent::UPDATE, TriggerEvent::DELETE, TriggerEvent::TRUNCATE], + 'my_function', + forEachRow: true, + whenCondition: 'NEW.status IS DISTINCT FROM OLD.status', + ); + + $table = new Table( + 'public', + 'test_table', + [new Column('id', ColumnType::integer(), false)], + triggers: [$trigger], + ); + + $catalog = new Catalog([new Schema('public', [$table])]); + $restored = Catalog::fromArray($catalog->normalize()); + + $restoredTrigger = $restored->get('public')->table('test_table')->triggers[0]; + + self::assertSame( + [TriggerEvent::INSERT, TriggerEvent::UPDATE, TriggerEvent::DELETE, TriggerEvent::TRUNCATE], + $restoredTrigger->events, + ); + self::assertTrue($restoredTrigger->forEachRow); + self::assertSame('NEW.status IS DISTINCT FROM OLD.status', $restoredTrigger->whenCondition); + } + + public function test_normalize_and_from_array_with_all_trigger_timings_and_events() : void + { + $triggers = []; + + foreach (TriggerTiming::cases() as $timing) { + $triggers[] = new Trigger( + 'trigger_' . $timing->value, + 'test_table', + $timing, + [TriggerEvent::INSERT, TriggerEvent::UPDATE], + 'my_function', + ); + } + + $table = new Table( + 'public', + 'test_table', + [new Column('id', ColumnType::integer(), false)], + triggers: $triggers, + ); + + $catalog = new Catalog([new Schema('public', [$table])]); + $restored = Catalog::fromArray($catalog->normalize()); + + $restoredTriggers = $restored->get('public')->table('test_table')->triggers; + + foreach (TriggerTiming::cases() as $i => $timing) { + self::assertSame($timing, $restoredTriggers[$i]->timing); + self::assertSame([TriggerEvent::INSERT, TriggerEvent::UPDATE], $restoredTriggers[$i]->events); + } + } + + public function test_normalize_and_from_array_with_function_volatility() : void + { + $functions = []; + + foreach (FunctionVolatility::cases() as $volatility) { + $functions[] = new Func( + 'func_' . $volatility->value, + 'text', + ['text'], + 'sql', + 'SELECT $1', + volatility: $volatility, + ); + } + + $functions[] = new Func('func_no_volatility', 'void', definition: 'SELECT 1'); + + $catalog = new Catalog([new Schema('public', functions: $functions)]); + $restored = Catalog::fromArray($catalog->normalize()); + + $restoredFunctions = $restored->get('public')->functions; + + foreach (FunctionVolatility::cases() as $i => $volatility) { + self::assertSame($volatility, $restoredFunctions[$i]->volatility); + } + + self::assertNull($restoredFunctions[\count(FunctionVolatility::cases())]->volatility); + } + + public function test_normalize_and_from_array_with_partition_strategies() : void + { + $tables = []; + + foreach (PartitionStrategy::cases() as $strategy) { + $tables[] = new Table( + 'public', + 'partitioned_' . $strategy->value, + [new Column('id', ColumnType::integer(), false)], + partitionStrategy: $strategy, + partitionColumns: ['id'], + ); + } + + $catalog = new Catalog([new Schema('public', $tables)]); + $restored = Catalog::fromArray($catalog->normalize()); + + foreach (PartitionStrategy::cases() as $i => $strategy) { + self::assertSame($strategy, $restored->get('public')->tables[$i]->partitionStrategy); + self::assertSame(['id'], $restored->get('public')->tables[$i]->partitionColumns); + } + } + + public function test_normalize_and_from_array_with_schema_containing_all_object_types() : void + { + $catalog = new Catalog([ + new Schema( + 'public', + tables: [ + new Table( + 'public', + 'users', + [ + new Column('id', ColumnType::bigint(), false, isIdentity: true, identityGeneration: IdentityGeneration::ALWAYS), + new Column('email', ColumnType::varchar(255), false), + new Column('name', ColumnType::text(), true), + ], + primaryKey: new PrimaryKey(['id'], 'users_pkey'), + indexes: [ + new Index('idx_users_email', ['email'], unique: true), + ], + uniqueConstraints: [ + new UniqueConstraint(['email'], 'uq_email'), + ], + ), + ], + sequences: [ + new Sequence('users_id_seq', 'bigint', startValue: 1, incrementBy: 1), + ], + views: [ + new View('active_users', 'SELECT * FROM users WHERE active = true'), + ], + materializedViews: [ + new MaterializedView( + 'user_stats', + 'SELECT count(*) FROM users', + [new Index('idx_user_stats', ['count'])], + ), + ], + functions: [ + new Func('get_user', 'text', ['integer'], 'sql', 'SELECT name FROM users WHERE id = $1', isStrict: true, volatility: FunctionVolatility::STABLE), + ], + procedures: [ + new Procedure('cleanup', [], 'sql', 'DELETE FROM users WHERE active = false'), + ], + domains: [ + new Domain( + 'email_address', + ColumnType::varchar(255), + nullable: false, + checkConstraints: [new CheckConstraint("VALUE ~ '^.+@.+$'", 'email_format_check')], + ), + ], + extensions: [ + new Extension('uuid-ossp', '1.1'), + ], + ), + ]); + + $normalized = $catalog->normalize(); + $restored = Catalog::fromArray($normalized); + + self::assertSame(['public'], $restored->names()); + + $restoredSchema = $restored->get('public'); + + self::assertCount(1, $restoredSchema->tables); + self::assertCount(1, $restoredSchema->sequences); + self::assertCount(1, $restoredSchema->views); + self::assertCount(1, $restoredSchema->materializedViews); + self::assertCount(1, $restoredSchema->functions); + self::assertCount(1, $restoredSchema->procedures); + self::assertCount(1, $restoredSchema->domains); + self::assertCount(1, $restoredSchema->extensions); + + $restoredTable = $restoredSchema->table('users'); + self::assertCount(3, $restoredTable->columns); + self::assertSame('users_pkey', $restoredTable->primaryKey->name); + self::assertCount(1, $restoredTable->indexes); + self::assertCount(1, $restoredTable->uniqueConstraints); + + self::assertSame('users_id_seq', $restoredSchema->sequences[0]->name); + self::assertSame('active_users', $restoredSchema->views[0]->name); + self::assertSame('user_stats', $restoredSchema->materializedViews[0]->name); + self::assertSame('get_user', $restoredSchema->functions[0]->name); + self::assertSame('cleanup', $restoredSchema->procedures[0]->name); + self::assertSame('email_address', $restoredSchema->domains[0]->name); + self::assertSame('uuid-ossp', $restoredSchema->extensions[0]->name); + self::assertSame('1.1', $restoredSchema->extensions[0]->version); + } + + public function test_normalize_and_from_array_with_table_all_constraints() : void + { + $table = new Table( + 'public', + 'orders', + [ + new Column('id', ColumnType::integer(), false), + new Column('user_id', ColumnType::integer(), false), + new Column('amount', ColumnType::numeric(10, 2), false), + new Column('status', ColumnType::text(), false, default: "'pending'"), + ], + primaryKey: new PrimaryKey(['id'], 'orders_pkey'), + indexes: [ + new Index('idx_orders_user', ['user_id'], method: IndexMethod::BTREE), + new Index('idx_orders_amount', ['amount'], method: IndexMethod::BRIN), + ], + foreignKeys: [ + new ForeignKey( + 'fk_orders_user', + ['user_id'], + 'public', + 'users', + ['id'], + onUpdate: ReferentialAction::CASCADE, + onDelete: ReferentialAction::SET_NULL, + deferrable: true, + initiallyDeferred: true, + ), + ], + uniqueConstraints: [ + new UniqueConstraint(['id', 'user_id'], 'uq_order_user', nullsNotDistinct: true), + ], + checkConstraints: [ + new CheckConstraint('amount > 0', 'chk_positive_amount', noInherit: true), + ], + excludeConstraints: [ + new ExcludeConstraint('USING gist (daterange(start_date, end_date) WITH &&)', 'excl_date_range'), + ], + triggers: [ + new Trigger( + 'trg_orders_audit', + 'orders', + TriggerTiming::AFTER, + [TriggerEvent::INSERT, TriggerEvent::UPDATE, TriggerEvent::DELETE], + 'audit_function', + forEachRow: true, + whenCondition: 'NEW.amount > 1000', + ), + ], + unlogged: true, + tablespace: 'fast_storage', + ); + + $catalog = new Catalog([new Schema('public', [$table])]); + $normalized = $catalog->normalize(); + $restored = Catalog::fromArray($normalized); + + $restoredTable = $restored->get('public')->table('orders'); + + self::assertSame('orders_pkey', $restoredTable->primaryKey->name); + self::assertSame(['id'], $restoredTable->primaryKey->columns); + + self::assertCount(2, $restoredTable->indexes); + self::assertSame(IndexMethod::BRIN, $restoredTable->indexes[1]->method); + + self::assertCount(1, $restoredTable->foreignKeys); + self::assertSame(ReferentialAction::CASCADE, $restoredTable->foreignKeys[0]->onUpdate); + self::assertSame(ReferentialAction::SET_NULL, $restoredTable->foreignKeys[0]->onDelete); + self::assertTrue($restoredTable->foreignKeys[0]->deferrable); + self::assertTrue($restoredTable->foreignKeys[0]->initiallyDeferred); + + self::assertCount(1, $restoredTable->uniqueConstraints); + self::assertTrue($restoredTable->uniqueConstraints[0]->nullsNotDistinct); + + self::assertCount(1, $restoredTable->checkConstraints); + self::assertTrue($restoredTable->checkConstraints[0]->noInherit); + self::assertSame('amount > 0', $restoredTable->checkConstraints[0]->expression); + + self::assertCount(1, $restoredTable->excludeConstraints); + self::assertSame('excl_date_range', $restoredTable->excludeConstraints[0]->name); + + self::assertCount(1, $restoredTable->triggers); + self::assertSame(TriggerTiming::AFTER, $restoredTable->triggers[0]->timing); + self::assertTrue($restoredTable->triggers[0]->forEachRow); + self::assertSame('NEW.amount > 1000', $restoredTable->triggers[0]->whenCondition); + + self::assertTrue($restoredTable->unlogged); + self::assertSame('fast_storage', $restoredTable->tablespace); + } + + public function test_normalize_and_from_array_with_table_inherits() : void + { + $table = new Table( + 'public', + 'child_table', + [new Column('id', ColumnType::integer(), false)], + inherits: ['parent_table_1', 'parent_table_2'], + ); + + $catalog = new Catalog([new Schema('public', [$table])]); + $restored = Catalog::fromArray($catalog->normalize()); + + self::assertSame(['parent_table_1', 'parent_table_2'], $restored->get('public')->table('child_table')->inherits); + } + + public function test_normalize_produces_expected_structure() : void + { + $catalog = new Catalog([ + new Schema('public', [ + new Table( + 'public', + 'simple', + [new Column('id', ColumnType::integer(), false)], + ), + ]), + ]); + + $normalized = $catalog->normalize(); + + self::assertArrayHasKey('schemas', $normalized); + self::assertCount(1, $normalized['schemas']); + self::assertSame('public', $normalized['schemas'][0]['name']); + self::assertArrayHasKey('tables', $normalized['schemas'][0]); + self::assertSame('simple', $normalized['schemas'][0]['tables'][0]['name']); + self::assertSame('public', $normalized['schemas'][0]['tables'][0]['schema']); + self::assertArrayHasKey('columns', $normalized['schemas'][0]['tables'][0]); + self::assertSame('id', $normalized['schemas'][0]['tables'][0]['columns'][0]['name']); + self::assertSame('int4', $normalized['schemas'][0]['tables'][0]['columns'][0]['type']['name']); + } + + public function test_round_trip_preserves_column_default_value() : void + { + $table = new Table( + 'public', + 'defaults', + [ + new Column('status', ColumnType::text(), false, default: "'active'"), + new Column('count', ColumnType::integer(), false, default: '0'), + new Column('no_default', ColumnType::text(), true), + ], + ); + + $catalog = new Catalog([new Schema('public', [$table])]); + $restored = Catalog::fromArray($catalog->normalize()); + + $restoredTable = $restored->get('public')->table('defaults'); + self::assertSame("'active'", $restoredTable->column('status')->default); + self::assertSame('0', $restoredTable->column('count')->default); + self::assertNull($restoredTable->column('no_default')->default); + } + + public function test_round_trip_preserves_domain_with_check_constraints() : void + { + $domain = new Domain( + 'positive_int', + ColumnType::integer(), + nullable: false, + default: '0', + checkConstraints: [ + new CheckConstraint('VALUE > 0', 'chk_positive'), + new CheckConstraint('VALUE < 1000000', 'chk_max'), + ], + ); + + $catalog = new Catalog([new Schema('public', domains: [$domain])]); + $restored = Catalog::fromArray($catalog->normalize()); + + $restoredDomain = $restored->get('public')->domains[0]; + self::assertSame('positive_int', $restoredDomain->name); + self::assertFalse($restoredDomain->nullable); + self::assertSame('0', $restoredDomain->default); + self::assertCount(2, $restoredDomain->checkConstraints); + self::assertSame('VALUE > 0', $restoredDomain->checkConstraints[0]->expression); + self::assertSame('chk_positive', $restoredDomain->checkConstraints[0]->name); + } + + public function test_round_trip_preserves_index_predicate() : void + { + $index = new Index('idx_partial', ['status'], predicate: "status = 'active'"); + + $table = new Table( + 'public', + 'test', + [new Column('status', ColumnType::text(), true)], + indexes: [$index], + ); + + $catalog = new Catalog([new Schema('public', [$table])]); + $restored = Catalog::fromArray($catalog->normalize()); + + self::assertSame("status = 'active'", $restored->get('public')->table('test')->indexes[0]->predicate); + } + + public function test_round_trip_preserves_materialized_view_indexes() : void + { + $mv = new MaterializedView( + 'stats', + 'SELECT count(*) as cnt FROM users', + [ + new Index('idx_stats_cnt', ['cnt'], unique: true, method: IndexMethod::BTREE), + ], + ); + + $catalog = new Catalog([new Schema('public', materializedViews: [$mv])]); + $restored = Catalog::fromArray($catalog->normalize()); + + $restoredMv = $restored->get('public')->materializedViews[0]; + self::assertSame('stats', $restoredMv->name); + self::assertCount(1, $restoredMv->indexes); + self::assertTrue($restoredMv->indexes[0]->unique); + self::assertSame('idx_stats_cnt', $restoredMv->indexes[0]->name); + } + + public function test_round_trip_preserves_multiple_schemas() : void + { + $catalog = new Catalog([ + new Schema('public', [ + new Table('public', 'users', [new Column('id', ColumnType::integer(), false)]), + ]), + new Schema('audit', [ + new Table('audit', 'logs', [new Column('id', ColumnType::bigint(), false)]), + ]), + new Schema('staging'), + ]); + + $restored = Catalog::fromArray($catalog->normalize()); + + self::assertSame(['public', 'audit', 'staging'], $restored->names()); + self::assertTrue($restored->get('public')->hasTable('users')); + self::assertTrue($restored->get('audit')->hasTable('logs')); + self::assertSame([], $restored->get('staging')->tables); + } + + public function test_round_trip_preserves_nullable_fields_as_null() : void + { + $table = new Table( + 'public', + 'nullable_test', + [ + new Column('id', ColumnType::integer(), false), + ], + ); + + $catalog = new Catalog([new Schema('public', [$table])]); + $restored = Catalog::fromArray($catalog->normalize()); + + $restoredTable = $restored->get('public')->table('nullable_test'); + self::assertNull($restoredTable->primaryKey); + self::assertNull($restoredTable->partitionStrategy); + self::assertNull($restoredTable->tablespace); + self::assertNull($restoredTable->columns[0]->default); + self::assertNull($restoredTable->columns[0]->identityGeneration); + self::assertNull($restoredTable->columns[0]->generationExpression); + self::assertNull($restoredTable->columns[0]->ordinalPosition); + } + + public function test_round_trip_preserves_procedure() : void + { + $procedure = new Procedure( + 'cleanup_proc', + ['integer', 'text'], + 'plpgsql', + 'BEGIN DELETE FROM logs WHERE age > $1; END;', + ); + + $catalog = new Catalog([new Schema('public', procedures: [$procedure])]); + $restored = Catalog::fromArray($catalog->normalize()); + + $restoredProc = $restored->get('public')->procedures[0]; + self::assertSame('cleanup_proc', $restoredProc->name); + self::assertSame(['integer', 'text'], $restoredProc->argumentTypes); + self::assertSame('plpgsql', $restoredProc->language); + self::assertSame('BEGIN DELETE FROM logs WHERE age > $1; END;', $restoredProc->definition); + } + + public function test_round_trip_preserves_sequence_all_fields() : void + { + $sequence = new Sequence( + 'custom_seq', + 'integer', + startValue: 100, + minValue: 1, + maxValue: 999999, + incrementBy: 5, + cycle: true, + cacheValue: 10, + ownedByTable: 'users', + ownedByColumn: 'id', + ); + + $catalog = new Catalog([new Schema('public', sequences: [$sequence])]); + $restored = Catalog::fromArray($catalog->normalize()); + + $restoredSeq = $restored->get('public')->sequences[0]; + self::assertSame('custom_seq', $restoredSeq->name); + self::assertSame('integer', $restoredSeq->dataType); + self::assertSame(100, $restoredSeq->startValue); + self::assertSame(1, $restoredSeq->minValue); + self::assertSame(999999, $restoredSeq->maxValue); + self::assertSame(5, $restoredSeq->incrementBy); + self::assertTrue($restoredSeq->cycle); + self::assertSame(10, $restoredSeq->cacheValue); + self::assertSame('users', $restoredSeq->ownedByTable); + self::assertSame('id', $restoredSeq->ownedByColumn); + } + + public function test_round_trip_preserves_strict_function() : void + { + $func = new Func( + 'my_func', + 'boolean', + ['text', 'integer'], + 'plpgsql', + 'BEGIN RETURN true; END;', + isStrict: true, + volatility: FunctionVolatility::IMMUTABLE, + ); + + $catalog = new Catalog([new Schema('public', functions: [$func])]); + $restored = Catalog::fromArray($catalog->normalize()); + + $restoredFunc = $restored->get('public')->functions[0]; + self::assertSame('my_func', $restoredFunc->name); + self::assertSame('boolean', $restoredFunc->returnType); + self::assertSame(['text', 'integer'], $restoredFunc->argumentTypes); + self::assertSame('plpgsql', $restoredFunc->language); + self::assertTrue($restoredFunc->isStrict); + self::assertSame(FunctionVolatility::IMMUTABLE, $restoredFunc->volatility); + } + + public function test_round_trip_preserves_view() : void + { + $view = new View('my_view', 'SELECT id, name FROM users', isUpdatable: true); + + $catalog = new Catalog([new Schema('public', views: [$view])]); + $restored = Catalog::fromArray($catalog->normalize()); + + $restoredView = $restored->get('public')->views[0]; + self::assertSame('my_view', $restoredView->name); + self::assertSame('SELECT id, name FROM users', $restoredView->definition); + self::assertTrue($restoredView->isUpdatable); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/ChainCatalogProviderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/ChainCatalogProviderTest.php new file mode 100644 index 0000000000..e23faaf3c5 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/ChainCatalogProviderTest.php @@ -0,0 +1,99 @@ +get()->all()); + } + + public function test_single_provider_returns_its_catalog_unchanged() : void + { + $catalog = new Catalog([schema('public', tables: [ + schema_table('users', [schema_column_integer('id', nullable: false)]), + ])]); + + $provider = chain_catalog_provider(manual_catalog_provider($catalog)); + + $result = $provider->get(); + self::assertSame(['public'], $result->names()); + self::assertTrue($result->get('public')->hasTable('users')); + } + + public function test_three_providers_merged_in_order() : void + { + $first = new Catalog([schema('public', tables: [ + schema_table('users', [schema_column_integer('id', nullable: false)]), + ])]); + $second = new Catalog([schema('public', tables: [ + schema_table('posts', [schema_column_integer('id', nullable: false)]), + ])]); + $third = new Catalog([schema('public', tables: [ + schema_table('users', [schema_column_text('name')]), + ])]); + + $provider = chain_catalog_provider( + manual_catalog_provider($first), + manual_catalog_provider($second), + manual_catalog_provider($third), + ); + + $result = $provider->get(); + self::assertTrue($result->get('public')->hasTable('users')); + self::assertTrue($result->get('public')->hasTable('posts')); + self::assertCount(1, $result->get('public')->table('users')->columns); + self::assertSame('name', $result->get('public')->table('users')->columns[0]->name); + } + + public function test_two_providers_with_distinct_schemas_are_combined() : void + { + $first = new Catalog([schema('public', tables: [ + schema_table('users', [schema_column_integer('id', nullable: false)]), + ])]); + $second = new Catalog([schema('audit', tables: [ + schema_table('logs', [schema_column_integer('id', nullable: false)]), + ])]); + + $provider = chain_catalog_provider( + manual_catalog_provider($first), + manual_catalog_provider($second), + ); + + $result = $provider->get(); + self::assertSame(['public', 'audit'], $result->names()); + self::assertTrue($result->get('public')->hasTable('users')); + self::assertTrue($result->get('audit')->hasTable('logs')); + } + + public function test_two_providers_with_overlapping_table_later_wins() : void + { + $first = new Catalog([schema('public', tables: [ + schema_table('users', [schema_column_integer('id', nullable: false)]), + ])]); + $second = new Catalog([schema('public', tables: [ + schema_table('users', [ + schema_column_integer('id', nullable: false), + schema_column_varchar('email', 255, nullable: false), + ]), + ])]); + + $provider = chain_catalog_provider( + manual_catalog_provider($first), + manual_catalog_provider($second), + ); + + $result = $provider->get(); + self::assertCount(2, $result->get('public')->table('users')->columns); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/ColumnTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/ColumnTest.php new file mode 100644 index 0000000000..f36961e32d --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/ColumnTest.php @@ -0,0 +1,141 @@ +name); + self::assertFalse($column->nullable); + self::assertNull($column->default); + } + + public function test_column_generated() : void + { + $column = schema_column('full_name', column_type_text(), isGenerated: true, generationExpression: "first_name || ' ' || last_name"); + + self::assertTrue($column->isGenerated); + self::assertSame("first_name || ' ' || last_name", $column->generationExpression); + } + + public function test_column_identity() : void + { + $column = schema_column('id', column_type_integer(), nullable: false, isIdentity: true, identityGeneration: IdentityGeneration::ALWAYS); + + self::assertTrue($column->isIdentity); + self::assertSame(IdentityGeneration::ALWAYS, $column->identityGeneration); + } + + public function test_column_with_default() : void + { + $column = schema_column('name', column_type_varchar(255), default: "'unknown'"); + + self::assertSame("'unknown'", $column->default); + } + + public function test_is_equal_for_identical_columns() : void + { + $a = schema_column('id', column_type_integer(), nullable: false); + $b = schema_column('id', column_type_integer(), nullable: false); + + self::assertTrue($a->isEqual($b)); + } + + public function test_is_equal_returns_false_when_default_differs() : void + { + $a = schema_column('name', column_type_text(), default: "'hello'"); + $b = schema_column('name', column_type_text(), default: "'world'"); + + self::assertFalse($a->isEqual($b)); + } + + public function test_is_equal_returns_false_when_generation_expression_differs() : void + { + $a = schema_column('full_name', column_type_text(), isGenerated: true, generationExpression: 'first || last'); + $b = schema_column('full_name', column_type_text(), isGenerated: true, generationExpression: "first || ' ' || last"); + + self::assertFalse($a->isEqual($b)); + } + + public function test_is_equal_returns_false_when_identity_differs() : void + { + $a = schema_column('id', column_type_integer(), nullable: false, isIdentity: true, identityGeneration: IdentityGeneration::ALWAYS); + $b = schema_column('id', column_type_integer(), nullable: false, isIdentity: false); + + self::assertFalse($a->isEqual($b)); + } + + public function test_is_equal_returns_false_when_name_differs() : void + { + $a = schema_column('id', column_type_integer(), nullable: false); + $b = schema_column('user_id', column_type_integer(), nullable: false); + + self::assertFalse($a->isEqual($b)); + } + + public function test_is_equal_returns_false_when_nullable_differs() : void + { + $a = schema_column('name', column_type_text(), nullable: false); + $b = schema_column('name', column_type_text(), nullable: true); + + self::assertFalse($a->isEqual($b)); + } + + public function test_is_equal_returns_false_when_type_differs() : void + { + $a = schema_column('name', column_type_text(), nullable: false); + $b = schema_column('name', column_type_varchar(255), nullable: false); + + self::assertFalse($a->isEqual($b)); + } + + public function test_is_equal_structure_ignores_ordinal_position() : void + { + $a = schema_column('id', column_type_integer(), nullable: false, ordinalPosition: 1); + $b = schema_column('id', column_type_integer(), nullable: false, ordinalPosition: 5); + + self::assertTrue($a->isEqualStructure($b)); + } + + public function test_is_equal_structure_returns_false_when_default_differs() : void + { + $a = schema_column('name', column_type_text(), default: "'a'"); + $b = schema_column('name', column_type_text(), default: "'b'"); + + self::assertFalse($a->isEqualStructure($b)); + } + + public function test_is_equal_structure_returns_false_when_nullable_differs() : void + { + $a = schema_column('name', column_type_text(), nullable: false); + $b = schema_column('name', column_type_text(), nullable: true); + + self::assertFalse($a->isEqualStructure($b)); + } + + public function test_is_equal_structure_returns_false_when_type_differs() : void + { + $a = schema_column('name', column_type_text(), nullable: false); + $b = schema_column('name', column_type_varchar(255), nullable: false); + + self::assertFalse($a->isEqualStructure($b)); + } + + public function test_is_equal_structure_returns_true_when_only_name_differs() : void + { + $a = schema_column('id', column_type_integer(), nullable: false); + $b = schema_column('user_id', column_type_integer(), nullable: false); + + self::assertTrue($a->isEqualStructure($b)); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Constraint/CheckConstraintTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Constraint/CheckConstraintTest.php new file mode 100644 index 0000000000..3d04024f9b --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Constraint/CheckConstraintTest.php @@ -0,0 +1,91 @@ + 0'); + + self::assertSame('age > 0', $check->expression); + self::assertNull($check->name); + self::assertFalse($check->noInherit); + } + + public function test_check_constraint_no_inherit() : void + { + $check = schema_check('age > 0', noInherit: true); + + self::assertTrue($check->noInherit); + } + + public function test_check_constraint_with_name() : void + { + $check = schema_check('age > 0', 'chk_positive_age'); + + self::assertSame('chk_positive_age', $check->name); + } + + public function test_is_equal_for_identical_constraints() : void + { + $a = schema_check('age > 0', 'chk_age', noInherit: true); + $b = schema_check('age > 0', 'chk_age', noInherit: true); + + self::assertTrue($a->isEqual($b)); + } + + public function test_is_equal_returns_false_when_expression_differs() : void + { + $a = schema_check('age > 0', 'chk_age'); + $b = schema_check('age >= 0', 'chk_age'); + + self::assertFalse($a->isEqual($b)); + } + + public function test_is_equal_returns_false_when_name_differs() : void + { + $a = schema_check('age > 0', 'chk_a'); + $b = schema_check('age > 0', 'chk_b'); + + self::assertFalse($a->isEqual($b)); + } + + public function test_is_equal_returns_false_when_no_inherit_differs() : void + { + $a = schema_check('age > 0', 'chk_age', noInherit: true); + $b = schema_check('age > 0', 'chk_age', noInherit: false); + + self::assertFalse($a->isEqual($b)); + } + + public function test_is_equal_structure_returns_false_when_expression_differs() : void + { + $a = schema_check('age > 0'); + $b = schema_check('age >= 18'); + + self::assertFalse($a->isEqualStructure($b)); + } + + public function test_is_equal_structure_returns_false_when_no_inherit_differs() : void + { + $a = schema_check('age > 0', noInherit: true); + $b = schema_check('age > 0', noInherit: false); + + self::assertFalse($a->isEqualStructure($b)); + } + + public function test_is_equal_structure_returns_true_when_only_name_differs() : void + { + $a = schema_check('age > 0', 'chk_a', noInherit: true); + $b = schema_check('age > 0', 'chk_b', noInherit: true); + + self::assertTrue($a->isEqualStructure($b)); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Constraint/ExcludeConstraintTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Constraint/ExcludeConstraintTest.php new file mode 100644 index 0000000000..e172b07dc3 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Constraint/ExcludeConstraintTest.php @@ -0,0 +1,67 @@ +definition); + self::assertNull($exclude->name); + } + + public function test_exclude_constraint_with_name() : void + { + $exclude = schema_exclude('USING gist (tsrange WITH &&)', 'excl_no_overlap'); + + self::assertSame('excl_no_overlap', $exclude->name); + } + + public function test_is_equal_for_identical_constraints() : void + { + $a = schema_exclude('USING gist (tsrange WITH &&)', 'excl_overlap'); + $b = schema_exclude('USING gist (tsrange WITH &&)', 'excl_overlap'); + + self::assertTrue($a->isEqual($b)); + } + + public function test_is_equal_returns_false_when_definition_differs() : void + { + $a = schema_exclude('USING gist (tsrange WITH &&)', 'excl_overlap'); + $b = schema_exclude('USING gist (daterange WITH &&)', 'excl_overlap'); + + self::assertFalse($a->isEqual($b)); + } + + public function test_is_equal_returns_false_when_name_differs() : void + { + $a = schema_exclude('USING gist (tsrange WITH &&)', 'excl_a'); + $b = schema_exclude('USING gist (tsrange WITH &&)', 'excl_b'); + + self::assertFalse($a->isEqual($b)); + } + + public function test_is_equal_structure_returns_false_when_definition_differs() : void + { + $a = schema_exclude('USING gist (tsrange WITH &&)'); + $b = schema_exclude('USING gist (daterange WITH &&)'); + + self::assertFalse($a->isEqualStructure($b)); + } + + public function test_is_equal_structure_returns_true_when_only_name_differs() : void + { + $a = schema_exclude('USING gist (tsrange WITH &&)', 'excl_a'); + $b = schema_exclude('USING gist (tsrange WITH &&)', 'excl_b'); + + self::assertTrue($a->isEqualStructure($b)); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Constraint/ForeignKeyTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Constraint/ForeignKeyTest.php new file mode 100644 index 0000000000..ab57aa55e4 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Constraint/ForeignKeyTest.php @@ -0,0 +1,120 @@ +columns); + self::assertSame('users', $fk->referenceTable); + self::assertSame(['id'], $fk->referenceColumns); + self::assertSame('public', $fk->referenceSchema); + self::assertNull($fk->name); + } + + public function test_foreign_key_deferrable() : void + { + $fk = schema_foreign_key(['user_id'], 'users', ['id'], deferrable: true, initiallyDeferred: true); + + self::assertTrue($fk->deferrable); + self::assertTrue($fk->initiallyDeferred); + } + + public function test_foreign_key_with_actions() : void + { + $fk = schema_foreign_key(['user_id'], 'users', ['id'], onDelete: ReferentialAction::CASCADE, onUpdate: ReferentialAction::CASCADE); + + self::assertSame(ReferentialAction::CASCADE, $fk->onDelete); + self::assertSame(ReferentialAction::CASCADE, $fk->onUpdate); + } + + public function test_is_equal_for_identical_foreign_keys() : void + { + $a = schema_foreign_key(['user_id'], 'users', ['id'], name: 'fk_orders_user', onDelete: ReferentialAction::CASCADE); + $b = schema_foreign_key(['user_id'], 'users', ['id'], name: 'fk_orders_user', onDelete: ReferentialAction::CASCADE); + + self::assertTrue($a->isEqual($b)); + } + + public function test_is_equal_returns_false_when_columns_differ() : void + { + $a = schema_foreign_key(['user_id'], 'users', ['id'], name: 'fk_orders'); + $b = schema_foreign_key(['account_id'], 'users', ['id'], name: 'fk_orders'); + + self::assertFalse($a->isEqual($b)); + } + + public function test_is_equal_returns_false_when_name_differs() : void + { + $a = schema_foreign_key(['user_id'], 'users', ['id'], name: 'fk_a'); + $b = schema_foreign_key(['user_id'], 'users', ['id'], name: 'fk_b'); + + self::assertFalse($a->isEqual($b)); + } + + public function test_is_equal_returns_false_when_on_delete_differs() : void + { + $a = schema_foreign_key(['user_id'], 'users', ['id'], name: 'fk_orders', onDelete: ReferentialAction::CASCADE); + $b = schema_foreign_key(['user_id'], 'users', ['id'], name: 'fk_orders', onDelete: ReferentialAction::RESTRICT); + + self::assertFalse($a->isEqual($b)); + } + + public function test_is_equal_returns_false_when_reference_table_differs() : void + { + $a = schema_foreign_key(['user_id'], 'users', ['id'], name: 'fk_orders'); + $b = schema_foreign_key(['user_id'], 'accounts', ['id'], name: 'fk_orders'); + + self::assertFalse($a->isEqual($b)); + } + + public function test_is_equal_structure_returns_false_when_deferrable_differs() : void + { + $a = schema_foreign_key(['user_id'], 'users', ['id'], deferrable: true); + $b = schema_foreign_key(['user_id'], 'users', ['id'], deferrable: false); + + self::assertFalse($a->isEqualStructure($b)); + } + + public function test_is_equal_structure_returns_false_when_initially_deferred_differs() : void + { + $a = schema_foreign_key(['user_id'], 'users', ['id'], deferrable: true, initiallyDeferred: true); + $b = schema_foreign_key(['user_id'], 'users', ['id'], deferrable: true, initiallyDeferred: false); + + self::assertFalse($a->isEqualStructure($b)); + } + + public function test_is_equal_structure_returns_false_when_reference_columns_differ() : void + { + $a = schema_foreign_key(['user_id'], 'users', ['id']); + $b = schema_foreign_key(['user_id'], 'users', ['uuid']); + + self::assertFalse($a->isEqualStructure($b)); + } + + public function test_is_equal_structure_returns_false_when_reference_schema_differs() : void + { + $a = schema_foreign_key(['user_id'], 'users', ['id'], referenceSchema: 'public'); + $b = schema_foreign_key(['user_id'], 'users', ['id'], referenceSchema: 'other'); + + self::assertFalse($a->isEqualStructure($b)); + } + + public function test_is_equal_structure_returns_true_when_only_name_differs() : void + { + $a = schema_foreign_key(['user_id'], 'users', ['id'], name: 'fk_a', onDelete: ReferentialAction::CASCADE, deferrable: true); + $b = schema_foreign_key(['user_id'], 'users', ['id'], name: 'fk_b', onDelete: ReferentialAction::CASCADE, deferrable: true); + + self::assertTrue($a->isEqualStructure($b)); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Constraint/PrimaryKeyTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Constraint/PrimaryKeyTest.php new file mode 100644 index 0000000000..781c490b84 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Constraint/PrimaryKeyTest.php @@ -0,0 +1,76 @@ +isEqual($b)); + } + + public function test_is_equal_returns_false_when_columns_differ() : void + { + $a = schema_primary_key(['id'], 'pk_users'); + $b = schema_primary_key(['id', 'tenant_id'], 'pk_users'); + + self::assertFalse($a->isEqual($b)); + } + + public function test_is_equal_returns_false_when_name_differs() : void + { + $a = schema_primary_key(['id'], 'pk_a'); + $b = schema_primary_key(['id'], 'pk_b'); + + self::assertFalse($a->isEqual($b)); + } + + public function test_is_equal_structure_returns_false_when_columns_differ() : void + { + $a = schema_primary_key(['id']); + $b = schema_primary_key(['user_id']); + + self::assertFalse($a->isEqualStructure($b)); + } + + public function test_is_equal_structure_returns_true_for_columns_in_different_order() : void + { + $a = schema_primary_key(['id', 'tenant_id'], 'pk_users'); + $b = schema_primary_key(['tenant_id', 'id'], 'pk_users'); + + self::assertTrue($a->isEqualStructure($b)); + } + + public function test_is_equal_structure_returns_true_when_only_name_differs() : void + { + $a = schema_primary_key(['id', 'tenant_id'], 'pk_a'); + $b = schema_primary_key(['id', 'tenant_id'], 'pk_b'); + + self::assertTrue($a->isEqualStructure($b)); + } + + public function test_primary_key_construction() : void + { + $pk = schema_primary_key(['id']); + + self::assertSame(['id'], $pk->columns); + self::assertNull($pk->name); + } + + public function test_primary_key_with_name() : void + { + $pk = schema_primary_key(['id', 'tenant_id'], 'pk_users'); + + self::assertSame(['id', 'tenant_id'], $pk->columns); + self::assertSame('pk_users', $pk->name); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Constraint/UniqueConstraintTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Constraint/UniqueConstraintTest.php new file mode 100644 index 0000000000..a5f95280b8 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Constraint/UniqueConstraintTest.php @@ -0,0 +1,100 @@ +isEqual($b)); + } + + public function test_is_equal_returns_false_when_columns_differ() : void + { + $a = schema_unique(['email'], 'uq_users'); + $b = schema_unique(['username'], 'uq_users'); + + self::assertFalse($a->isEqual($b)); + } + + public function test_is_equal_returns_false_when_name_differs() : void + { + $a = schema_unique(['email'], 'uq_a'); + $b = schema_unique(['email'], 'uq_b'); + + self::assertFalse($a->isEqual($b)); + } + + public function test_is_equal_returns_false_when_nulls_not_distinct_differs() : void + { + $a = schema_unique(['email'], 'uq_email', nullsNotDistinct: true); + $b = schema_unique(['email'], 'uq_email', nullsNotDistinct: false); + + self::assertFalse($a->isEqual($b)); + } + + public function test_is_equal_structure_returns_false_when_columns_differ() : void + { + $a = schema_unique(['email']); + $b = schema_unique(['username']); + + self::assertFalse($a->isEqualStructure($b)); + } + + public function test_is_equal_structure_returns_false_when_nulls_not_distinct_differs() : void + { + $a = schema_unique(['email'], nullsNotDistinct: true); + $b = schema_unique(['email'], nullsNotDistinct: false); + + self::assertFalse($a->isEqualStructure($b)); + } + + public function test_is_equal_structure_returns_true_for_columns_in_different_order() : void + { + $a = schema_unique(['email', 'tenant_id'], 'uq_users'); + $b = schema_unique(['tenant_id', 'email'], 'uq_users'); + + self::assertTrue($a->isEqualStructure($b)); + } + + public function test_is_equal_structure_returns_true_when_only_name_differs() : void + { + $a = schema_unique(['email', 'tenant_id'], 'uq_a', nullsNotDistinct: true); + $b = schema_unique(['email', 'tenant_id'], 'uq_b', nullsNotDistinct: true); + + self::assertTrue($a->isEqualStructure($b)); + } + + public function test_unique_constraint_construction() : void + { + $unique = schema_unique(['email']); + + self::assertSame(['email'], $unique->columns); + self::assertNull($unique->name); + self::assertFalse($unique->nullsNotDistinct); + } + + public function test_unique_constraint_nulls_not_distinct() : void + { + $unique = schema_unique(['email'], nullsNotDistinct: true); + + self::assertTrue($unique->nullsNotDistinct); + } + + public function test_unique_constraint_with_name() : void + { + $unique = schema_unique(['email', 'tenant_id'], 'uq_users_email_tenant'); + + self::assertSame(['email', 'tenant_id'], $unique->columns); + self::assertSame('uq_users_email_tenant', $unique->name); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/CatalogComparatorTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/CatalogComparatorTest.php new file mode 100644 index 0000000000..aceed0341b --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/CatalogComparatorTest.php @@ -0,0 +1,2233 @@ +compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertCount(1, $tableDiff->addedColumns); + self::assertSame('email', $tableDiff->addedColumns[0]->name); + } + + public function test_added_index_detected() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false), schema_column_text('email')]), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false), schema_column_text('email')], indexes: [ + schema_index('idx_email', ['email']), + ]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertCount(1, $tableDiff->addedIndexes); + self::assertSame('idx_email', $tableDiff->addedIndexes[0]->name); + } + + public function test_added_schema_detected() : void + { + $source = new Catalog([schema('public')]); + $target = new Catalog([schema('public'), schema('audit')]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->addedSchemas); + self::assertSame('audit', $diff->addedSchemas[0]->name); + self::assertCount(0, $diff->removedSchemas); + } + + public function test_added_table_detected() : void + { + $source = new Catalog([schema('public')]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false)]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->modifiedSchemas); + self::assertCount(1, $diff->modifiedSchemas[0]->addedTables); + self::assertSame('users', $diff->modifiedSchemas[0]->addedTables[0]->name); + } + + public function test_ambiguous_column_rename_resolved_by_similarity() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('users', [ + schema_column_integer('id', false), + schema_column_text('first_name'), + schema_column_text('last_name'), + ]), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('users', [ + schema_column_integer('id', false), + schema_column_text('full_name'), + ]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertCount(0, $tableDiff->addedColumns); + self::assertCount(1, $tableDiff->removedColumns); + self::assertSame('first_name', $tableDiff->removedColumns[0]->name); + self::assertCount(1, $tableDiff->modifiedColumns); + self::assertTrue($tableDiff->modifiedColumns[0]->hasNameChanged()); + self::assertSame('last_name', $tableDiff->modifiedColumns[0]->source->name); + self::assertSame('full_name', $tableDiff->modifiedColumns[0]->target->name); + } + + public function test_ambiguous_index_rename_resolved_by_similarity() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false), schema_column_text('email')], indexes: [ + schema_index('idx_email_a', ['email']), + schema_index('idx_email_b', ['email']), + ]), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false), schema_column_text('email')], indexes: [ + schema_index('idx_email_c', ['email']), + ]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertCount(0, $tableDiff->addedIndexes); + self::assertCount(1, $tableDiff->removedIndexes); + self::assertCount(1, $tableDiff->renamedIndexes); + } + + public function test_both_empty_catalogs_produce_empty_diff() : void + { + $source = new Catalog([]); + $target = new Catalog([]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertTrue($diff->isEmpty()); + } + + public function test_both_empty_schemas_produce_empty_diff() : void + { + $source = new Catalog([schema('public')]); + $target = new Catalog([schema('public')]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertTrue($diff->isEmpty()); + } + + public function test_check_constraint_added() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('age')]), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('age')], checkConstraints: [ + schema_check('age > 0', 'chk_age_positive'), + ]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertCount(1, $tableDiff->addedCheckConstraints); + self::assertSame('age > 0', $tableDiff->addedCheckConstraints[0]->expression); + } + + public function test_check_constraint_modified_treated_as_drop_and_add() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('age')], checkConstraints: [ + schema_check('age > 0', 'chk_age'), + ]), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('age')], checkConstraints: [ + schema_check('age > 18', 'chk_age'), + ]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertCount(1, $tableDiff->addedCheckConstraints); + self::assertSame('age > 18', $tableDiff->addedCheckConstraints[0]->expression); + self::assertCount(1, $tableDiff->removedCheckConstraints); + self::assertSame('age > 0', $tableDiff->removedCheckConstraints[0]->expression); + } + + public function test_check_constraint_no_inherit_change_detected() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('age')], checkConstraints: [ + schema_check('age > 0', 'chk_age', false), + ]), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('age')], checkConstraints: [ + schema_check('age > 0', 'chk_age', true), + ]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertCount(1, $tableDiff->addedCheckConstraints); + self::assertCount(1, $tableDiff->removedCheckConstraints); + } + + public function test_check_constraint_removed() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('age')], checkConstraints: [ + schema_check('age > 0', 'chk_age_positive'), + ]), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('age')]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertCount(1, $tableDiff->removedCheckConstraints); + self::assertSame('age > 0', $tableDiff->removedCheckConstraints[0]->expression); + } + + public function test_check_constraint_without_name_uses_expression_for_matching() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('age')], checkConstraints: [ + schema_check('age > 0'), + ]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $source); + + self::assertTrue($diff->isEmpty()); + } + + public function test_column_add_and_remove_not_confused_as_rename() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('users', [ + schema_column_integer('id', false), + schema_column_text('foo'), + schema_column_text('bar'), + ]), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('users', [ + schema_column_integer('id', false), + schema_column_text('xyz_completely_different_one'), + schema_column_text('xyz_completely_different_two'), + ]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertCount(2, $tableDiff->addedColumns); + self::assertCount(2, $tableDiff->removedColumns); + self::assertCount(0, $tableDiff->modifiedColumns); + } + + public function test_column_rename_detected() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('users', [ + schema_column_integer('id', false), + schema_column_text('name'), + ]), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('users', [ + schema_column_integer('id', false), + schema_column_text('full_name'), + ]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertCount(0, $tableDiff->addedColumns); + self::assertCount(0, $tableDiff->removedColumns); + self::assertCount(1, $tableDiff->modifiedColumns); + self::assertTrue($tableDiff->modifiedColumns[0]->hasNameChanged()); + self::assertSame('name', $tableDiff->modifiedColumns[0]->source->name); + self::assertSame('full_name', $tableDiff->modifiedColumns[0]->target->name); + } + + public function test_column_rename_detected_with_ambiguous_candidates() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('orders', [ + schema_column_integer('id', false), + schema_column_bigint('net_commission_cents'), + schema_column_bigint('retail_agency_commission_cents'), + schema_column_bigint('total_commission_cents'), + ]), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('orders', [ + schema_column_integer('id', false), + schema_column_bigint('net_commission'), + schema_column_bigint('retail_agency_commission'), + schema_column_bigint('total_commission'), + ]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertCount(0, $tableDiff->addedColumns); + self::assertCount(0, $tableDiff->removedColumns); + self::assertCount(3, $tableDiff->modifiedColumns); + + $renames = []; + + foreach ($tableDiff->modifiedColumns as $col) { + self::assertTrue($col->hasNameChanged()); + $renames[$col->source->name] = $col->target->name; + } + + \ksort($renames); + self::assertSame([ + 'net_commission_cents' => 'net_commission', + 'retail_agency_commission_cents' => 'retail_agency_commission', + 'total_commission_cents' => 'total_commission', + ], $renames); + } + + public function test_column_rename_not_detected_when_type_changes() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('users', [ + schema_column_integer('id', false), + schema_column_text('name'), + ]), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('users', [ + schema_column_integer('id', false), + schema_column_integer('full_name'), + ]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertCount(1, $tableDiff->addedColumns); + self::assertSame('full_name', $tableDiff->addedColumns[0]->name); + self::assertCount(1, $tableDiff->removedColumns); + self::assertSame('name', $tableDiff->removedColumns[0]->name); + self::assertCount(0, $tableDiff->modifiedColumns); + } + + public function test_column_rename_with_mixed_types() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('orders', [ + schema_column_integer('id', false), + schema_column_bigint('amount_cents'), + schema_column_bigint('total_cents'), + schema_column_text('description_old'), + ]), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('orders', [ + schema_column_integer('id', false), + schema_column_bigint('amount'), + schema_column_bigint('total'), + schema_column_text('description'), + ]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertCount(0, $tableDiff->addedColumns); + self::assertCount(0, $tableDiff->removedColumns); + self::assertCount(3, $tableDiff->modifiedColumns); + + $renames = []; + + foreach ($tableDiff->modifiedColumns as $col) { + self::assertTrue($col->hasNameChanged()); + $renames[$col->source->name] = $col->target->name; + } + + \ksort($renames); + self::assertSame([ + 'amount_cents' => 'amount', + 'description_old' => 'description', + 'total_cents' => 'total', + ], $renames); + } + + public function test_column_rename_with_strict_rename_strategy() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('orders', [ + schema_column_integer('id', false), + schema_column_bigint('net_commission_cents'), + schema_column_bigint('retail_agency_commission_cents'), + schema_column_bigint('total_commission_cents'), + ]), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('orders', [ + schema_column_integer('id', false), + schema_column_bigint('net_commission'), + schema_column_bigint('retail_agency_commission'), + schema_column_bigint('total_commission'), + ]), + ]), + ]); + + $diff = catalog_comparator(new StrictRenameStrategy())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertCount(3, $tableDiff->addedColumns); + self::assertCount(3, $tableDiff->removedColumns); + self::assertCount(0, $tableDiff->modifiedColumns); + } + + public function test_domain_added() : void + { + $source = new Catalog([schema('public')]); + $target = new Catalog([ + schema('public', domains: [ + schema_domain('email', ColumnType::text()), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->modifiedSchemas[0]->addedDomains); + self::assertSame('email', $diff->modifiedSchemas[0]->addedDomains[0]->name); + } + + public function test_domain_base_type_change_detected() : void + { + $source = new Catalog([ + schema('public', domains: [ + schema_domain('positive_int', ColumnType::integer()), + ]), + ]); + $target = new Catalog([ + schema('public', domains: [ + schema_domain('positive_int', ColumnType::bigint()), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->modifiedSchemas[0]->modifiedDomains); + self::assertTrue($diff->modifiedSchemas[0]->modifiedDomains[0]->hasBaseTypeChanged()); + } + + public function test_domain_check_constraint_change_detected() : void + { + $source = new Catalog([ + schema('public', domains: [ + schema_domain('email', ColumnType::text(), checkConstraints: [ + schema_check('VALUE ~ \'@\'', 'chk_email'), + ]), + ]), + ]); + $target = new Catalog([ + schema('public', domains: [ + schema_domain('email', ColumnType::text(), checkConstraints: [ + schema_check('VALUE ~ \'@.+\\.\'', 'chk_email'), + ]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->modifiedSchemas[0]->modifiedDomains); + self::assertCount(1, $diff->modifiedSchemas[0]->modifiedDomains[0]->addedCheckConstraints); + self::assertCount(1, $diff->modifiedSchemas[0]->modifiedDomains[0]->removedCheckConstraints); + } + + public function test_domain_default_change_detected() : void + { + $source = new Catalog([ + schema('public', domains: [ + schema_domain('email', ColumnType::text(), default: 'old'), + ]), + ]); + $target = new Catalog([ + schema('public', domains: [ + schema_domain('email', ColumnType::text(), default: 'new'), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->modifiedSchemas[0]->modifiedDomains); + self::assertTrue($diff->modifiedSchemas[0]->modifiedDomains[0]->hasDefaultChanged()); + } + + public function test_domain_no_change_when_identical() : void + { + $source = new Catalog([ + schema('public', domains: [ + schema_domain('email', ColumnType::text(), nullable: false, default: 'x', checkConstraints: [ + schema_check('VALUE ~ \'@\'', 'chk_email'), + ]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $source); + + self::assertTrue($diff->isEmpty()); + } + + public function test_domain_nullable_change_detected() : void + { + $source = new Catalog([ + schema('public', domains: [ + schema_domain('email', ColumnType::text(), nullable: true), + ]), + ]); + $target = new Catalog([ + schema('public', domains: [ + schema_domain('email', ColumnType::text(), nullable: false), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->modifiedSchemas[0]->modifiedDomains); + self::assertTrue($diff->modifiedSchemas[0]->modifiedDomains[0]->hasNullableChanged()); + } + + public function test_domain_removed() : void + { + $source = new Catalog([ + schema('public', domains: [ + schema_domain('email', ColumnType::text()), + ]), + ]); + $target = new Catalog([schema('public')]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->modifiedSchemas[0]->removedDomains); + } + + public function test_exclude_constraint_added() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('events', [ + schema_column_integer('id', false), + schema_column_text('room'), + ]), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('events', [ + schema_column_integer('id', false), + schema_column_text('room'), + ], excludeConstraints: [ + schema_exclude('USING gist (room WITH =)', 'excl_room'), + ]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertCount(1, $tableDiff->addedExcludeConstraints); + self::assertSame('USING gist (room WITH =)', $tableDiff->addedExcludeConstraints[0]->definition); + } + + public function test_exclude_constraint_modified_treated_as_drop_and_add() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('events', [ + schema_column_integer('id', false), + schema_column_text('room'), + ], excludeConstraints: [ + schema_exclude('USING gist (room WITH =)', 'excl_room'), + ]), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('events', [ + schema_column_integer('id', false), + schema_column_text('room'), + ], excludeConstraints: [ + schema_exclude('USING gist (room WITH &&)', 'excl_room'), + ]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertCount(1, $tableDiff->addedExcludeConstraints); + self::assertCount(1, $tableDiff->removedExcludeConstraints); + } + + public function test_exclude_constraint_removed() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('events', [ + schema_column_integer('id', false), + schema_column_text('room'), + ], excludeConstraints: [ + schema_exclude('USING gist (room WITH =)', 'excl_room'), + ]), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('events', [ + schema_column_integer('id', false), + schema_column_text('room'), + ]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertCount(1, $tableDiff->removedExcludeConstraints); + } + + public function test_exclude_constraint_without_name_uses_definition_for_matching() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('events', [ + schema_column_integer('id', false), + schema_column_text('room'), + ], excludeConstraints: [ + schema_exclude('USING gist (room WITH =)'), + ]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $source); + + self::assertTrue($diff->isEmpty()); + } + + public function test_extension_added() : void + { + $source = new Catalog([schema('public')]); + $target = new Catalog([ + schema('public', extensions: [ + schema_extension('uuid-ossp', '1.0'), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->modifiedSchemas[0]->addedExtensions); + self::assertSame('uuid-ossp', $diff->modifiedSchemas[0]->addedExtensions[0]->name); + } + + public function test_extension_no_change_when_identical() : void + { + $source = new Catalog([ + schema('public', extensions: [ + schema_extension('uuid-ossp', '1.0'), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $source); + + self::assertTrue($diff->isEmpty()); + } + + public function test_extension_removed() : void + { + $source = new Catalog([ + schema('public', extensions: [ + schema_extension('uuid-ossp', '1.0'), + ]), + ]); + $target = new Catalog([schema('public')]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->modifiedSchemas[0]->removedExtensions); + } + + public function test_extension_version_change_detected() : void + { + $source = new Catalog([ + schema('public', extensions: [ + schema_extension('uuid-ossp', '1.0'), + ]), + ]); + $target = new Catalog([ + schema('public', extensions: [ + schema_extension('uuid-ossp', '1.1'), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->modifiedSchemas[0]->modifiedExtensions); + self::assertTrue($diff->modifiedSchemas[0]->modifiedExtensions[0]->hasVersionChanged()); + } + + public function test_foreign_key_added() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('orders', [ + schema_column_integer('id', false), + schema_column_integer('user_id', false), + ]), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('orders', [ + schema_column_integer('id', false), + schema_column_integer('user_id', false), + ], foreignKeys: [ + schema_foreign_key(['user_id'], 'users', ['id']), + ]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertCount(1, $tableDiff->addedForeignKeys); + self::assertSame(['user_id'], $tableDiff->addedForeignKeys[0]->columns); + } + + public function test_foreign_key_modified_columns_change() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('orders', [ + schema_column_integer('id', false), + schema_column_integer('user_id', false), + ], foreignKeys: [ + schema_foreign_key(['user_id'], 'users', ['id'], name: 'fk_user'), + ]), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('orders', [ + schema_column_integer('id', false), + schema_column_integer('user_id', false), + ], foreignKeys: [ + schema_foreign_key(['user_id'], 'users', ['uuid'], name: 'fk_user'), + ]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertCount(1, $tableDiff->addedForeignKeys); + self::assertCount(1, $tableDiff->removedForeignKeys); + } + + public function test_foreign_key_modified_deferrable_change() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('orders', [ + schema_column_integer('id', false), + schema_column_integer('user_id', false), + ], foreignKeys: [ + schema_foreign_key(['user_id'], 'users', ['id'], name: 'fk_user', deferrable: false), + ]), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('orders', [ + schema_column_integer('id', false), + schema_column_integer('user_id', false), + ], foreignKeys: [ + schema_foreign_key(['user_id'], 'users', ['id'], name: 'fk_user', deferrable: true), + ]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertCount(1, $tableDiff->addedForeignKeys); + self::assertCount(1, $tableDiff->removedForeignKeys); + } + + public function test_foreign_key_modified_initially_deferred_change() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('orders', [ + schema_column_integer('id', false), + schema_column_integer('user_id', false), + ], foreignKeys: [ + schema_foreign_key(['user_id'], 'users', ['id'], name: 'fk_user', deferrable: true, initiallyDeferred: false), + ]), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('orders', [ + schema_column_integer('id', false), + schema_column_integer('user_id', false), + ], foreignKeys: [ + schema_foreign_key(['user_id'], 'users', ['id'], name: 'fk_user', deferrable: true, initiallyDeferred: true), + ]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertCount(1, $tableDiff->addedForeignKeys); + self::assertCount(1, $tableDiff->removedForeignKeys); + } + + public function test_foreign_key_modified_on_delete_action_change() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('orders', [ + schema_column_integer('id', false), + schema_column_integer('user_id', false), + ], foreignKeys: [ + schema_foreign_key(['user_id'], 'users', ['id'], name: 'fk_user', onDelete: ReferentialAction::NO_ACTION), + ]), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('orders', [ + schema_column_integer('id', false), + schema_column_integer('user_id', false), + ], foreignKeys: [ + schema_foreign_key(['user_id'], 'users', ['id'], name: 'fk_user', onDelete: ReferentialAction::CASCADE), + ]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertCount(1, $tableDiff->addedForeignKeys); + self::assertCount(1, $tableDiff->removedForeignKeys); + } + + public function test_foreign_key_modified_on_update_action_change() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('orders', [ + schema_column_integer('id', false), + schema_column_integer('user_id', false), + ], foreignKeys: [ + schema_foreign_key(['user_id'], 'users', ['id'], name: 'fk_user', onUpdate: ReferentialAction::NO_ACTION), + ]), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('orders', [ + schema_column_integer('id', false), + schema_column_integer('user_id', false), + ], foreignKeys: [ + schema_foreign_key(['user_id'], 'users', ['id'], name: 'fk_user', onUpdate: ReferentialAction::CASCADE), + ]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertCount(1, $tableDiff->addedForeignKeys); + self::assertCount(1, $tableDiff->removedForeignKeys); + } + + public function test_foreign_key_modified_reference_schema_change() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('orders', [ + schema_column_integer('id', false), + schema_column_integer('user_id', false), + ], foreignKeys: [ + schema_foreign_key(['user_id'], 'users', ['id'], name: 'fk_user', referenceSchema: 'public'), + ]), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('orders', [ + schema_column_integer('id', false), + schema_column_integer('user_id', false), + ], foreignKeys: [ + schema_foreign_key(['user_id'], 'users', ['id'], name: 'fk_user', referenceSchema: 'auth'), + ]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertCount(1, $tableDiff->addedForeignKeys); + self::assertCount(1, $tableDiff->removedForeignKeys); + } + + public function test_foreign_key_modified_reference_table_change() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('orders', [ + schema_column_integer('id', false), + schema_column_integer('user_id', false), + ], foreignKeys: [ + schema_foreign_key(['user_id'], 'users', ['id'], name: 'fk_user'), + ]), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('orders', [ + schema_column_integer('id', false), + schema_column_integer('user_id', false), + ], foreignKeys: [ + schema_foreign_key(['user_id'], 'accounts', ['id'], name: 'fk_user'), + ]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertCount(1, $tableDiff->addedForeignKeys); + self::assertCount(1, $tableDiff->removedForeignKeys); + } + + public function test_foreign_key_removed() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('orders', [ + schema_column_integer('id', false), + schema_column_integer('user_id', false), + ], foreignKeys: [ + schema_foreign_key(['user_id'], 'users', ['id']), + ]), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('orders', [ + schema_column_integer('id', false), + schema_column_integer('user_id', false), + ]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertCount(1, $tableDiff->removedForeignKeys); + } + + public function test_foreign_key_without_name_uses_identity_for_matching() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('orders', [ + schema_column_integer('id', false), + schema_column_integer('user_id', false), + ], foreignKeys: [ + schema_foreign_key(['user_id'], 'users', ['id']), + ]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $source); + + self::assertTrue($diff->isEmpty()); + } + + public function test_function_added() : void + { + $source = new Catalog([schema('public')]); + $target = new Catalog([ + schema('public', functions: [ + schema_function('get_user', 'text', ['integer'], 'sql', select(col('name'))->from(table('users'))->where(eq(col('id'), literal(1)))->toSql()), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->modifiedSchemas[0]->addedFunctions); + self::assertSame('get_user', $diff->modifiedSchemas[0]->addedFunctions[0]->name); + } + + public function test_function_modified_argument_types_change() : void + { + $source = new Catalog([ + schema('public', functions: [ + schema_function('get_user', 'text', ['integer']), + ]), + ]); + $target = new Catalog([ + schema('public', functions: [ + schema_function('get_user', 'text', ['text']), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->modifiedSchemas[0]->modifiedFunctions); + } + + public function test_function_modified_definition_change() : void + { + $source = new Catalog([ + schema('public', functions: [ + schema_function('get_user', 'text', ['integer'], definition: select(literal(1))->toSql()), + ]), + ]); + $target = new Catalog([ + schema('public', functions: [ + schema_function('get_user', 'text', ['integer'], definition: select(literal(2))->toSql()), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->modifiedSchemas[0]->modifiedFunctions); + } + + public function test_function_modified_language_change() : void + { + $source = new Catalog([ + schema('public', functions: [ + schema_function('get_user', 'text', ['integer'], 'sql'), + ]), + ]); + $target = new Catalog([ + schema('public', functions: [ + schema_function('get_user', 'text', ['integer'], 'plpgsql'), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->modifiedSchemas[0]->modifiedFunctions); + } + + public function test_function_modified_return_type_change() : void + { + $source = new Catalog([ + schema('public', functions: [ + schema_function('get_user', 'text', ['integer']), + ]), + ]); + $target = new Catalog([ + schema('public', functions: [ + schema_function('get_user', 'integer', ['integer']), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->modifiedSchemas[0]->modifiedFunctions); + } + + public function test_function_modified_strict_change() : void + { + $source = new Catalog([ + schema('public', functions: [ + schema_function('get_user', 'text', ['integer'], isStrict: false), + ]), + ]); + $target = new Catalog([ + schema('public', functions: [ + schema_function('get_user', 'text', ['integer'], isStrict: true), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->modifiedSchemas[0]->modifiedFunctions); + } + + public function test_function_modified_volatility_change() : void + { + $source = new Catalog([ + schema('public', functions: [ + schema_function('get_user', 'text', ['integer'], volatility: FunctionVolatility::VOLATILE), + ]), + ]); + $target = new Catalog([ + schema('public', functions: [ + schema_function('get_user', 'text', ['integer'], volatility: FunctionVolatility::IMMUTABLE), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->modifiedSchemas[0]->modifiedFunctions); + } + + public function test_function_no_change_when_identical() : void + { + $source = new Catalog([ + schema('public', functions: [ + schema_function('get_user', 'text', ['integer'], 'sql', select(literal(1))->toSql(), true, FunctionVolatility::STABLE), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $source); + + self::assertTrue($diff->isEmpty()); + } + + public function test_function_removed() : void + { + $source = new Catalog([ + schema('public', functions: [ + schema_function('get_user', 'text', ['integer']), + ]), + ]); + $target = new Catalog([schema('public')]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->modifiedSchemas[0]->removedFunctions); + } + + public function test_identical_catalogs_produce_empty_diff() : void + { + $catalog = new Catalog([ + schema('public', tables: [ + schema_table('users', [ + schema_column_integer('id', false), + schema_column_text('name'), + ], primaryKey: schema_primary_key(['id'])), + ]), + ]); + + $diff = (catalog_comparator())->compare($catalog, $catalog); + + self::assertTrue($diff->isEmpty()); + } + + public function test_identical_table_not_in_modified_tables() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('users', [ + schema_column_integer('id', false), + schema_column_text('name'), + ], primaryKey: schema_primary_key(['id']), indexes: [ + schema_index('idx_name', ['name']), + ]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $source); + + self::assertTrue($diff->isEmpty()); + self::assertCount(0, $diff->modifiedSchemas); + } + + public function test_index_rename_detected() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false), schema_column_text('email')], indexes: [ + schema_index('idx_email_old', ['email']), + ]), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false), schema_column_text('email')], indexes: [ + schema_index('idx_email_new', ['email']), + ]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertCount(0, $tableDiff->addedIndexes); + self::assertCount(0, $tableDiff->removedIndexes); + self::assertCount(1, $tableDiff->renamedIndexes); + self::assertArrayHasKey('idx_email_old', $tableDiff->renamedIndexes); + self::assertSame('idx_email_new', $tableDiff->renamedIndexes['idx_email_old']->name); + } + + public function test_index_with_same_name_but_different_structure() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false), schema_column_text('email'), schema_column_text('name')], indexes: [ + schema_index('idx_users', ['email']), + ]), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false), schema_column_text('email'), schema_column_text('name')], indexes: [ + schema_index('idx_users', ['name']), + ]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertCount(1, $tableDiff->addedIndexes); + self::assertSame('idx_users', $tableDiff->addedIndexes[0]->name); + self::assertCount(1, $tableDiff->removedIndexes); + self::assertSame('idx_users', $tableDiff->removedIndexes[0]->name); + } + + public function test_materialized_view_added() : void + { + $source = new Catalog([schema('public')]); + $target = new Catalog([ + schema('public', materializedViews: [ + schema_materialized_view('mv_users', select(star())->from(table('users'))->toSql()), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->modifiedSchemas[0]->addedMaterializedViews); + self::assertSame('mv_users', $diff->modifiedSchemas[0]->addedMaterializedViews[0]->name); + } + + public function test_materialized_view_definition_change_detected() : void + { + $source = new Catalog([ + schema('public', materializedViews: [ + schema_materialized_view('mv_users', select(star())->from(table('users'))->toSql()), + ]), + ]); + $target = new Catalog([ + schema('public', materializedViews: [ + schema_materialized_view('mv_users', select(star())->from(table('users'))->where(eq(col('active'), literal(true)))->toSql()), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->modifiedSchemas[0]->modifiedMaterializedViews); + self::assertTrue($diff->modifiedSchemas[0]->modifiedMaterializedViews[0]->hasDefinitionChanged()); + } + + public function test_materialized_view_index_change_detected() : void + { + $source = new Catalog([ + schema('public', materializedViews: [ + schema_materialized_view('mv_users', select(star())->from(table('users'))->toSql()), + ]), + ]); + $target = new Catalog([ + schema('public', materializedViews: [ + schema_materialized_view('mv_users', select(star())->from(table('users'))->toSql(), indexes: [ + schema_index('idx_mv_users', ['id']), + ]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->modifiedSchemas[0]->modifiedMaterializedViews); + self::assertCount(1, $diff->modifiedSchemas[0]->modifiedMaterializedViews[0]->addedIndexes); + } + + public function test_materialized_view_no_change_when_identical() : void + { + $source = new Catalog([ + schema('public', materializedViews: [ + schema_materialized_view('mv_users', select(star())->from(table('users'))->toSql()), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $source); + + self::assertTrue($diff->isEmpty()); + } + + public function test_materialized_view_removed() : void + { + $source = new Catalog([ + schema('public', materializedViews: [ + schema_materialized_view('mv_users', select(star())->from(table('users'))->toSql()), + ]), + ]); + $target = new Catalog([schema('public')]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->modifiedSchemas[0]->removedMaterializedViews); + } + + public function test_modified_column_detected() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('users', [ + schema_column_integer('id', false), + schema_column_text('name'), + ]), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('users', [ + schema_column_integer('id', false), + schema_column_text('name', false), + ]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertCount(1, $tableDiff->modifiedColumns); + self::assertSame('name', $tableDiff->modifiedColumns[0]->source->name); + self::assertTrue($tableDiff->modifiedColumns[0]->hasNullableChanged()); + self::assertFalse($tableDiff->modifiedColumns[0]->hasNameChanged()); + } + + public function test_primary_key_added() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false)]), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false)], primaryKey: schema_primary_key(['id'])), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertNotNull($tableDiff->addedPrimaryKey); + self::assertNull($tableDiff->removedPrimaryKey); + self::assertSame(['id'], $tableDiff->addedPrimaryKey->columns); + } + + public function test_primary_key_changed() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('users', [ + schema_column_integer('id', false), + schema_column_uuid('uuid', false), + ], primaryKey: schema_primary_key(['id'])), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('users', [ + schema_column_integer('id', false), + schema_column_uuid('uuid', false), + ], primaryKey: schema_primary_key(['uuid'])), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertNotNull($tableDiff->addedPrimaryKey); + self::assertNotNull($tableDiff->removedPrimaryKey); + self::assertSame(['uuid'], $tableDiff->addedPrimaryKey->columns); + self::assertSame(['id'], $tableDiff->removedPrimaryKey->columns); + } + + public function test_primary_key_removed() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false)], primaryKey: schema_primary_key(['id'])), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false)]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertNull($tableDiff->addedPrimaryKey); + self::assertNotNull($tableDiff->removedPrimaryKey); + } + + public function test_procedure_added() : void + { + $source = new Catalog([schema('public')]); + $target = new Catalog([ + schema('public', procedures: [ + schema_procedure('cleanup', ['integer'], 'sql', 'DELETE FROM logs WHERE id = $1'), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->modifiedSchemas[0]->addedProcedures); + self::assertSame('cleanup', $diff->modifiedSchemas[0]->addedProcedures[0]->name); + } + + public function test_procedure_modified_argument_types_change() : void + { + $source = new Catalog([ + schema('public', procedures: [ + schema_procedure('cleanup', ['integer']), + ]), + ]); + $target = new Catalog([ + schema('public', procedures: [ + schema_procedure('cleanup', ['text']), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->modifiedSchemas[0]->modifiedProcedures); + } + + public function test_procedure_modified_definition_change() : void + { + $source = new Catalog([ + schema('public', procedures: [ + schema_procedure('cleanup', ['integer'], definition: 'DELETE FROM logs WHERE id = $1'), + ]), + ]); + $target = new Catalog([ + schema('public', procedures: [ + schema_procedure('cleanup', ['integer'], definition: 'DELETE FROM logs'), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->modifiedSchemas[0]->modifiedProcedures); + } + + public function test_procedure_modified_language_change() : void + { + $source = new Catalog([ + schema('public', procedures: [ + schema_procedure('cleanup', ['integer'], 'sql'), + ]), + ]); + $target = new Catalog([ + schema('public', procedures: [ + schema_procedure('cleanup', ['integer'], 'plpgsql'), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->modifiedSchemas[0]->modifiedProcedures); + } + + public function test_procedure_no_change_when_identical() : void + { + $source = new Catalog([ + schema('public', procedures: [ + schema_procedure('cleanup', ['integer'], 'sql', 'DELETE FROM logs'), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $source); + + self::assertTrue($diff->isEmpty()); + } + + public function test_procedure_removed() : void + { + $source = new Catalog([ + schema('public', procedures: [ + schema_procedure('cleanup', ['integer']), + ]), + ]); + $target = new Catalog([schema('public')]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->modifiedSchemas[0]->removedProcedures); + } + + public function test_removed_column_detected() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('users', [ + schema_column_integer('id', false), + schema_column_text('email'), + ]), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false)]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertCount(1, $tableDiff->removedColumns); + self::assertSame('email', $tableDiff->removedColumns[0]->name); + } + + public function test_removed_index_detected() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false), schema_column_text('email')], indexes: [ + schema_index('idx_email', ['email']), + ]), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false), schema_column_text('email')]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertCount(1, $tableDiff->removedIndexes); + self::assertSame('idx_email', $tableDiff->removedIndexes[0]->name); + } + + public function test_removed_schema_detected() : void + { + $source = new Catalog([schema('public'), schema('audit')]); + $target = new Catalog([schema('public')]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(0, $diff->addedSchemas); + self::assertCount(1, $diff->removedSchemas); + self::assertSame('audit', $diff->removedSchemas[0]->name); + } + + public function test_removed_table_detected() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false)]), + ]), + ]); + $target = new Catalog([schema('public')]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->modifiedSchemas); + self::assertCount(1, $diff->modifiedSchemas[0]->removedTables); + self::assertSame('users', $diff->modifiedSchemas[0]->removedTables[0]->name); + } + + public function test_reverse_comparison_produces_inverse_diff() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false)]), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false)]), + schema_table('orders', [schema_column_integer('id', false)]), + ]), + ]); + + $comparator = catalog_comparator(); + + $upDiff = $comparator->compare($source, $target); + $downDiff = $comparator->compare($target, $source); + + self::assertCount(1, $upDiff->modifiedSchemas[0]->addedTables); + self::assertSame('orders', $upDiff->modifiedSchemas[0]->addedTables[0]->name); + self::assertCount(0, $upDiff->modifiedSchemas[0]->removedTables); + + self::assertCount(0, $downDiff->modifiedSchemas[0]->addedTables); + self::assertCount(1, $downDiff->modifiedSchemas[0]->removedTables); + self::assertSame('orders', $downDiff->modifiedSchemas[0]->removedTables[0]->name); + } + + public function test_sequence_added() : void + { + $source = new Catalog([schema('public')]); + $target = new Catalog([ + schema('public', sequences: [ + schema_sequence('users_id_seq'), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->modifiedSchemas[0]->addedSequences); + self::assertSame('users_id_seq', $diff->modifiedSchemas[0]->addedSequences[0]->name); + } + + public function test_sequence_cache_value_change_detected() : void + { + $source = new Catalog([ + schema('public', sequences: [ + schema_sequence('s1', cacheValue: 1), + ]), + ]); + $target = new Catalog([ + schema('public', sequences: [ + schema_sequence('s1', cacheValue: 10), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->modifiedSchemas[0]->modifiedSequences); + } + + public function test_sequence_column_type_change_detected() : void + { + $source = new Catalog([ + schema('public', sequences: [ + schema_sequence('s1', dataType: 'bigint'), + ]), + ]); + $target = new Catalog([ + schema('public', sequences: [ + schema_sequence('s1', dataType: 'integer'), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->modifiedSchemas[0]->modifiedSequences); + } + + public function test_sequence_cycle_change_detected() : void + { + $source = new Catalog([ + schema('public', sequences: [ + schema_sequence('s1', cycle: false), + ]), + ]); + $target = new Catalog([ + schema('public', sequences: [ + schema_sequence('s1', cycle: true), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->modifiedSchemas[0]->modifiedSequences); + } + + public function test_sequence_max_value_change_detected() : void + { + $source = new Catalog([ + schema('public', sequences: [ + schema_sequence('s1'), + ]), + ]); + $target = new Catalog([ + schema('public', sequences: [ + schema_sequence('s1', maxValue: 9999), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->modifiedSchemas[0]->modifiedSequences); + } + + public function test_sequence_min_value_change_detected() : void + { + $source = new Catalog([ + schema('public', sequences: [ + schema_sequence('s1', minValue: 1), + ]), + ]); + $target = new Catalog([ + schema('public', sequences: [ + schema_sequence('s1', minValue: 0), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->modifiedSchemas[0]->modifiedSequences); + } + + public function test_sequence_modification_detected() : void + { + $source = new Catalog([ + schema('public', sequences: [ + schema_sequence('users_id_seq'), + ]), + ]); + $target = new Catalog([ + schema('public', sequences: [ + schema_sequence('users_id_seq', incrementBy: 10), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->modifiedSchemas); + self::assertCount(1, $diff->modifiedSchemas[0]->modifiedSequences); + self::assertSame('users_id_seq', $diff->modifiedSchemas[0]->modifiedSequences[0]->source->name); + } + + public function test_sequence_no_change_when_identical() : void + { + $source = new Catalog([ + schema('public', sequences: [ + schema_sequence('s1', 'bigint', 1, 1, null, 1, false, 1, 'users', 'id'), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $source); + + self::assertTrue($diff->isEmpty()); + } + + public function test_sequence_owned_by_column_change_detected() : void + { + $source = new Catalog([ + schema('public', sequences: [ + schema_sequence('s1', ownedByColumn: 'id'), + ]), + ]); + $target = new Catalog([ + schema('public', sequences: [ + schema_sequence('s1', ownedByColumn: 'user_id'), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->modifiedSchemas[0]->modifiedSequences); + } + + public function test_sequence_owned_by_table_change_detected() : void + { + $source = new Catalog([ + schema('public', sequences: [ + schema_sequence('s1', ownedByTable: 'users'), + ]), + ]); + $target = new Catalog([ + schema('public', sequences: [ + schema_sequence('s1', ownedByTable: 'accounts'), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->modifiedSchemas[0]->modifiedSequences); + } + + public function test_sequence_removed() : void + { + $source = new Catalog([ + schema('public', sequences: [ + schema_sequence('users_id_seq'), + ]), + ]); + $target = new Catalog([schema('public')]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->modifiedSchemas[0]->removedSequences); + } + + public function test_sequence_start_value_change_detected() : void + { + $source = new Catalog([ + schema('public', sequences: [ + schema_sequence('s1', startValue: 1), + ]), + ]); + $target = new Catalog([ + schema('public', sequences: [ + schema_sequence('s1', startValue: 100), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->modifiedSchemas[0]->modifiedSequences); + } + + public function test_trigger_added() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false)]), + ]), + ]); + + $trigger = new Trigger('trg_audit', 'users', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'audit_fn'); + + $target = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false)], triggers: [$trigger]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertCount(1, $tableDiff->addedTriggers); + self::assertSame('trg_audit', $tableDiff->addedTriggers[0]->name); + } + + public function test_trigger_modified_events_change_treated_as_drop_and_add() : void + { + $sourceTrigger = new Trigger('trg_audit', 'users', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'audit_fn'); + $targetTrigger = new Trigger('trg_audit', 'users', TriggerTiming::AFTER, [TriggerEvent::INSERT, TriggerEvent::UPDATE], 'audit_fn'); + + $source = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false)], triggers: [$sourceTrigger]), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false)], triggers: [$targetTrigger]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertCount(1, $tableDiff->addedTriggers); + self::assertCount(1, $tableDiff->removedTriggers); + } + + public function test_trigger_modified_for_each_row_change_treated_as_drop_and_add() : void + { + $sourceTrigger = new Trigger('trg_audit', 'users', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'audit_fn', forEachRow: false); + $targetTrigger = new Trigger('trg_audit', 'users', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'audit_fn', forEachRow: true); + + $source = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false)], triggers: [$sourceTrigger]), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false)], triggers: [$targetTrigger]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertCount(1, $tableDiff->addedTriggers); + self::assertCount(1, $tableDiff->removedTriggers); + } + + public function test_trigger_modified_function_name_change_treated_as_drop_and_add() : void + { + $sourceTrigger = new Trigger('trg_audit', 'users', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'audit_fn'); + $targetTrigger = new Trigger('trg_audit', 'users', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'new_audit_fn'); + + $source = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false)], triggers: [$sourceTrigger]), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false)], triggers: [$targetTrigger]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertCount(1, $tableDiff->addedTriggers); + self::assertCount(1, $tableDiff->removedTriggers); + } + + public function test_trigger_modified_table_name_change_treated_as_drop_and_add() : void + { + $sourceTrigger = new Trigger('trg_audit', 'users', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'audit_fn'); + $targetTrigger = new Trigger('trg_audit', 'accounts', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'audit_fn'); + + $source = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false)], triggers: [$sourceTrigger]), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false)], triggers: [$targetTrigger]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertCount(1, $tableDiff->addedTriggers); + self::assertCount(1, $tableDiff->removedTriggers); + } + + public function test_trigger_modified_timing_change_treated_as_drop_and_add() : void + { + $sourceTrigger = new Trigger('trg_audit', 'users', TriggerTiming::BEFORE, [TriggerEvent::INSERT], 'audit_fn'); + $targetTrigger = new Trigger('trg_audit', 'users', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'audit_fn'); + + $source = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false)], triggers: [$sourceTrigger]), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false)], triggers: [$targetTrigger]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertCount(1, $tableDiff->addedTriggers); + self::assertCount(1, $tableDiff->removedTriggers); + } + + public function test_trigger_modified_when_condition_change_treated_as_drop_and_add() : void + { + $sourceTrigger = new Trigger('trg_audit', 'users', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'audit_fn', whenCondition: 'OLD.* IS DISTINCT FROM NEW.*'); + $targetTrigger = new Trigger('trg_audit', 'users', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'audit_fn', whenCondition: 'NEW.active = true'); + + $source = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false)], triggers: [$sourceTrigger]), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false)], triggers: [$targetTrigger]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertCount(1, $tableDiff->addedTriggers); + self::assertCount(1, $tableDiff->removedTriggers); + } + + public function test_trigger_no_change_when_identical() : void + { + $trigger = new Trigger('trg_audit', 'users', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'audit_fn', true, 'NEW.active = true'); + + $source = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false)], triggers: [$trigger]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $source); + + self::assertTrue($diff->isEmpty()); + } + + public function test_trigger_removed() : void + { + $trigger = new Trigger('trg_audit', 'users', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'audit_fn'); + + $source = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false)], triggers: [$trigger]), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false)]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertCount(1, $tableDiff->removedTriggers); + self::assertSame('trg_audit', $tableDiff->removedTriggers[0]->name); + } + + public function test_unique_constraint_added() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false), schema_column_text('email')]), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false), schema_column_text('email')], uniqueConstraints: [ + schema_unique(['email']), + ]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertCount(1, $tableDiff->addedUniqueConstraints); + } + + public function test_unique_constraint_modified_nulls_not_distinct_change() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false), schema_column_text('email')], uniqueConstraints: [ + schema_unique(['email'], 'uq_email', false), + ]), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false), schema_column_text('email')], uniqueConstraints: [ + schema_unique(['email'], 'uq_email', true), + ]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertCount(1, $tableDiff->addedUniqueConstraints); + self::assertCount(1, $tableDiff->removedUniqueConstraints); + } + + public function test_unique_constraint_removed() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false), schema_column_text('email')], uniqueConstraints: [ + schema_unique(['email']), + ]), + ]), + ]); + $target = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false), schema_column_text('email')]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + $tableDiff = $diff->modifiedSchemas[0]->modifiedTables[0]; + self::assertCount(1, $tableDiff->removedUniqueConstraints); + } + + public function test_unique_constraint_without_name_uses_columns_for_matching() : void + { + $source = new Catalog([ + schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false), schema_column_text('email')], uniqueConstraints: [ + schema_unique(['email']), + ]), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $source); + + self::assertTrue($diff->isEmpty()); + } + + public function test_view_added() : void + { + $source = new Catalog([schema('public')]); + $target = new Catalog([ + schema('public', views: [ + schema_view('active_users', select(star())->from(table('users'))->where(eq(col('active'), literal(true)))->toSql()), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->modifiedSchemas[0]->addedViews); + self::assertSame('active_users', $diff->modifiedSchemas[0]->addedViews[0]->name); + } + + public function test_view_is_updatable_change_detected() : void + { + $source = new Catalog([ + schema('public', views: [ + schema_view('active_users', select(star())->from(table('users'))->where(eq(col('active'), literal(true)))->toSql(), isUpdatable: false), + ]), + ]); + $target = new Catalog([ + schema('public', views: [ + schema_view('active_users', select(star())->from(table('users'))->where(eq(col('active'), literal(true)))->toSql(), isUpdatable: true), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->modifiedSchemas[0]->modifiedViews); + } + + public function test_view_modification_detected() : void + { + $source = new Catalog([ + schema('public', views: [ + schema_view('active_users', select(star())->from(table('users'))->where(eq(col('active'), literal(true)))->toSql()), + ]), + ]); + $target = new Catalog([ + schema('public', views: [ + schema_view('active_users', select(star())->from(table('users'))->where(and_(eq(col('active'), literal(true)), eq(col('verified'), literal(true))))->toSql()), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->modifiedSchemas[0]->modifiedViews); + } + + public function test_view_no_change_when_identical() : void + { + $source = new Catalog([ + schema('public', views: [ + schema_view('active_users', select(star())->from(table('users'))->where(eq(col('active'), literal(true)))->toSql(), true), + ]), + ]); + + $diff = (catalog_comparator())->compare($source, $source); + + self::assertTrue($diff->isEmpty()); + } + + public function test_view_removed() : void + { + $source = new Catalog([ + schema('public', views: [ + schema_view('active_users', select(star())->from(table('users'))->where(eq(col('active'), literal(true)))->toSql()), + ]), + ]); + $target = new Catalog([schema('public')]); + + $diff = (catalog_comparator())->compare($source, $target); + + self::assertCount(1, $diff->modifiedSchemas[0]->removedViews); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/CatalogDiffTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/CatalogDiffTest.php new file mode 100644 index 0000000000..a1e8ea2b0a --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/CatalogDiffTest.php @@ -0,0 +1,314 @@ +generate(); + + self::assertCount(1, $sqls); + self::assertSame('CREATE SCHEMA IF NOT EXISTS audit', $sqls[0]->toSql()); + } + + public function test_creates_added_schema_with_objects() : void + { + $source = new Catalog([schema('public')]); + + $auditSchema = schema( + 'audit', + tables: [schema_table('events', [schema_column_integer('id', false), schema_column_text('name')], schema: 'audit')], + sequences: [schema_sequence('events_id_seq')], + ); + + $target = new Catalog([schema('public'), $auditSchema]); + + $diff = new CatalogDiff($source, $target, addedSchemas: [$auditSchema]); + + $sqls = $diff->generate(); + + self::assertGreaterThanOrEqual(3, \count($sqls)); + self::assertSame('CREATE SCHEMA IF NOT EXISTS audit', $sqls[0]->toSql()); + self::assertStringContainsString('CREATE SEQUENCE', $sqls[1]->toSql()); + self::assertStringContainsString('events_id_seq', $sqls[1]->toSql()); + self::assertStringContainsString('CREATE TABLE', $sqls[2]->toSql()); + self::assertStringContainsString('events', $sqls[2]->toSql()); + } + + public function test_delegates_to_schema_diff() : void + { + $source = new Catalog([schema('public')]); + $target = new Catalog([schema('public')]); + + $table = schema_table('users', [schema_column_integer('id', false)]); + + $schemaDiff = new SchemaDiff( + schema('public'), + schema('public', tables: [$table]), + addedTables: [$table], + ); + + $diff = new CatalogDiff($source, $target, modifiedSchemas: [$schemaDiff]); + + $sqls = $diff->generate(); + + self::assertNotEmpty($sqls); + self::assertStringContainsString('CREATE TABLE', $sqls[0]->toSql()); + self::assertStringContainsString('users', $sqls[0]->toSql()); + } + + public function test_drops_removed_schema() : void + { + $source = new Catalog([schema('public'), schema('audit')]); + $target = new Catalog([schema('public')]); + + $diff = new CatalogDiff($source, $target, removedSchemas: [schema('audit')]); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('DROP SCHEMA audit CASCADE', $sqls[0]->toSql()); + } + + public function test_empty_diff() : void + { + $catalog = new Catalog([schema('public')]); + + $diff = new CatalogDiff($catalog, $catalog); + + self::assertTrue($diff->isEmpty()); + } + + public function test_handles_multiple_schemas() : void + { + $source = new Catalog([schema('public'), schema('old_schema')]); + $target = new Catalog([schema('public'), schema('new_schema')]); + + $diff = new CatalogDiff( + $source, + $target, + addedSchemas: [schema('new_schema')], + removedSchemas: [schema('old_schema')], + ); + + $sqls = $diff->generate(); + + self::assertCount(2, $sqls); + self::assertSame('CREATE SCHEMA IF NOT EXISTS new_schema', $sqls[0]->toSql()); + self::assertSame('DROP SCHEMA old_schema CASCADE', $sqls[1]->toSql()); + } + + public function test_not_empty_when_schema_added() : void + { + $source = new Catalog([schema('public')]); + $target = new Catalog([schema('public'), schema('audit')]); + + $diff = new CatalogDiff($source, $target, addedSchemas: [schema('audit')]); + + self::assertFalse($diff->isEmpty()); + } + + public function test_not_empty_when_schema_modified() : void + { + $source = new Catalog([schema('public')]); + $target = new Catalog([schema('public')]); + + $schemaDiff = new SchemaDiff( + schema('public'), + schema('public', tables: [schema_table('users', [schema_column_integer('id', false)])]), + addedTables: [schema_table('users', [schema_column_integer('id', false)])], + ); + + $diff = new CatalogDiff($source, $target, modifiedSchemas: [$schemaDiff]); + + self::assertFalse($diff->isEmpty()); + } + + public function test_not_empty_when_schema_removed() : void + { + $source = new Catalog([schema('public'), schema('audit')]); + $target = new Catalog([schema('public')]); + + $diff = new CatalogDiff($source, $target, removedSchemas: [schema('audit')]); + + self::assertFalse($diff->isEmpty()); + } + + public function test_ordering_added_before_modified_before_removed() : void + { + $table = schema_table('users', [schema_column_integer('id', false)]); + + $schemaDiff = new SchemaDiff( + schema('existing'), + schema('existing', tables: [$table]), + addedTables: [$table], + ); + + $diff = new CatalogDiff( + new Catalog([schema('public'), schema('existing'), schema('old')]), + new Catalog([schema('new'), schema('existing'), schema('public')]), + addedSchemas: [schema('new')], + removedSchemas: [schema('old')], + modifiedSchemas: [$schemaDiff], + ); + + $sqls = $diff->generate(); + + self::assertSame('CREATE SCHEMA IF NOT EXISTS new', $sqls[0]->toSql()); + + $createTableIdx = null; + $dropSchemaIdx = null; + + foreach ($sqls as $i => $sql) { + if (\str_contains($sql->toSql(), 'CREATE TABLE') && $createTableIdx === null) { + $createTableIdx = $i; + } + + if (\str_contains($sql->toSql(), 'DROP SCHEMA old CASCADE') && $dropSchemaIdx === null) { + $dropSchemaIdx = $i; + } + } + + self::assertNotNull($createTableIdx); + self::assertNotNull($dropSchemaIdx); + self::assertGreaterThan($createTableIdx, $dropSchemaIdx); + } + + public function test_returns_empty_when_no_changes() : void + { + $catalog = new Catalog([]); + + $diff = new CatalogDiff($catalog, $catalog); + + self::assertSame([], $diff->generate()); + } + + public function test_reversed_added_schema() : void + { + $source = new Catalog([schema('public'), schema('audit')]); + $target = new Catalog([schema('public')]); + + $diff = new CatalogDiff($source, $target, removedSchemas: [schema('audit')]); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('DROP SCHEMA audit CASCADE', $sqls[0]->toSql()); + } + + public function test_reversed_creates_removed_schema() : void + { + $auditSchema = schema( + 'audit', + tables: [schema_table('events', [schema_column_integer('id', false)], schema: 'audit')], + ); + + $source = new Catalog([schema('public')]); + $target = new Catalog([schema('public'), $auditSchema]); + + $diff = new CatalogDiff($source, $target, addedSchemas: [$auditSchema]); + + $sqls = $diff->generate(); + + self::assertGreaterThanOrEqual(2, \count($sqls)); + self::assertSame('CREATE SCHEMA IF NOT EXISTS audit', $sqls[0]->toSql()); + self::assertStringContainsString('CREATE TABLE', $sqls[1]->toSql()); + self::assertStringContainsString('events', $sqls[1]->toSql()); + } + + public function test_reversed_creates_removed_schema_with_sequence() : void + { + $auditSchema = schema( + 'audit', + tables: [schema_table('events', [schema_column_integer('id', false)], schema: 'audit')], + sequences: [schema_sequence('events_id_seq')], + ); + + $source = new Catalog([schema('public')]); + $target = new Catalog([schema('public'), $auditSchema]); + + $diff = new CatalogDiff($source, $target, addedSchemas: [$auditSchema]); + + $sqls = $diff->generate(); + + self::assertSame('CREATE SCHEMA IF NOT EXISTS audit', $sqls[0]->toSql()); + self::assertStringContainsString('CREATE SEQUENCE', $sqls[1]->toSql()); + self::assertStringContainsString('events_id_seq', $sqls[1]->toSql()); + self::assertStringContainsString('CREATE TABLE', $sqls[2]->toSql()); + } + + public function test_reversed_delegates_to_schema_diff() : void + { + $source = new Catalog([schema('public')]); + $target = new Catalog([schema('public')]); + + $table = schema_table('users', [schema_column_integer('id', false)]); + + $schemaDiff = new SchemaDiff( + schema('public', tables: [$table]), + schema('public'), + removedTables: [$table], + ); + + $diff = new CatalogDiff($target, $source, modifiedSchemas: [$schemaDiff]); + + $sqls = $diff->generate(); + + self::assertNotEmpty($sqls); + self::assertStringContainsString('DROP TABLE', $sqls[0]->toSql()); + } + + public function test_reversed_ordering_added_before_modified_before_removed() : void + { + $table = schema_table('users', [schema_column_integer('id', false)]); + + $schemaDiff = new SchemaDiff( + schema('existing', tables: [$table]), + schema('existing'), + removedTables: [$table], + ); + + $diff = new CatalogDiff( + new Catalog([schema('new'), schema('existing'), schema('public')]), + new Catalog([schema('public'), schema('existing'), schema('old')]), + addedSchemas: [schema('old')], + removedSchemas: [schema('new')], + modifiedSchemas: [$schemaDiff], + ); + + $sqls = $diff->generate(); + + self::assertSame('CREATE SCHEMA IF NOT EXISTS old', $sqls[0]->toSql()); + + $dropTableIdx = null; + $dropSchemaIdx = null; + + foreach ($sqls as $i => $sql) { + if (\str_contains($sql->toSql(), 'DROP TABLE') && $dropTableIdx === null) { + $dropTableIdx = $i; + } + + if (\str_contains($sql->toSql(), 'DROP SCHEMA new CASCADE') && $dropSchemaIdx === null) { + $dropSchemaIdx = $i; + } + } + + self::assertNotNull($dropTableIdx); + self::assertNotNull($dropSchemaIdx); + self::assertGreaterThan($dropTableIdx, $dropSchemaIdx); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/CatalogDiffViewRebuildTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/CatalogDiffViewRebuildTest.php new file mode 100644 index 0000000000..619c427585 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/CatalogDiffViewRebuildTest.php @@ -0,0 +1,264 @@ +get('data'), + $target->get('data'), + modifiedTables: [ + new TableDiff( + $sourceTable, + $targetTable, + modifiedColumns: [new ColumnDiff('data.events', schema_column_integer('amount'), schema_column_bigint('amount'))], + ), + ], + ), + ], + viewDependencyResolver: ast_view_dependency_resolver(), + ); + + $sqls = \array_map(static fn ($q) => $q->toSql(), $diff->generate()); + + self::assertSame('DROP VIEW public.dashboard', $sqls[0]); + self::assertSame('DROP VIEW report.event_summary', $sqls[1]); + self::assertStringContainsString('ALTER TABLE data.events ALTER COLUMN amount TYPE bigint', $sqls[2]); + self::assertSame('CREATE VIEW report.event_summary AS SELECT * FROM data.events', $sqls[3]); + self::assertSame('CREATE VIEW public.dashboard AS SELECT * FROM report.event_summary', $sqls[4]); + } + + public function test_materialized_view_dropped_and_recreated_when_dependent_table_changes() : void + { + $sourceTable = schema_table('orders', [schema_column_integer('id', false), schema_column_integer('total')]); + $targetTable = schema_table('orders', [schema_column_integer('id', false), schema_column_bigint('total')]); + + $source = new Catalog([ + schema('public', tables: [$sourceTable], materializedViews: [schema_materialized_view('mv_order_stats', 'SELECT * FROM orders')]), + ]); + + $target = new Catalog([ + schema('public', tables: [$targetTable], materializedViews: [schema_materialized_view('mv_order_stats', 'SELECT * FROM orders')]), + ]); + + $diff = new CatalogDiff( + $source, + $target, + modifiedSchemas: [ + new SchemaDiff( + $source->get('public'), + $target->get('public'), + modifiedTables: [ + new TableDiff( + $sourceTable, + $targetTable, + modifiedColumns: [new ColumnDiff('public.orders', schema_column_integer('total'), schema_column_bigint('total'))], + ), + ], + ), + ], + viewDependencyResolver: ast_view_dependency_resolver(), + ); + + $sqls = \array_map(static fn ($q) => $q->toSql(), $diff->generate()); + + self::assertSame('DROP MATERIALIZED VIEW public.mv_order_stats', $sqls[0]); + self::assertStringContainsString('ALTER TABLE public.orders ALTER COLUMN total TYPE bigint', $sqls[1]); + self::assertSame('CREATE MATERIALIZED VIEW public.mv_order_stats AS SELECT * FROM orders', $sqls[2]); + } + + public function test_noop_resolver_skips_view_rebuild_even_when_table_column_type_changes() : void + { + $sourceTable = schema_table('data', [schema_column_integer('id', false), schema_column_integer('amount')]); + $targetTable = schema_table('data', [schema_column_integer('id', false), schema_column_bigint('amount')]); + + $source = new Catalog([ + schema('public', tables: [$sourceTable], views: [schema_view('all_data', 'SELECT * FROM data')]), + ]); + + $target = new Catalog([ + schema('public', tables: [$targetTable], views: [schema_view('all_data', 'SELECT * FROM data')]), + ]); + + $diff = new CatalogDiff( + $source, + $target, + modifiedSchemas: [ + new SchemaDiff( + $source->get('public'), + $target->get('public'), + modifiedTables: [ + new TableDiff( + $sourceTable, + $targetTable, + modifiedColumns: [new ColumnDiff('public.data', schema_column_integer('amount'), schema_column_bigint('amount'))], + ), + ], + ), + ], + viewDependencyResolver: noop_view_dependency_resolver(), + ); + + $sqls = \array_map(static fn ($q) => $q->toSql(), $diff->generate()); + + self::assertCount(1, $sqls); + self::assertStringContainsString('ALTER TABLE public.data ALTER COLUMN amount TYPE bigint', $sqls[0]); + } + + public function test_view_dropped_and_recreated_when_dependent_table_column_type_changes() : void + { + $sourceTable = schema_table('full_data', [schema_column_integer('id', false), schema_column_integer('amount')], schema: 'enriched'); + $targetTable = schema_table('full_data', [schema_column_integer('id', false), schema_column_bigint('amount')], schema: 'enriched'); + + $source = new Catalog([ + schema('enriched', tables: [$sourceTable]), + schema('public', views: [schema_view('enriched_full_data', 'SELECT * FROM enriched.full_data')]), + ]); + + $target = new Catalog([ + schema('enriched', tables: [$targetTable]), + schema('public', views: [schema_view('enriched_full_data', 'SELECT * FROM enriched.full_data')]), + ]); + + $diff = new CatalogDiff( + $source, + $target, + modifiedSchemas: [ + new SchemaDiff( + $source->get('enriched'), + $target->get('enriched'), + modifiedTables: [ + new TableDiff( + $sourceTable, + $targetTable, + modifiedColumns: [new ColumnDiff('enriched.full_data', schema_column_integer('amount'), schema_column_bigint('amount'))], + ), + ], + ), + ], + viewDependencyResolver: ast_view_dependency_resolver(), + ); + + $sqls = \array_map(static fn ($q) => $q->toSql(), $diff->generate()); + + self::assertSame('DROP VIEW public.enriched_full_data', $sqls[0]); + self::assertStringContainsString('ALTER TABLE enriched.full_data ALTER COLUMN amount TYPE bigint', $sqls[1]); + self::assertSame('CREATE VIEW public.enriched_full_data AS SELECT * FROM enriched.full_data', $sqls[2]); + } + + public function test_view_not_affected_when_unrelated_table_modified() : void + { + $sourceTable = schema_table('orders', [schema_column_integer('id', false), schema_column_integer('amount')]); + $targetTable = schema_table('orders', [schema_column_integer('id', false), schema_column_bigint('amount')]); + + $source = new Catalog([ + schema( + 'public', + tables: [$sourceTable, schema_table('users', [schema_column_integer('id', false)])], + views: [schema_view('active_users', 'SELECT * FROM users')], + ), + ]); + + $target = new Catalog([ + schema( + 'public', + tables: [$targetTable, schema_table('users', [schema_column_integer('id', false)])], + views: [schema_view('active_users', 'SELECT * FROM users')], + ), + ]); + + $diff = new CatalogDiff( + $source, + $target, + modifiedSchemas: [ + new SchemaDiff( + $source->get('public'), + $target->get('public'), + modifiedTables: [ + new TableDiff( + $sourceTable, + $targetTable, + modifiedColumns: [new ColumnDiff('public.orders', schema_column_integer('amount'), schema_column_bigint('amount'))], + ), + ], + ), + ], + viewDependencyResolver: ast_view_dependency_resolver(), + ); + + $sqls = \array_map(static fn ($q) => $q->toSql(), $diff->generate()); + + foreach ($sqls as $sql) { + self::assertStringNotContainsString('DROP VIEW', $sql); + self::assertStringNotContainsString('CREATE VIEW', $sql); + } + } + + public function test_view_not_dropped_when_table_only_adds_column() : void + { + $sourceTable = schema_table('users', [schema_column_integer('id', false)]); + $targetTable = schema_table('users', [schema_column_integer('id', false), schema_column_text('name')]); + + $source = new Catalog([ + schema('public', tables: [$sourceTable], views: [schema_view('all_users', 'SELECT * FROM users')]), + ]); + + $target = new Catalog([ + schema('public', tables: [$targetTable], views: [schema_view('all_users', 'SELECT * FROM users')]), + ]); + + $diff = new CatalogDiff( + $source, + $target, + modifiedSchemas: [ + new SchemaDiff( + $source->get('public'), + $target->get('public'), + modifiedTables: [ + new TableDiff($sourceTable, $targetTable, addedColumns: [new Column('name', ColumnType::text(), true)]), + ], + ), + ], + viewDependencyResolver: ast_view_dependency_resolver(), + ); + + $sqls = \array_map(static fn ($q) => $q->toSql(), $diff->generate()); + + foreach ($sqls as $sql) { + self::assertStringNotContainsString('DROP VIEW', $sql); + } + + self::assertCount(1, $sqls); + self::assertSame('ALTER TABLE public.users ADD COLUMN name pg_catalog.text', $sqls[0]); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/ChangeSetTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/ChangeSetTest.php new file mode 100644 index 0000000000..105a87057e --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/ChangeSetTest.php @@ -0,0 +1,186 @@ +added); + self::assertSame(['c'], $changeSet->removed); + self::assertNull($changeSet->modified); + self::assertNull($changeSet->renamed); + } + + public function test_constructor_with_all_properties() : void + { + $changeSet = new ChangeSet(['a'], ['b'], ['diff_ab'], ['old' => 'new']); + + self::assertSame(['a'], $changeSet->added); + self::assertSame(['b'], $changeSet->removed); + self::assertSame(['diff_ab'], $changeSet->modified); + self::assertSame(['old' => 'new'], $changeSet->renamed); + } + + public function test_constructor_with_empty_lists() : void + { + $changeSet = new ChangeSet([], []); + + self::assertSame([], $changeSet->added); + self::assertSame([], $changeSet->removed); + self::assertNull($changeSet->modified); + self::assertNull($changeSet->renamed); + } + + public function test_from_named_objects_detects_added() : void + { + $result = ChangeSet::fromNamedObjects( + [], + [['name' => 'a'], ['name' => 'b']], + static fn (array $item) : string => $item['name'], + ); + + self::assertCount(2, $result->added); + self::assertSame([], $result->removed); + } + + public function test_from_named_objects_detects_added_removed_and_modified_simultaneously() : void + { + $source = [ + ['name' => 'keep', 'value' => 1], + ['name' => 'modify', 'value' => 10], + ['name' => 'remove', 'value' => 99], + ]; + $target = [ + ['name' => 'keep', 'value' => 1], + ['name' => 'modify', 'value' => 20], + ['name' => 'add', 'value' => 50], + ]; + + $result = ChangeSet::fromNamedObjects( + $source, + $target, + static fn (array $item) : string => $item['name'], + static fn (array $a, array $b) : ?string => $a['value'] === $b['value'] ? null : 'modified:' . $a['name'], + ); + + self::assertCount(1, $result->added); + self::assertSame('add', $result->added[0]['name']); + self::assertCount(1, $result->removed); + self::assertSame('remove', $result->removed[0]['name']); + self::assertSame(['modified:modify'], $result->modified); + } + + public function test_from_named_objects_detects_modified() : void + { + $source = [['name' => 'a', 'value' => 1]]; + $target = [['name' => 'a', 'value' => 2]]; + + $result = ChangeSet::fromNamedObjects( + $source, + $target, + static fn (array $item) : string => $item['name'], + static fn (array $a, array $b) : ?string => $a['value'] === $b['value'] ? null : 'value_changed', + ); + + self::assertSame([], $result->added); + self::assertSame([], $result->removed); + self::assertSame(['value_changed'], $result->modified); + } + + public function test_from_named_objects_detects_removed() : void + { + $result = ChangeSet::fromNamedObjects( + [['name' => 'a'], ['name' => 'b']], + [], + static fn (array $item) : string => $item['name'], + ); + + self::assertSame([], $result->added); + self::assertCount(2, $result->removed); + } + + public function test_from_named_objects_modified_returns_null_when_all_equal() : void + { + $items = [['name' => 'a', 'value' => 1]]; + + $result = ChangeSet::fromNamedObjects( + $items, + $items, + static fn (array $item) : string => $item['name'], + static fn (array $a, array $b) : ?string => $a === $b ? null : 'diff', + ); + + self::assertNull($result->modified); + } + + public function test_from_named_objects_no_changes_for_identical() : void + { + $items = [['name' => 'a', 'value' => 1], ['name' => 'b', 'value' => 2]]; + + $result = ChangeSet::fromNamedObjects( + $items, + $items, + static fn (array $item) : string => $item['name'], + static fn (array $a, array $b) : ?string => $a === $b ? null : 'changed', + ); + + self::assertSame([], $result->added); + self::assertSame([], $result->removed); + self::assertNull($result->modified); + } + + public function test_from_named_objects_uses_identity_function_for_matching() : void + { + $source = [['id' => 'x', 'label' => 'old']]; + $target = [['id' => 'x', 'label' => 'new']]; + + $result = ChangeSet::fromNamedObjects( + $source, + $target, + static fn (array $item) : string => $item['id'], + static fn (array $a, array $b) : ?string => $a['label'] === $b['label'] ? null : 'label_changed', + ); + + self::assertSame([], $result->added); + self::assertSame([], $result->removed); + self::assertSame(['label_changed'], $result->modified); + } + + public function test_from_named_objects_with_empty_collections() : void + { + $result = ChangeSet::fromNamedObjects( + [], + [], + static fn (array $item) : string => $item['name'], + static fn (array $a, array $b) : ?string => null, + ); + + self::assertSame([], $result->added); + self::assertSame([], $result->removed); + self::assertNull($result->modified); + } + + public function test_from_named_objects_without_modified_fn() : void + { + $source = [['name' => 'a', 'value' => 1]]; + $target = [['name' => 'a', 'value' => 2]]; + + $result = ChangeSet::fromNamedObjects( + $source, + $target, + static fn (array $item) : string => $item['name'], + ); + + self::assertSame([], $result->added); + self::assertSame([], $result->removed); + self::assertNull($result->modified); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/ColumnDiffTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/ColumnDiffTest.php new file mode 100644 index 0000000000..3ba79f5571 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/ColumnDiffTest.php @@ -0,0 +1,409 @@ +generate(); + + self::assertCount(2, $sqls); + self::assertSame('ALTER TABLE public.users DROP full_name', $sqls[0]->toSql()); + self::assertSame('ALTER TABLE public.users ADD COLUMN full_name pg_catalog.text GENERATED ALWAYS AS (first_name || last_name) STORED', $sqls[1]->toSql()); + } + + public function test_adds_identity_column() : void + { + $diff = new ColumnDiff( + 'public.users', + new Column('id', ColumnType::integer(), false), + new Column('id', ColumnType::integer(), false, isIdentity: true, identityGeneration: IdentityGeneration::ALWAYS), + ); + + $sqls = $diff->generate(); + + self::assertCount(2, $sqls); + self::assertSame('ALTER TABLE public.users DROP id', $sqls[0]->toSql()); + self::assertSame('ALTER TABLE public.users ADD COLUMN id int NOT NULL GENERATED ALWAYS AS IDENTITY', $sqls[1]->toSql()); + } + + public function test_changes_generation_expression() : void + { + $diff = new ColumnDiff( + 'public.users', + new Column('full_name', ColumnType::text(), true, isGenerated: true, generationExpression: 'first_name || last_name'), + new Column('full_name', ColumnType::text(), true, isGenerated: true, generationExpression: 'upper(first_name || last_name)'), + ); + + $sqls = $diff->generate(); + + self::assertCount(2, $sqls); + self::assertSame('ALTER TABLE public.users DROP full_name', $sqls[0]->toSql()); + self::assertSame('ALTER TABLE public.users ADD COLUMN full_name pg_catalog.text GENERATED ALWAYS AS (upper(first_name || last_name)) STORED', $sqls[1]->toSql()); + } + + public function test_changes_identity_generation_type() : void + { + $diff = new ColumnDiff( + 'public.users', + new Column('id', ColumnType::integer(), false, isIdentity: true, identityGeneration: IdentityGeneration::ALWAYS), + new Column('id', ColumnType::integer(), false, isIdentity: true, identityGeneration: IdentityGeneration::BY_DEFAULT), + ); + + $sqls = $diff->generate(); + + self::assertCount(2, $sqls); + self::assertSame('ALTER TABLE public.users DROP id', $sqls[0]->toSql()); + self::assertSame('ALTER TABLE public.users ADD COLUMN id int NOT NULL GENERATED BY DEFAULT AS IDENTITY', $sqls[1]->toSql()); + } + + public function test_changes_type() : void + { + $diff = new ColumnDiff( + 'public.users', + new Column('col', ColumnType::text(), true), + new Column('col', ColumnType::integer(), true), + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER TABLE public.users ALTER COLUMN col TYPE int', $sqls[0]->toSql()); + } + + public function test_detects_default_change() : void + { + $diff = new ColumnDiff( + 'public.test_table', + new Column('col', ColumnType::text(), true, 'old_default'), + new Column('col', ColumnType::text(), true, 'new_default'), + ); + + self::assertTrue($diff->hasDefaultChanged()); + self::assertFalse($diff->hasTypeChanged()); + self::assertFalse($diff->hasNullableChanged()); + self::assertFalse($diff->hasNameChanged()); + } + + public function test_detects_generation_change() : void + { + $diff = new ColumnDiff( + 'public.test_table', + new Column('col', ColumnType::text(), true, isGenerated: false), + new Column('col', ColumnType::text(), true, isGenerated: true, generationExpression: 'upper(name)'), + ); + + self::assertTrue($diff->hasGenerationChanged()); + } + + public function test_detects_identity_change() : void + { + $diff = new ColumnDiff( + 'public.test_table', + new Column('col', ColumnType::integer(), false, isIdentity: false), + new Column('col', ColumnType::integer(), false, isIdentity: true, identityGeneration: IdentityGeneration::ALWAYS), + ); + + self::assertTrue($diff->hasIdentityChanged()); + } + + public function test_detects_name_change() : void + { + $diff = new ColumnDiff( + 'public.test_table', + new Column('old_name', ColumnType::text(), true), + new Column('new_name', ColumnType::text(), true), + ); + + self::assertTrue($diff->hasNameChanged()); + self::assertFalse($diff->hasTypeChanged()); + self::assertFalse($diff->hasNullableChanged()); + self::assertFalse($diff->hasDefaultChanged()); + } + + public function test_detects_nullable_change() : void + { + $diff = new ColumnDiff( + 'public.test_table', + new Column('col', ColumnType::text(), true), + new Column('col', ColumnType::text(), false), + ); + + self::assertTrue($diff->hasNullableChanged()); + self::assertFalse($diff->hasTypeChanged()); + } + + public function test_detects_type_change() : void + { + $diff = new ColumnDiff( + 'public.test_table', + new Column('col', ColumnType::integer(), true), + new Column('col', ColumnType::text(), true), + ); + + self::assertTrue($diff->hasTypeChanged()); + self::assertFalse($diff->hasNullableChanged()); + } + + public function test_drops_default() : void + { + $diff = new ColumnDiff( + 'public.users', + new Column('col', ColumnType::text(), true, '42'), + new Column('col', ColumnType::text(), true, null), + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER TABLE public.users ALTER COLUMN col DROP DEFAULT', $sqls[0]->toSql()); + } + + public function test_drops_not_null() : void + { + $diff = new ColumnDiff( + 'public.users', + new Column('col', ColumnType::text(), false), + new Column('col', ColumnType::text(), true), + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER TABLE public.users ALTER COLUMN col DROP NOT NULL', $sqls[0]->toSql()); + } + + public function test_generated_column_with_not_null() : void + { + $diff = new ColumnDiff( + 'public.users', + new Column('computed', ColumnType::text(), true), + new Column('computed', ColumnType::text(), false, isGenerated: true, generationExpression: 'upper(name)'), + ); + + $sqls = $diff->generate(); + + self::assertCount(2, $sqls); + self::assertSame('ALTER TABLE public.users DROP computed', $sqls[0]->toSql()); + self::assertSame('ALTER TABLE public.users ADD COLUMN computed pg_catalog.text NOT NULL GENERATED ALWAYS AS (upper(name)) STORED', $sqls[1]->toSql()); + } + + public function test_handles_multiple_changes_type_nullable_default() : void + { + $diff = new ColumnDiff( + 'public.users', + new Column('col', ColumnType::text(), true, null), + new Column('col', ColumnType::integer(), false, '0'), + ); + + $sqls = $diff->generate(); + + self::assertCount(3, $sqls); + self::assertSame('ALTER TABLE public.users ALTER COLUMN col TYPE int', $sqls[0]->toSql()); + self::assertSame('ALTER TABLE public.users ALTER COLUMN col SET NOT NULL', $sqls[1]->toSql()); + self::assertSame('ALTER TABLE public.users ALTER COLUMN col SET DEFAULT 0', $sqls[2]->toSql()); + } + + public function test_handles_rename_and_type_change() : void + { + $diff = new ColumnDiff( + 'public.users', + new Column('old_name', ColumnType::text(), true), + new Column('new_name', ColumnType::integer(), true), + ); + + $sqls = $diff->generate(); + + self::assertCount(2, $sqls); + self::assertSame('ALTER TABLE public.users RENAME COLUMN old_name TO new_name', $sqls[0]->toSql()); + self::assertSame('ALTER TABLE public.users ALTER COLUMN new_name TYPE int', $sqls[1]->toSql()); + } + + public function test_handles_rename_with_generation_change() : void + { + $diff = new ColumnDiff( + 'public.users', + new Column('old_name', ColumnType::text(), true), + new Column('new_name', ColumnType::text(), true, isGenerated: true, generationExpression: 'upper(name)'), + ); + + $sqls = $diff->generate(); + + self::assertCount(3, $sqls); + self::assertSame('ALTER TABLE public.users RENAME COLUMN old_name TO new_name', $sqls[0]->toSql()); + self::assertSame('ALTER TABLE public.users DROP new_name', $sqls[1]->toSql()); + self::assertSame('ALTER TABLE public.users ADD COLUMN new_name pg_catalog.text GENERATED ALWAYS AS (upper(name)) STORED', $sqls[2]->toSql()); + } + + public function test_identity_with_default_and_not_null() : void + { + $diff = new ColumnDiff( + 'public.users', + new Column('id', ColumnType::integer(), true), + new Column('id', ColumnType::integer(), false, default: '0', isIdentity: true, identityGeneration: IdentityGeneration::BY_DEFAULT), + ); + + $sqls = $diff->generate(); + + self::assertCount(2, $sqls); + self::assertSame('ALTER TABLE public.users DROP id', $sqls[0]->toSql()); + self::assertSame('ALTER TABLE public.users ADD COLUMN id int NOT NULL DEFAULT 0 GENERATED BY DEFAULT AS IDENTITY', $sqls[1]->toSql()); + } + + public function test_no_changes_when_identical() : void + { + $diff = new ColumnDiff( + 'public.test_table', + new Column('col', ColumnType::text(), true, 'default_val'), + new Column('col', ColumnType::text(), true, 'default_val'), + ); + + self::assertFalse($diff->hasNameChanged()); + self::assertFalse($diff->hasTypeChanged()); + self::assertFalse($diff->hasNullableChanged()); + self::assertFalse($diff->hasDefaultChanged()); + self::assertFalse($diff->hasIdentityChanged()); + self::assertFalse($diff->hasGenerationChanged()); + } + + public function test_removes_generation_from_column() : void + { + $diff = new ColumnDiff( + 'public.users', + new Column('full_name', ColumnType::text(), true, isGenerated: true, generationExpression: 'first_name || last_name'), + new Column('full_name', ColumnType::text(), true), + ); + + $sqls = $diff->generate(); + + self::assertCount(2, $sqls); + self::assertSame('ALTER TABLE public.users DROP full_name', $sqls[0]->toSql()); + self::assertSame('ALTER TABLE public.users ADD COLUMN full_name pg_catalog.text', $sqls[1]->toSql()); + } + + public function test_removes_identity_from_column() : void + { + $diff = new ColumnDiff( + 'public.users', + new Column('id', ColumnType::integer(), false, isIdentity: true, identityGeneration: IdentityGeneration::ALWAYS), + new Column('id', ColumnType::integer(), false), + ); + + $sqls = $diff->generate(); + + self::assertCount(2, $sqls); + self::assertSame('ALTER TABLE public.users DROP id', $sqls[0]->toSql()); + self::assertSame('ALTER TABLE public.users ADD COLUMN id int NOT NULL', $sqls[1]->toSql()); + } + + public function test_renames_column() : void + { + $diff = new ColumnDiff( + 'public.users', + new Column('old_name', ColumnType::text(), true), + new Column('new_name', ColumnType::text(), true), + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER TABLE public.users RENAME COLUMN old_name TO new_name', $sqls[0]->toSql()); + } + + public function test_returns_empty_when_no_changes() : void + { + $diff = new ColumnDiff( + 'public.users', + new Column('col', ColumnType::text(), true), + new Column('col', ColumnType::text(), true), + ); + + self::assertSame([], $diff->generate()); + } + + public function test_reversed_generation_change() : void + { + $diff = new ColumnDiff( + 'public.users', + new Column('full_name', ColumnType::text(), true, isGenerated: true, generationExpression: 'upper(name)'), + new Column('full_name', ColumnType::text(), true), + ); + + $sqls = $diff->generate(); + + self::assertCount(2, $sqls); + self::assertSame('ALTER TABLE public.users DROP full_name', $sqls[0]->toSql()); + self::assertSame('ALTER TABLE public.users ADD COLUMN full_name pg_catalog.text', $sqls[1]->toSql()); + } + + public function test_reversed_identity_change() : void + { + $diff = new ColumnDiff( + 'public.users', + new Column('id', ColumnType::integer(), false, isIdentity: true, identityGeneration: IdentityGeneration::ALWAYS), + new Column('id', ColumnType::integer(), false), + ); + + $sqls = $diff->generate(); + + self::assertCount(2, $sqls); + self::assertSame('ALTER TABLE public.users DROP id', $sqls[0]->toSql()); + self::assertSame('ALTER TABLE public.users ADD COLUMN id int NOT NULL', $sqls[1]->toSql()); + } + + public function test_reversed_type_change() : void + { + $diff = new ColumnDiff( + 'public.users', + new Column('col', ColumnType::integer(), true), + new Column('col', ColumnType::text(), true), + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER TABLE public.users ALTER COLUMN col TYPE pg_catalog.text', $sqls[0]->toSql()); + } + + public function test_sets_default() : void + { + $diff = new ColumnDiff( + 'public.users', + new Column('col', ColumnType::text(), true, null), + new Column('col', ColumnType::text(), true, '42'), + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER TABLE public.users ALTER COLUMN col SET DEFAULT 42', $sqls[0]->toSql()); + } + + public function test_sets_not_null() : void + { + $diff = new ColumnDiff( + 'public.users', + new Column('col', ColumnType::text(), true), + new Column('col', ColumnType::text(), false), + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER TABLE public.users ALTER COLUMN col SET NOT NULL', $sqls[0]->toSql()); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/ConstraintComparatorTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/ConstraintComparatorTest.php new file mode 100644 index 0000000000..c9cef48663 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/ConstraintComparatorTest.php @@ -0,0 +1,383 @@ +diffCheckConstraints( + [], + [new CheckConstraint('age > 0', 'chk_age')], + ); + + self::assertCount(1, $result->added); + self::assertSame('chk_age', $result->added[0]->name); + self::assertSame([], $result->removed); + } + + public function test_check_constraint_modified_expression() : void + { + $comparator = new ConstraintComparator(); + + $result = $comparator->diffCheckConstraints( + [new CheckConstraint('age > 0', 'chk_age')], + [new CheckConstraint('age > 18', 'chk_age')], + ); + + self::assertCount(1, $result->added); + self::assertSame('age > 18', $result->added[0]->expression); + self::assertCount(1, $result->removed); + } + + public function test_check_constraint_modified_no_inherit() : void + { + $comparator = new ConstraintComparator(); + + $result = $comparator->diffCheckConstraints( + [new CheckConstraint('age > 0', 'chk_age', noInherit: false)], + [new CheckConstraint('age > 0', 'chk_age', noInherit: true)], + ); + + self::assertCount(1, $result->added); + self::assertTrue($result->added[0]->noInherit); + self::assertCount(1, $result->removed); + } + + public function test_check_constraint_removed() : void + { + $comparator = new ConstraintComparator(); + + $result = $comparator->diffCheckConstraints( + [new CheckConstraint('age > 0', 'chk_age')], + [], + ); + + self::assertSame([], $result->added); + self::assertCount(1, $result->removed); + } + + public function test_exclude_constraint_added() : void + { + $comparator = new ConstraintComparator(); + + $result = $comparator->diffExcludeConstraints( + [], + [new ExcludeConstraint('USING gist (range WITH &&)', 'excl_range')], + ); + + self::assertCount(1, $result->added); + self::assertSame('excl_range', $result->added[0]->name); + self::assertSame([], $result->removed); + } + + public function test_exclude_constraint_modified_definition() : void + { + $comparator = new ConstraintComparator(); + + $result = $comparator->diffExcludeConstraints( + [new ExcludeConstraint('USING gist (range WITH &&)', 'excl_range')], + [new ExcludeConstraint('USING gist (period WITH &&)', 'excl_range')], + ); + + self::assertCount(1, $result->added); + self::assertSame('USING gist (period WITH &&)', $result->added[0]->definition); + self::assertCount(1, $result->removed); + } + + public function test_exclude_constraint_removed() : void + { + $comparator = new ConstraintComparator(); + + $result = $comparator->diffExcludeConstraints( + [new ExcludeConstraint('USING gist (range WITH &&)', 'excl_range')], + [], + ); + + self::assertSame([], $result->added); + self::assertCount(1, $result->removed); + } + + public function test_foreign_key_added() : void + { + $comparator = new ConstraintComparator(); + + $result = $comparator->diffForeignKeys( + [], + [new ForeignKey('fk_user', ['user_id'], 'public', 'users', ['id'])], + ); + + self::assertCount(1, $result->added); + self::assertSame('fk_user', $result->added[0]->name); + self::assertSame([], $result->removed); + } + + public function test_foreign_key_identical() : void + { + $comparator = new ConstraintComparator(); + + $result = $comparator->diffForeignKeys( + [new ForeignKey('fk_user', ['user_id'], 'public', 'users', ['id'])], + [new ForeignKey('fk_user', ['user_id'], 'public', 'users', ['id'])], + ); + + self::assertSame([], $result->added); + self::assertSame([], $result->removed); + } + + public function test_foreign_key_modified_columns() : void + { + $comparator = new ConstraintComparator(); + + $result = $comparator->diffForeignKeys( + [new ForeignKey('fk_user', ['user_id'], 'public', 'users', ['id'])], + [new ForeignKey('fk_user', ['account_id'], 'public', 'users', ['id'])], + ); + + self::assertCount(1, $result->added); + self::assertSame(['account_id'], $result->added[0]->columns); + self::assertCount(1, $result->removed); + self::assertSame(['user_id'], $result->removed[0]->columns); + } + + public function test_foreign_key_modified_deferrable() : void + { + $comparator = new ConstraintComparator(); + + $result = $comparator->diffForeignKeys( + [new ForeignKey('fk_user', ['user_id'], 'public', 'users', ['id'], deferrable: false)], + [new ForeignKey('fk_user', ['user_id'], 'public', 'users', ['id'], deferrable: true)], + ); + + self::assertCount(1, $result->added); + self::assertTrue($result->added[0]->deferrable); + self::assertCount(1, $result->removed); + } + + public function test_foreign_key_modified_initially_deferred() : void + { + $comparator = new ConstraintComparator(); + + $result = $comparator->diffForeignKeys( + [new ForeignKey('fk_user', ['user_id'], 'public', 'users', ['id'], initiallyDeferred: false)], + [new ForeignKey('fk_user', ['user_id'], 'public', 'users', ['id'], initiallyDeferred: true)], + ); + + self::assertCount(1, $result->added); + self::assertTrue($result->added[0]->initiallyDeferred); + self::assertCount(1, $result->removed); + } + + public function test_foreign_key_modified_on_delete() : void + { + $comparator = new ConstraintComparator(); + + $result = $comparator->diffForeignKeys( + [new ForeignKey('fk_user', ['user_id'], 'public', 'users', ['id'], onDelete: ReferentialAction::NO_ACTION)], + [new ForeignKey('fk_user', ['user_id'], 'public', 'users', ['id'], onDelete: ReferentialAction::SET_NULL)], + ); + + self::assertCount(1, $result->added); + self::assertSame(ReferentialAction::SET_NULL, $result->added[0]->onDelete); + self::assertCount(1, $result->removed); + } + + public function test_foreign_key_modified_on_update() : void + { + $comparator = new ConstraintComparator(); + + $result = $comparator->diffForeignKeys( + [new ForeignKey('fk_user', ['user_id'], 'public', 'users', ['id'], onUpdate: ReferentialAction::NO_ACTION)], + [new ForeignKey('fk_user', ['user_id'], 'public', 'users', ['id'], onUpdate: ReferentialAction::CASCADE)], + ); + + self::assertCount(1, $result->added); + self::assertSame(ReferentialAction::CASCADE, $result->added[0]->onUpdate); + self::assertCount(1, $result->removed); + } + + public function test_foreign_key_modified_reference_columns() : void + { + $comparator = new ConstraintComparator(); + + $result = $comparator->diffForeignKeys( + [new ForeignKey('fk_user', ['user_id'], 'public', 'users', ['id'])], + [new ForeignKey('fk_user', ['user_id'], 'public', 'users', ['uuid'])], + ); + + self::assertCount(1, $result->added); + self::assertSame(['uuid'], $result->added[0]->referenceColumns); + self::assertCount(1, $result->removed); + } + + public function test_foreign_key_modified_reference_schema() : void + { + $comparator = new ConstraintComparator(); + + $result = $comparator->diffForeignKeys( + [new ForeignKey('fk_user', ['user_id'], 'public', 'users', ['id'])], + [new ForeignKey('fk_user', ['user_id'], 'audit', 'users', ['id'])], + ); + + self::assertCount(1, $result->added); + self::assertSame('audit', $result->added[0]->referenceSchema); + self::assertCount(1, $result->removed); + } + + public function test_foreign_key_modified_reference_table() : void + { + $comparator = new ConstraintComparator(); + + $result = $comparator->diffForeignKeys( + [new ForeignKey('fk_user', ['user_id'], 'public', 'users', ['id'])], + [new ForeignKey('fk_user', ['user_id'], 'public', 'accounts', ['id'])], + ); + + self::assertCount(1, $result->added); + self::assertSame('accounts', $result->added[0]->referenceTable); + self::assertCount(1, $result->removed); + } + + public function test_foreign_key_removed() : void + { + $comparator = new ConstraintComparator(); + + $result = $comparator->diffForeignKeys( + [new ForeignKey('fk_user', ['user_id'], 'public', 'users', ['id'])], + [], + ); + + self::assertSame([], $result->added); + self::assertCount(1, $result->removed); + self::assertSame('fk_user', $result->removed[0]->name); + } + + public function test_unique_constraint_added() : void + { + $comparator = new ConstraintComparator(); + + $result = $comparator->diffUniqueConstraints( + [], + [new UniqueConstraint(['email'], 'uq_email')], + ); + + self::assertCount(1, $result->added); + self::assertSame('uq_email', $result->added[0]->name); + self::assertSame([], $result->removed); + } + + public function test_unique_constraint_identical_columns_in_different_order() : void + { + $comparator = new ConstraintComparator(); + + $result = $comparator->diffUniqueConstraints( + [new UniqueConstraint(['a', 'b'], 'uq_ab')], + [new UniqueConstraint(['b', 'a'], 'uq_ab')], + ); + + self::assertSame([], $result->added); + self::assertSame([], $result->removed); + } + + public function test_unique_constraint_modified_columns() : void + { + $comparator = new ConstraintComparator(); + + $result = $comparator->diffUniqueConstraints( + [new UniqueConstraint(['email'], 'uq_email')], + [new UniqueConstraint(['username'], 'uq_email')], + ); + + self::assertCount(1, $result->added); + self::assertSame(['username'], $result->added[0]->columns); + self::assertCount(1, $result->removed); + } + + public function test_unique_constraint_modified_nulls_not_distinct() : void + { + $comparator = new ConstraintComparator(); + + $result = $comparator->diffUniqueConstraints( + [new UniqueConstraint(['email'], 'uq_email', nullsNotDistinct: false)], + [new UniqueConstraint(['email'], 'uq_email', nullsNotDistinct: true)], + ); + + self::assertCount(1, $result->added); + self::assertTrue($result->added[0]->nullsNotDistinct); + self::assertCount(1, $result->removed); + } + + public function test_unique_constraint_removed() : void + { + $comparator = new ConstraintComparator(); + + $result = $comparator->diffUniqueConstraints( + [new UniqueConstraint(['email'], 'uq_email')], + [], + ); + + self::assertSame([], $result->added); + self::assertCount(1, $result->removed); + } + + public function test_unnamed_check_constraint_matched_by_expression() : void + { + $comparator = new ConstraintComparator(); + + $result = $comparator->diffCheckConstraints( + [new CheckConstraint('age > 0')], + [new CheckConstraint('age > 0')], + ); + + self::assertSame([], $result->added); + self::assertSame([], $result->removed); + } + + public function test_unnamed_exclude_constraint_matched_by_definition() : void + { + $comparator = new ConstraintComparator(); + + $result = $comparator->diffExcludeConstraints( + [new ExcludeConstraint('USING gist (range WITH &&)')], + [new ExcludeConstraint('USING gist (range WITH &&)')], + ); + + self::assertSame([], $result->added); + self::assertSame([], $result->removed); + } + + public function test_unnamed_foreign_key_matched_by_structural_identity() : void + { + $comparator = new ConstraintComparator(); + + $result = $comparator->diffForeignKeys( + [new ForeignKey(null, ['user_id'], 'public', 'users', ['id'])], + [new ForeignKey(null, ['user_id'], 'public', 'users', ['id'])], + ); + + self::assertSame([], $result->added); + self::assertSame([], $result->removed); + } + + public function test_unnamed_unique_constraint_matched_by_columns() : void + { + $comparator = new ConstraintComparator(); + + $result = $comparator->diffUniqueConstraints( + [new UniqueConstraint(['email', 'tenant_id'])], + [new UniqueConstraint(['tenant_id', 'email'])], + ); + + self::assertSame([], $result->added); + self::assertSame([], $result->removed); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/DomainDiffTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/DomainDiffTest.php new file mode 100644 index 0000000000..5029d44c1f --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/DomainDiffTest.php @@ -0,0 +1,219 @@ + 0', 'positive_check')], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER DOMAIN positive_int ADD CONSTRAINT positive_check CHECK (value > 0)', $sqls[0]->toSql()); + } + + public function test_changes_default() : void + { + $diff = new DomainDiff( + schema_domain('email', ColumnType::text(), default: null), + schema_domain('email', ColumnType::text(), default: "'unknown'"), + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame("ALTER DOMAIN email SET DEFAULT 'unknown'", $sqls[0]->toSql()); + } + + public function test_changes_nullable() : void + { + $diff = new DomainDiff( + schema_domain('email', ColumnType::text(), nullable: true), + schema_domain('email', ColumnType::text(), nullable: false), + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER DOMAIN email SET NOT NULL', $sqls[0]->toSql()); + } + + public function test_drops_check_constraint() : void + { + $diff = new DomainDiff( + schema_domain('positive_int', ColumnType::integer()), + schema_domain('positive_int', ColumnType::integer()), + removedCheckConstraints: [new CheckConstraint('value > 0', 'positive_check')], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER DOMAIN positive_int DROP CONSTRAINT positive_check', $sqls[0]->toSql()); + } + + public function test_drops_default() : void + { + $diff = new DomainDiff( + schema_domain('email', ColumnType::text(), default: "'unknown'"), + schema_domain('email', ColumnType::text(), default: null), + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER DOMAIN email DROP DEFAULT', $sqls[0]->toSql()); + } + + public function test_has_base_type_changed_returns_false_when_same() : void + { + $diff = new DomainDiff( + schema_domain('email', ColumnType::text()), + schema_domain('email', ColumnType::text()), + ); + + self::assertFalse($diff->hasBaseTypeChanged()); + } + + public function test_has_base_type_changed_returns_true_when_different() : void + { + $diff = new DomainDiff( + schema_domain('positive_int', ColumnType::integer()), + schema_domain('positive_int', ColumnType::bigint()), + ); + + self::assertTrue($diff->hasBaseTypeChanged()); + } + + public function test_has_default_changed_returns_false_when_same() : void + { + $diff = new DomainDiff( + schema_domain('email', ColumnType::text(), default: 'unknown'), + schema_domain('email', ColumnType::text(), default: 'unknown'), + ); + + self::assertFalse($diff->hasDefaultChanged()); + } + + public function test_has_default_changed_returns_true_when_different() : void + { + $diff = new DomainDiff( + schema_domain('email', ColumnType::text(), default: 'unknown'), + schema_domain('email', ColumnType::text(), default: 'empty'), + ); + + self::assertTrue($diff->hasDefaultChanged()); + } + + public function test_has_nullable_changed_returns_false_when_same() : void + { + $diff = new DomainDiff( + schema_domain('email', ColumnType::text(), nullable: false), + schema_domain('email', ColumnType::text(), nullable: false), + ); + + self::assertFalse($diff->hasNullableChanged()); + } + + public function test_has_nullable_changed_returns_true_when_different() : void + { + $diff = new DomainDiff( + schema_domain('email', ColumnType::text(), nullable: true), + schema_domain('email', ColumnType::text(), nullable: false), + ); + + self::assertTrue($diff->hasNullableChanged()); + } + + public function test_recreates_when_base_type_changed() : void + { + $diff = new DomainDiff( + schema_domain('positive_int', ColumnType::integer()), + schema_domain('positive_int', ColumnType::bigint()), + ); + + $sqls = $diff->generate(); + + self::assertCount(2, $sqls); + self::assertSame('DROP DOMAIN positive_int CASCADE', $sqls[0]->toSql()); + self::assertSame('CREATE DOMAIN positive_int AS bigint', $sqls[1]->toSql()); + } + + public function test_recreates_with_all_properties_when_base_type_changed() : void + { + $diff = new DomainDiff( + schema_domain('positive_int', ColumnType::integer(), nullable: false, default: '0', checkConstraints: [new CheckConstraint('value >= 0', 'non_negative')]), + schema_domain('positive_int', ColumnType::bigint(), nullable: false, default: '0', checkConstraints: [new CheckConstraint('value >= 0', 'non_negative')]), + ); + + $sqls = $diff->generate(); + + self::assertCount(2, $sqls); + self::assertSame('DROP DOMAIN positive_int CASCADE', $sqls[0]->toSql()); + self::assertSame('CREATE DOMAIN positive_int AS bigint NOT NULL DEFAULT 0 CONSTRAINT non_negative CHECK (value >= 0)', $sqls[1]->toSql()); + } + + public function test_returns_empty_when_no_changes() : void + { + $diff = new DomainDiff( + schema_domain('email', ColumnType::text()), + schema_domain('email', ColumnType::text()), + ); + + self::assertSame([], $diff->generate()); + } + + public function test_reversed_nullable_change() : void + { + $diff = new DomainDiff( + schema_domain('email', ColumnType::text(), nullable: false), + schema_domain('email', ColumnType::text(), nullable: true), + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER DOMAIN email DROP NOT NULL', $sqls[0]->toSql()); + } + + public function test_throws_when_adding_unnamed_constraint() : void + { + $diff = new DomainDiff( + schema_domain('positive_int', ColumnType::integer()), + schema_domain('positive_int', ColumnType::integer()), + addedCheckConstraints: [new CheckConstraint('value > 0')], + ); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('Cannot add unnamed check constraint on domain "positive_int"'); + $diff->generate(); + } + + public function test_throws_when_dropping_unnamed_constraint() : void + { + $diff = new DomainDiff( + schema_domain('positive_int', ColumnType::integer()), + schema_domain('positive_int', ColumnType::integer()), + removedCheckConstraints: [new CheckConstraint('value > 0')], + ); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('Cannot drop unnamed check constraint on domain "positive_int"'); + $diff->generate(); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/ExtensionDiffTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/ExtensionDiffTest.php new file mode 100644 index 0000000000..36c4de82cf --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/ExtensionDiffTest.php @@ -0,0 +1,115 @@ +generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER EXTENSION "uuid-ossp" UPDATE TO "1.1"', $sqls[0]->toSql()); + } + + public function test_generates_alter_extension_update_when_target_version_null() : void + { + $diff = new ExtensionDiff( + schema_extension('uuid-ossp', '1.0'), + schema_extension('uuid-ossp'), + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER EXTENSION "uuid-ossp" UPDATE', $sqls[0]->toSql()); + } + + public function test_has_version_changed_returns_false_when_both_null() : void + { + $diff = new ExtensionDiff( + schema_extension('uuid-ossp'), + schema_extension('uuid-ossp'), + ); + + self::assertFalse($diff->hasVersionChanged()); + } + + public function test_has_version_changed_returns_false_when_same() : void + { + $diff = new ExtensionDiff( + schema_extension('uuid-ossp', '1.0'), + schema_extension('uuid-ossp', '1.0'), + ); + + self::assertFalse($diff->hasVersionChanged()); + } + + public function test_has_version_changed_returns_true_when_different() : void + { + $diff = new ExtensionDiff( + schema_extension('uuid-ossp', '1.0'), + schema_extension('uuid-ossp', '1.1'), + ); + + self::assertTrue($diff->hasVersionChanged()); + } + + public function test_has_version_changed_returns_true_when_null_to_value() : void + { + $diff = new ExtensionDiff( + schema_extension('uuid-ossp'), + schema_extension('uuid-ossp', '1.0'), + ); + + self::assertTrue($diff->hasVersionChanged()); + } + + public function test_returns_empty_when_no_changes() : void + { + $diff = new ExtensionDiff( + schema_extension('uuid-ossp', '1.0'), + schema_extension('uuid-ossp', '1.0'), + ); + + self::assertSame([], $diff->generate()); + } + + public function test_reversed_version_change() : void + { + $diff = new ExtensionDiff( + schema_extension('uuid-ossp', '1.1'), + schema_extension('uuid-ossp', '1.0'), + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER EXTENSION "uuid-ossp" UPDATE TO "1.0"', $sqls[0]->toSql()); + } + + public function test_reversed_version_change_when_target_version_null() : void + { + $diff = new ExtensionDiff( + schema_extension('uuid-ossp', '1.0'), + schema_extension('uuid-ossp'), + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER EXTENSION "uuid-ossp" UPDATE', $sqls[0]->toSql()); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/FuncDiffTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/FuncDiffTest.php new file mode 100644 index 0000000000..29ebb9f7ce --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/FuncDiffTest.php @@ -0,0 +1,55 @@ +from(table('users'))->where(eq(col('id'), literal(1)))->toSql()), + schema_function('get_user', 'text', ['integer'], 'plpgsql', 'BEGIN RETURN (SELECT name FROM users WHERE id = $1); END'), + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame( + 'CREATE OR REPLACE FUNCTION get_user(IN int) RETURNS text LANGUAGE plpgsql AS $$BEGIN RETURN (SELECT name FROM users WHERE id = $1); END$$', + $sqls[0]->toSql() + ); + } + + public function test_returns_empty_when_definition_null() : void + { + $diff = new FuncDiff( + schema_function('get_user', 'text', ['integer'], 'sql', 'SELECT name FROM users WHERE id = $1'), + schema_function('get_user', 'text', ['integer'], 'plpgsql'), + ); + + self::assertSame([], $diff->generate()); + } + + public function test_reversed_function_definition_change() : void + { + $diff = new FuncDiff( + schema_function('get_user', 'text', ['integer'], 'plpgsql', 'BEGIN RETURN (SELECT name FROM users WHERE id = $1); END'), + schema_function('get_user', 'text', ['integer'], 'sql', 'SELECT name FROM users WHERE id = $1'), + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame( + 'CREATE OR REPLACE FUNCTION get_user(IN int) RETURNS text LANGUAGE sql AS $$SELECT name FROM users WHERE id = $1$$', + $sqls[0]->toSql() + ); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/GreedySimilarityRenameStrategyTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/GreedySimilarityRenameStrategyTest.php new file mode 100644 index 0000000000..8433f88255 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/GreedySimilarityRenameStrategyTest.php @@ -0,0 +1,198 @@ +resolve([ + new RenameCandidate('net_commission', 'net_commission_cents'), + new RenameCandidate('net_commission', 'retail_agency_commission_cents'), + new RenameCandidate('net_commission', 'total_commission_cents'), + new RenameCandidate('retail_agency_commission', 'net_commission_cents'), + new RenameCandidate('retail_agency_commission', 'retail_agency_commission_cents'), + new RenameCandidate('retail_agency_commission', 'total_commission_cents'), + new RenameCandidate('total_commission', 'net_commission_cents'), + new RenameCandidate('total_commission', 'retail_agency_commission_cents'), + new RenameCandidate('total_commission', 'total_commission_cents'), + ]); + + $renames = []; + + foreach ($result as $match) { + $renames[$match->removedName] = $match->addedName; + } + + \ksort($renames); + + self::assertSame([ + 'net_commission_cents' => 'net_commission', + 'retail_agency_commission_cents' => 'retail_agency_commission', + 'total_commission_cents' => 'total_commission', + ], $renames); + } + + public function test_below_threshold_not_matched() : void + { + $strategy = new GreedySimilarityRenameStrategy(new SimilarTextStrategy()); + + $result = $strategy->resolve([ + new RenameCandidate('xyz_completely_different', 'foo'), + new RenameCandidate('xyz_completely_different', 'bar'), + ]); + + self::assertSame([], $result); + } + + public function test_different_similarity_strategy_changes_matching_outcome() : void + { + $candidates = [ + new RenameCandidate('net_commission', 'net_commission_cents'), + new RenameCandidate('net_commission', 'total_commission_cents'), + new RenameCandidate('total_commission', 'net_commission_cents'), + new RenameCandidate('total_commission', 'total_commission_cents'), + ]; + + $withSimilarText = new GreedySimilarityRenameStrategy(new SimilarTextStrategy()); + $withLevenshtein = new GreedySimilarityRenameStrategy(new LevenshteinStrategy()); + + $similarTextResult = $withSimilarText->resolve($candidates); + $levenshteinResult = $withLevenshtein->resolve($candidates); + + self::assertCount(2, $similarTextResult); + self::assertCount(2, $levenshteinResult); + + $stRenames = []; + + foreach ($similarTextResult as $m) { + $stRenames[$m->removedName] = $m->addedName; + } + + $lvRenames = []; + + foreach ($levenshteinResult as $m) { + $lvRenames[$m->removedName] = $m->addedName; + } + + self::assertSame('net_commission', $stRenames['net_commission_cents']); + self::assertSame('total_commission', $stRenames['total_commission_cents']); + self::assertSame('net_commission', $lvRenames['net_commission_cents']); + self::assertSame('total_commission', $lvRenames['total_commission_cents']); + } + + public function test_empty_candidates_returns_empty() : void + { + $strategy = new GreedySimilarityRenameStrategy(new SimilarTextStrategy()); + + self::assertSame([], $strategy->resolve([])); + } + + public function test_greedy_picks_highest_similarity_first() : void + { + $strategy = new GreedySimilarityRenameStrategy(new SimilarTextStrategy()); + + $result = $strategy->resolve([ + new RenameCandidate('full_name', 'first_name'), + new RenameCandidate('full_name', 'last_name'), + ]); + + self::assertCount(1, $result); + self::assertSame('full_name', $result[0]->addedName); + self::assertSame('last_name', $result[0]->removedName); + } + + public function test_higher_threshold_rejects_matches_that_default_accepts() : void + { + $candidates = [ + new RenameCandidate('full_name', 'first_name'), + new RenameCandidate('full_name', 'last_name'), + ]; + + $defaultStrategy = new GreedySimilarityRenameStrategy(new SimilarTextStrategy()); + $strictStrategy = new GreedySimilarityRenameStrategy(new SimilarTextStrategy(90.0)); + + self::assertCount(1, $defaultStrategy->resolve($candidates)); + self::assertSame([], $strictStrategy->resolve($candidates)); + } + + public function test_same_removed_not_matched_twice() : void + { + $strategy = new GreedySimilarityRenameStrategy(new SimilarTextStrategy()); + + $result = $strategy->resolve([ + new RenameCandidate('col_x', 'col_old'), + new RenameCandidate('col_y', 'col_old'), + ]); + + self::assertCount(1, $result); + self::assertSame('col_old', $result[0]->removedName); + } + + public function test_unambiguous_match_consumed_before_ambiguous_pass() : void + { + $strategy = new GreedySimilarityRenameStrategy(new SimilarTextStrategy()); + + $result = $strategy->resolve([ + new RenameCandidate('email', 'email_address'), + new RenameCandidate('name', 'email_address'), + new RenameCandidate('name', 'full_name'), + ]); + + $renames = []; + + foreach ($result as $match) { + $renames[$match->removedName] = $match->addedName; + } + + self::assertCount(2, $renames); + self::assertSame('email', $renames['email_address']); + self::assertSame('name', $renames['full_name']); + } + + public function test_unambiguous_matched_first_then_ambiguous_resolved() : void + { + $strategy = new GreedySimilarityRenameStrategy(new SimilarTextStrategy()); + + $result = $strategy->resolve([ + new RenameCandidate('unique_col', 'old_unique_col'), + new RenameCandidate('amount', 'amount_cents'), + new RenameCandidate('amount', 'total_cents'), + new RenameCandidate('total', 'amount_cents'), + new RenameCandidate('total', 'total_cents'), + ]); + + $renames = []; + + foreach ($result as $match) { + $renames[$match->removedName] = $match->addedName; + } + + self::assertArrayHasKey('old_unique_col', $renames); + self::assertSame('unique_col', $renames['old_unique_col']); + self::assertArrayHasKey('amount_cents', $renames); + self::assertSame('amount', $renames['amount_cents']); + self::assertArrayHasKey('total_cents', $renames); + self::assertSame('total', $renames['total_cents']); + } + + public function test_unambiguous_single_match() : void + { + $strategy = new GreedySimilarityRenameStrategy(new SimilarTextStrategy()); + + $result = $strategy->resolve([ + new RenameCandidate('full_name', 'name'), + ]); + + self::assertCount(1, $result); + self::assertSame('full_name', $result[0]->addedName); + self::assertSame('name', $result[0]->removedName); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/IndexComparatorTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/IndexComparatorTest.php new file mode 100644 index 0000000000..67e83af9e4 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/IndexComparatorTest.php @@ -0,0 +1,173 @@ +compare( + [], + [schema_index('idx_email', ['email'])], + ); + + self::assertCount(1, $result->added); + self::assertSame('idx_email', $result->added[0]->name); + self::assertSame([], $result->removed); + self::assertSame([], $result->renamed); + } + + public function test_ambiguous_rename_resolved_by_similarity() : void + { + $comparator = new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + + $result = $comparator->compare( + [ + schema_index('idx_old_a', ['email']), + schema_index('idx_old_b', ['email']), + ], + [ + schema_index('idx_new', ['email']), + ], + ); + + self::assertCount(0, $result->added); + self::assertCount(1, $result->removed); + self::assertCount(1, $result->renamed); + } + + public function test_index_with_same_name_different_columns_detected_as_change() : void + { + $comparator = new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + + $result = $comparator->compare( + [schema_index('idx_search', ['email'])], + [schema_index('idx_search', ['name'])], + ); + + self::assertCount(1, $result->added); + self::assertSame(['name'], $result->added[0]->columns); + self::assertCount(1, $result->removed); + self::assertSame(['email'], $result->removed[0]->columns); + self::assertSame([], $result->renamed); + } + + public function test_index_with_same_name_different_method_detected_as_change() : void + { + $comparator = new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + + $result = $comparator->compare( + [schema_index('idx_email', ['email'], method: IndexMethod::BTREE)], + [schema_index('idx_email', ['email'], method: IndexMethod::HASH)], + ); + + self::assertCount(1, $result->added); + self::assertSame(IndexMethod::HASH, $result->added[0]->method); + self::assertCount(1, $result->removed); + self::assertSame(IndexMethod::BTREE, $result->removed[0]->method); + self::assertSame([], $result->renamed); + } + + public function test_index_with_same_name_different_predicate_detected_as_change() : void + { + $comparator = new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + + $result = $comparator->compare( + [schema_index('idx_active', ['active'], predicate: null)], + [schema_index('idx_active', ['active'], predicate: 'active = true')], + ); + + self::assertCount(1, $result->added); + self::assertSame('active = true', $result->added[0]->predicate); + self::assertCount(1, $result->removed); + self::assertNull($result->removed[0]->predicate); + self::assertSame([], $result->renamed); + } + + public function test_index_with_same_name_different_primary_detected_as_change() : void + { + $comparator = new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + + $result = $comparator->compare( + [schema_index('idx_id', ['id'], primary: false)], + [schema_index('idx_id', ['id'], primary: true)], + ); + + self::assertCount(1, $result->added); + self::assertTrue($result->added[0]->primary); + self::assertCount(1, $result->removed); + self::assertFalse($result->removed[0]->primary); + self::assertSame([], $result->renamed); + } + + public function test_index_with_same_name_different_unique_detected_as_change() : void + { + $comparator = new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + + $result = $comparator->compare( + [schema_index('idx_email', ['email'], unique: false)], + [schema_index('idx_email', ['email'], unique: true)], + ); + + self::assertCount(1, $result->added); + self::assertTrue($result->added[0]->unique); + self::assertCount(1, $result->removed); + self::assertFalse($result->removed[0]->unique); + self::assertSame([], $result->renamed); + } + + public function test_no_changes_for_identical_indexes() : void + { + $comparator = new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + + $result = $comparator->compare( + [schema_index('idx_email', ['email'])], + [schema_index('idx_email', ['email'])], + ); + + self::assertSame([], $result->added); + self::assertSame([], $result->removed); + self::assertSame([], $result->renamed); + } + + public function test_removed_index_detected() : void + { + $comparator = new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + + $result = $comparator->compare( + [schema_index('idx_email', ['email'])], + [], + ); + + self::assertSame([], $result->added); + self::assertCount(1, $result->removed); + self::assertSame('idx_email', $result->removed[0]->name); + self::assertSame([], $result->renamed); + } + + public function test_rename_detected() : void + { + $comparator = new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + + $result = $comparator->compare( + [schema_index('idx_old', ['email'])], + [schema_index('idx_new', ['email'])], + ); + + self::assertSame([], $result->added); + self::assertSame([], $result->removed); + self::assertCount(1, $result->renamed); + self::assertArrayHasKey('idx_old', $result->renamed); + self::assertSame('idx_new', $result->renamed['idx_old']->name); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/LevenshteinStrategyTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/LevenshteinStrategyTest.php new file mode 100644 index 0000000000..834802e9b7 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/LevenshteinStrategyTest.php @@ -0,0 +1,63 @@ +similarity('', '')); + } + + public function test_custom_threshold() : void + { + self::assertSame(75.0, (new LevenshteinStrategy(75.0))->threshold()); + } + + public function test_default_threshold_is_50() : void + { + self::assertSame(50.0, (new LevenshteinStrategy())->threshold()); + } + + public function test_identical_names_score_100() : void + { + self::assertSame(100.0, (new LevenshteinStrategy())->similarity('column_name', 'column_name')); + } + + public function test_levenshtein_penalizes_suffix_removal_more_than_similar_text() : void + { + $levenshtein = new LevenshteinStrategy(); + + $score = $levenshtein->similarity('net_commission_cents', 'net_commission'); + + self::assertEqualsWithDelta(70.0, $score, 0.01); + self::assertLessThan(80.0, $score); + } + + public function test_one_empty_string_scores_0() : void + { + self::assertSame(0.0, (new LevenshteinStrategy())->similarity('', 'something')); + } + + public function test_realistic_column_rename_suffix_removed() : void + { + self::assertEqualsWithDelta(70.0, (new LevenshteinStrategy())->similarity('net_commission_cents', 'net_commission'), 0.01); + } + + public function test_single_character_typo_scores_above_90() : void + { + self::assertEqualsWithDelta(90.91, (new LevenshteinStrategy())->similarity('column_name', 'column_namx'), 0.01); + } + + public function test_unrelated_names_score_low() : void + { + $score = (new LevenshteinStrategy())->similarity('foo', 'xyz_completely_different'); + + self::assertLessThan(20.0, $score); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/LongestCommonSubstringStrategyTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/LongestCommonSubstringStrategyTest.php new file mode 100644 index 0000000000..1f18897887 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/LongestCommonSubstringStrategyTest.php @@ -0,0 +1,61 @@ +similarity('', '')); + } + + public function test_common_prefix_with_different_suffix() : void + { + $strategy = new LongestCommonSubstringStrategy(); + + $withSuffix = $strategy->similarity('user_email_old', 'user_email'); + $noOverlap = $strategy->similarity('user_email_old', 'total_amount'); + + self::assertGreaterThan($noOverlap, $withSuffix); + } + + public function test_custom_threshold() : void + { + self::assertSame(75.0, (new LongestCommonSubstringStrategy(75.0))->threshold()); + } + + public function test_default_threshold_is_50() : void + { + self::assertSame(50.0, (new LongestCommonSubstringStrategy())->threshold()); + } + + public function test_identical_names_score_100() : void + { + self::assertSame(100.0, (new LongestCommonSubstringStrategy())->similarity('column_name', 'column_name')); + } + + public function test_no_common_characters_scores_0() : void + { + self::assertSame(0.0, (new LongestCommonSubstringStrategy())->similarity('abc', 'xyz')); + } + + public function test_one_empty_string_scores_0() : void + { + self::assertSame(0.0, (new LongestCommonSubstringStrategy())->similarity('', 'something')); + } + + public function test_realistic_column_rename_suffix_removed() : void + { + self::assertEqualsWithDelta(70.0, (new LongestCommonSubstringStrategy())->similarity('net_commission_cents', 'net_commission'), 0.01); + } + + public function test_reversed_single_chars_share_one_character_substring() : void + { + self::assertSame(50.0, (new LongestCommonSubstringStrategy())->similarity('ax', 'xa')); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/MaterializedViewDiffTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/MaterializedViewDiffTest.php new file mode 100644 index 0000000000..cd59b03870 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/MaterializedViewDiffTest.php @@ -0,0 +1,184 @@ +from(table('users'))->toSql(); + + $diff = new MaterializedViewDiff( + schema_materialized_view('mv_users', $definition), + schema_materialized_view('mv_users', $definition), + addedIndexes: [schema_index('idx_email', ['email'])], + removedIndexes: [schema_index('idx_name', ['name'])], + ); + + $sqls = $diff->generate(); + + self::assertCount(2, $sqls); + self::assertSame('DROP INDEX idx_name', $sqls[0]->toSql()); + self::assertSame('CREATE INDEX idx_email ON mv_users (email)', $sqls[1]->toSql()); + } + + public function test_adds_gin_index_without_definition_change() : void + { + $source = schema_materialized_view('mv_users', select(star())->from(table('users'))->toSql()); + $target = schema_materialized_view('mv_users', select(star())->from(table('users'))->toSql()); + + $diff = new MaterializedViewDiff( + $source, + $target, + addedIndexes: [schema_index('idx_data', ['data'], method: IndexMethod::GIN)], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('CREATE INDEX idx_data ON mv_users USING gin (data)', $sqls[0]->toSql()); + } + + public function test_adds_index() : void + { + $definition = select(star())->from(table('users'))->toSql(); + + $diff = new MaterializedViewDiff( + schema_materialized_view('mv_users', $definition), + schema_materialized_view('mv_users', $definition), + addedIndexes: [schema_index('idx_email', ['email'])], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('CREATE INDEX idx_email ON mv_users (email)', $sqls[0]->toSql()); + } + + public function test_adds_unique_index_without_definition_change() : void + { + $source = schema_materialized_view('mv_users', select(star())->from(table('users'))->toSql()); + $target = schema_materialized_view('mv_users', select(star())->from(table('users'))->toSql()); + + $diff = new MaterializedViewDiff( + $source, + $target, + addedIndexes: [schema_index('idx_unique_email', ['email'], unique: true)], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('CREATE UNIQUE INDEX idx_unique_email ON mv_users (email)', $sqls[0]->toSql()); + } + + public function test_drops_index() : void + { + $definition = select(star())->from(table('users'))->toSql(); + + $diff = new MaterializedViewDiff( + schema_materialized_view('mv_users', $definition), + schema_materialized_view('mv_users', $definition), + removedIndexes: [schema_index('idx_email', ['email'])], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('DROP INDEX idx_email', $sqls[0]->toSql()); + } + + public function test_drops_source_indexes_before_recreating_when_definition_changed() : void + { + $sourceDefinition = select(star())->from(table('users'))->toSql(); + $targetDefinition = select(star())->from(table('users'))->where(eq(col('active'), literal(true)))->toSql(); + + $diff = new MaterializedViewDiff( + schema_materialized_view('mv_users', $sourceDefinition, [schema_index('idx_name', ['name'])]), + schema_materialized_view('mv_users', $targetDefinition, [schema_index('idx_email', ['email'])]), + ); + + $sqls = $diff->generate(); + + self::assertCount(4, $sqls); + self::assertSame('DROP INDEX idx_name', $sqls[0]->toSql()); + self::assertSame('DROP MATERIALIZED VIEW mv_users', $sqls[1]->toSql()); + self::assertSame('CREATE MATERIALIZED VIEW mv_users AS SELECT * FROM users WHERE active = true', $sqls[2]->toSql()); + self::assertSame('CREATE INDEX idx_email ON mv_users (email)', $sqls[3]->toSql()); + } + + public function test_has_definition_changed_returns_false_when_same() : void + { + $diff = new MaterializedViewDiff( + schema_materialized_view('mv_users', select(star())->from(table('users'))->toSql()), + schema_materialized_view('mv_users', select(star())->from(table('users'))->toSql()), + ); + + self::assertFalse($diff->hasDefinitionChanged()); + } + + public function test_has_definition_changed_returns_true_when_different() : void + { + $diff = new MaterializedViewDiff( + schema_materialized_view('mv_users', select(star())->from(table('users'))->toSql()), + schema_materialized_view('mv_users', select(star())->from(table('users'))->where(eq(col('active'), literal(true)))->toSql()), + ); + + self::assertTrue($diff->hasDefinitionChanged()); + } + + public function test_recreates_when_definition_changed() : void + { + $diff = new MaterializedViewDiff( + schema_materialized_view('mv_users', select(star())->from(table('users'))->toSql()), + schema_materialized_view('mv_users', select(star())->from(table('users'))->where(eq(col('active'), literal(true)))->toSql()), + ); + + $sqls = $diff->generate(); + + self::assertCount(2, $sqls); + self::assertSame('DROP MATERIALIZED VIEW mv_users', $sqls[0]->toSql()); + self::assertSame('CREATE MATERIALIZED VIEW mv_users AS SELECT * FROM users WHERE active = true', $sqls[1]->toSql()); + } + + public function test_reversed_definition_change() : void + { + $diff = new MaterializedViewDiff( + schema_materialized_view('mv_users', select(star())->from(table('users'))->where(eq(col('active'), literal(true)))->toSql()), + schema_materialized_view('mv_users', select(star())->from(table('users'))->toSql()), + ); + + $sqls = $diff->generate(); + + self::assertCount(2, $sqls); + self::assertSame('DROP MATERIALIZED VIEW mv_users', $sqls[0]->toSql()); + self::assertSame('CREATE MATERIALIZED VIEW mv_users AS SELECT * FROM users', $sqls[1]->toSql()); + } + + public function test_reversed_index_only_changes() : void + { + $definition = select(star())->from(table('users'))->toSql(); + + $diff = new MaterializedViewDiff( + schema_materialized_view('mv_users', $definition), + schema_materialized_view('mv_users', $definition), + addedIndexes: [schema_index('idx_name', ['name'])], + removedIndexes: [schema_index('idx_email', ['email'])], + ); + + $sqls = $diff->generate(); + + self::assertCount(2, $sqls); + self::assertSame('DROP INDEX idx_email', $sqls[0]->toSql()); + self::assertSame('CREATE INDEX idx_name ON mv_users (name)', $sqls[1]->toSql()); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/NoRenameStrategyTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/NoRenameStrategyTest.php new file mode 100644 index 0000000000..f63e6728b7 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/NoRenameStrategyTest.php @@ -0,0 +1,37 @@ +resolve([ + new RenameCandidate('full_name', 'name'), + ])); + } + + public function test_empty_candidates_returns_empty() : void + { + $strategy = new NoRenameStrategy(); + + self::assertSame([], $strategy->resolve([])); + } + + public function test_multiple_candidates_returns_empty() : void + { + $strategy = new NoRenameStrategy(); + + self::assertSame([], $strategy->resolve([ + new RenameCandidate('col_a', 'col_x'), + new RenameCandidate('col_b', 'col_y'), + ])); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/NoSimilarityStrategyTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/NoSimilarityStrategyTest.php new file mode 100644 index 0000000000..3eded71638 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/NoSimilarityStrategyTest.php @@ -0,0 +1,39 @@ +similarity('column_name', 'column_name')); + } + + public function test_returns_zero_for_different_names() : void + { + $strategy = new NoSimilarityStrategy(); + + self::assertSame(0.0, $strategy->similarity('foo', 'bar')); + } + + public function test_returns_zero_for_empty_strings() : void + { + $strategy = new NoSimilarityStrategy(); + + self::assertSame(0.0, $strategy->similarity('', '')); + } + + public function test_threshold_is_100() : void + { + $strategy = new NoSimilarityStrategy(); + + self::assertSame(100.0, $strategy->threshold()); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/ProcedureDiffTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/ProcedureDiffTest.php new file mode 100644 index 0000000000..3e5000ecf7 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/ProcedureDiffTest.php @@ -0,0 +1,55 @@ +generate(); + + self::assertCount(1, $sqls); + self::assertSame( + 'CREATE OR REPLACE PROCEDURE cleanup(IN int) LANGUAGE plpgsql AS $$BEGIN DELETE FROM logs WHERE id = $1; END$$', + $sqls[0]->toSql() + ); + } + + public function test_returns_empty_when_definition_null() : void + { + $diff = new ProcedureDiff( + schema_procedure('cleanup', ['integer'], 'sql', 'DELETE FROM logs WHERE id = $1'), + schema_procedure('cleanup', ['integer'], 'plpgsql'), + ); + + self::assertSame([], $diff->generate()); + } + + public function test_reversed_procedure_definition_change() : void + { + $diff = new ProcedureDiff( + schema_procedure('cleanup', ['integer'], 'plpgsql', 'BEGIN DELETE FROM logs WHERE id = $1; END'), + schema_procedure('cleanup', ['integer'], 'sql', 'DELETE FROM logs WHERE id = $1'), + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame( + 'CREATE OR REPLACE PROCEDURE cleanup(IN int) LANGUAGE sql AS $$DELETE FROM logs WHERE id = $1$$', + $sqls[0]->toSql() + ); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/SchemaComparatorTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/SchemaComparatorTest.php new file mode 100644 index 0000000000..3e3fc2cb26 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/SchemaComparatorTest.php @@ -0,0 +1,890 @@ +compare($source, $target); + + self::assertCount(1, $diff->addedDomains); + } + + public function test_domain_modified_base_type() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public', domains: [schema_domain('d1', ColumnType::text())]); + $target = new Schema('public', domains: [schema_domain('d1', ColumnType::varchar(255))]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->modifiedDomains); + } + + public function test_domain_modified_check_constraint() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public', domains: [schema_domain('d1', ColumnType::text(), checkConstraints: [ + new CheckConstraint('VALUE ~ \'^[a-z]+$\'', 'chk_lower'), + ])]); + $target = new Schema('public', domains: [schema_domain('d1', ColumnType::text(), checkConstraints: [ + new CheckConstraint('VALUE ~ \'^[A-Z]+$\'', 'chk_lower'), + ])]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->modifiedDomains); + } + + public function test_domain_modified_default() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public', domains: [schema_domain('d1', ColumnType::text(), default: null)]); + $target = new Schema('public', domains: [schema_domain('d1', ColumnType::text(), default: "'hello'")]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->modifiedDomains); + } + + public function test_domain_modified_nullable() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public', domains: [schema_domain('d1', ColumnType::text(), nullable: true)]); + $target = new Schema('public', domains: [schema_domain('d1', ColumnType::text(), nullable: false)]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->modifiedDomains); + } + + public function test_domain_removed() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public', domains: [schema_domain('email', ColumnType::text())]); + $target = new Schema('public'); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->removedDomains); + } + + public function test_extension_added() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public'); + $target = new Schema('public', extensions: [schema_extension('uuid-ossp')]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->addedExtensions); + } + + public function test_extension_modified_version() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public', extensions: [schema_extension('uuid-ossp', version: '1.0')]); + $target = new Schema('public', extensions: [schema_extension('uuid-ossp', version: '2.0')]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->modifiedExtensions); + } + + public function test_extension_removed() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public', extensions: [schema_extension('uuid-ossp')]); + $target = new Schema('public'); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->removedExtensions); + } + + public function test_function_added() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public'); + $target = new Schema('public', functions: [schema_function('add', 'integer', ['integer', 'integer'], definition: 'SELECT $1 + $2')]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->addedFunctions); + } + + public function test_function_modified_argument_types() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public', functions: [schema_function('fn', 'integer', ['integer'])]); + $target = new Schema('public', functions: [schema_function('fn', 'integer', ['text'])]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->modifiedFunctions); + } + + public function test_function_modified_definition() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public', functions: [schema_function('fn', 'integer', definition: 'SELECT 1')]); + $target = new Schema('public', functions: [schema_function('fn', 'integer', definition: 'SELECT 2')]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->modifiedFunctions); + } + + public function test_function_modified_is_strict() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public', functions: [schema_function('fn', 'integer', isStrict: false)]); + $target = new Schema('public', functions: [schema_function('fn', 'integer', isStrict: true)]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->modifiedFunctions); + } + + public function test_function_modified_language() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public', functions: [schema_function('fn', 'integer', language: 'sql')]); + $target = new Schema('public', functions: [schema_function('fn', 'integer', language: 'plpgsql')]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->modifiedFunctions); + } + + public function test_function_modified_return_type() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public', functions: [schema_function('fn', 'integer')]); + $target = new Schema('public', functions: [schema_function('fn', 'bigint')]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->modifiedFunctions); + } + + public function test_function_modified_volatility() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public', functions: [schema_function('fn', 'integer', volatility: FunctionVolatility::VOLATILE)]); + $target = new Schema('public', functions: [schema_function('fn', 'integer', volatility: FunctionVolatility::STABLE)]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->modifiedFunctions); + } + + public function test_function_removed() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public', functions: [schema_function('add', 'integer', ['integer', 'integer'], definition: 'SELECT $1 + $2')]); + $target = new Schema('public'); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->removedFunctions); + } + + public function test_identical_schemas_produce_empty_diff() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $schema = new Schema('public', tables: [ + schema_table('users', [schema_column_integer('id', false)]), + ]); + + $diff = $comparator->compare($schema, $schema); + + self::assertTrue($diff->isEmpty()); + } + + public function test_materialized_view_added() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public'); + $target = new Schema('public', materializedViews: [schema_materialized_view('mv_users', 'SELECT * FROM users')]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->addedMaterializedViews); + } + + public function test_materialized_view_modified_definition() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public', materializedViews: [schema_materialized_view('mv_users', 'SELECT * FROM users')]); + $target = new Schema('public', materializedViews: [schema_materialized_view('mv_users', 'SELECT id FROM users')]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->modifiedMaterializedViews); + } + + public function test_materialized_view_modified_index() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public', materializedViews: [schema_materialized_view('mv_users', 'SELECT * FROM users')]); + $target = new Schema('public', materializedViews: [schema_materialized_view('mv_users', 'SELECT * FROM users', indexes: [ + schema_index('idx_mv_id', ['id']), + ])]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->modifiedMaterializedViews); + } + + public function test_materialized_view_removed() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public', materializedViews: [schema_materialized_view('mv_users', 'SELECT * FROM users')]); + $target = new Schema('public'); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->removedMaterializedViews); + } + + public function test_procedure_added() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public'); + $target = new Schema('public', procedures: [schema_procedure('do_stuff')]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->addedProcedures); + } + + public function test_procedure_modified_argument_types() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public', procedures: [schema_procedure('do_stuff', argumentTypes: ['integer'])]); + $target = new Schema('public', procedures: [schema_procedure('do_stuff', argumentTypes: ['text'])]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->modifiedProcedures); + } + + public function test_procedure_modified_definition() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public', procedures: [schema_procedure('do_stuff', definition: 'BEGIN END')]); + $target = new Schema('public', procedures: [schema_procedure('do_stuff', definition: 'BEGIN RAISE NOTICE; END')]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->modifiedProcedures); + } + + public function test_procedure_modified_language() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public', procedures: [schema_procedure('do_stuff', language: 'sql')]); + $target = new Schema('public', procedures: [schema_procedure('do_stuff', language: 'plpgsql')]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->modifiedProcedures); + } + + public function test_procedure_removed() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public', procedures: [schema_procedure('do_stuff')]); + $target = new Schema('public'); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->removedProcedures); + } + + public function test_sequence_added() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public'); + $target = new Schema('public', sequences: [schema_sequence('users_id_seq')]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->addedSequences); + self::assertSame('users_id_seq', $diff->addedSequences[0]->name); + } + + public function test_sequence_modified_cache_value() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public', sequences: [schema_sequence('s1', cacheValue: 1)]); + $target = new Schema('public', sequences: [schema_sequence('s1', cacheValue: 20)]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->modifiedSequences); + } + + public function test_sequence_modified_cycle() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public', sequences: [schema_sequence('s1', cycle: false)]); + $target = new Schema('public', sequences: [schema_sequence('s1', cycle: true)]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->modifiedSequences); + } + + public function test_sequence_modified_data_type() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public', sequences: [schema_sequence('s1', dataType: 'bigint')]); + $target = new Schema('public', sequences: [schema_sequence('s1', dataType: 'integer')]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->modifiedSequences); + } + + public function test_sequence_modified_increment_by() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public', sequences: [schema_sequence('s1', incrementBy: 1)]); + $target = new Schema('public', sequences: [schema_sequence('s1', incrementBy: 5)]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->modifiedSequences); + } + + public function test_sequence_modified_max_value() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public', sequences: [schema_sequence('s1', maxValue: null)]); + $target = new Schema('public', sequences: [schema_sequence('s1', maxValue: 999)]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->modifiedSequences); + } + + public function test_sequence_modified_min_value() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public', sequences: [schema_sequence('s1', minValue: 1)]); + $target = new Schema('public', sequences: [schema_sequence('s1', minValue: 10)]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->modifiedSequences); + } + + public function test_sequence_modified_owned_by_column() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public', sequences: [schema_sequence('s1', ownedByColumn: null)]); + $target = new Schema('public', sequences: [schema_sequence('s1', ownedByColumn: 'id')]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->modifiedSequences); + } + + public function test_sequence_modified_owned_by_table() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public', sequences: [schema_sequence('s1', ownedByTable: null)]); + $target = new Schema('public', sequences: [schema_sequence('s1', ownedByTable: 'users')]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->modifiedSequences); + } + + public function test_sequence_modified_start_value() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public', sequences: [schema_sequence('s1', startValue: 1)]); + $target = new Schema('public', sequences: [schema_sequence('s1', startValue: 100)]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->modifiedSequences); + } + + public function test_sequence_removed() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public', sequences: [schema_sequence('users_id_seq')]); + $target = new Schema('public'); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->removedSequences); + } + + public function test_table_added() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public'); + $target = new Schema('public', tables: [schema_table('users', [schema_column_integer('id', false)])]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->addedTables); + self::assertSame('users', $diff->addedTables[0]->name); + } + + public function test_table_inherits_changed() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public', tables: [schema_table('employees', [schema_column_integer('id', false)])]); + $target = new Schema('public', tables: [schema_table('employees', [schema_column_integer('id', false)], inherits: ['persons'])]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->modifiedTables); + self::assertSame(['persons'], $diff->modifiedTables[0]->addedInherits); + self::assertSame([], $diff->modifiedTables[0]->removedInherits); + } + + public function test_table_modified() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public', tables: [schema_table('users', [schema_column_integer('id', false)])]); + $target = new Schema('public', tables: [schema_table('users', [schema_column_integer('id', false), schema_column_text('email')])]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->modifiedTables); + } + + public function test_table_partition_changed() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public', tables: [schema_table('events', [schema_column_integer('id', false)])]); + $target = new Schema('public', tables: [schema_table('events', [schema_column_integer('id', false)], partitionStrategy: PartitionStrategy::RANGE, partitionColumns: ['id'])]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->modifiedTables); + self::assertTrue($diff->modifiedTables[0]->partitionChanged); + } + + public function test_table_removed() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public', tables: [schema_table('users', [schema_column_integer('id', false)])]); + $target = new Schema('public'); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->removedTables); + self::assertSame('users', $diff->removedTables[0]->name); + } + + public function test_table_rename_populates_schema_diff() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public', tables: [ + schema_table('old_users', [schema_column_integer('id', false), schema_column_text('name')], schema_primary_key(['id'])), + ]); + $target = new Schema('public', tables: [ + schema_table('new_users', [schema_column_integer('id', false), schema_column_text('name')], schema_primary_key(['id'])), + ]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(0, $diff->addedTables); + self::assertCount(0, $diff->removedTables); + self::assertCount(1, $diff->renamedTables); + self::assertArrayHasKey('public.old_users', $diff->renamedTables); + self::assertSame('new_users', $diff->renamedTables['public.old_users']->name); + } + + public function test_table_tablespace_changed() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public', tables: [schema_table('users', [schema_column_integer('id', false)])]); + $target = new Schema('public', tables: [schema_table('users', [schema_column_integer('id', false)], tablespace: 'fast_storage')]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->modifiedTables); + self::assertTrue($diff->modifiedTables[0]->tablespaceChanged); + } + + public function test_table_unlogged_changed() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public', tables: [schema_table('users', [schema_column_integer('id', false)])]); + $target = new Schema('public', tables: [schema_table('users', [schema_column_integer('id', false)], unlogged: true)]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->modifiedTables); + self::assertTrue($diff->modifiedTables[0]->unloggedChanged); + } + + public function test_view_added() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public'); + $target = new Schema('public', views: [schema_view('v_users', 'SELECT * FROM users')]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->addedViews); + self::assertSame('v_users', $diff->addedViews[0]->name); + } + + public function test_view_modified_definition() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public', views: [schema_view('v_users', 'SELECT * FROM users')]); + $target = new Schema('public', views: [schema_view('v_users', 'SELECT id FROM users')]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->modifiedViews); + } + + public function test_view_modified_is_updatable() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public', views: [schema_view('v_users', 'SELECT * FROM users', isUpdatable: false)]); + $target = new Schema('public', views: [schema_view('v_users', 'SELECT * FROM users', isUpdatable: true)]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->modifiedViews); + } + + public function test_view_removed() : void + { + $constraintComparator = new ConstraintComparator(); + $comparator = new SchemaComparator( + new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), $constraintComparator, new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + $constraintComparator, + new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), + ); + $source = new Schema('public', views: [schema_view('v_users', 'SELECT * FROM users')]); + $target = new Schema('public'); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->removedViews); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/SchemaDiffTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/SchemaDiffTest.php new file mode 100644 index 0000000000..171848cdbc --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/SchemaDiffTest.php @@ -0,0 +1,527 @@ +generate(); + + self::assertCount(1, $sqls); + self::assertSame('CREATE DOMAIN email AS pg_catalog.text NOT NULL', $sqls[0]->toSql()); + } + + public function test_creates_added_extension() : void + { + $s = schema('public'); + + $diff = new SchemaDiff( + $s, + $s, + addedExtensions: [schema_extension('uuid-ossp')], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('CREATE EXTENSION "uuid-ossp"', $sqls[0]->toSql()); + } + + public function test_creates_added_function() : void + { + $s = schema('public'); + + $diff = new SchemaDiff( + $s, + $s, + addedFunctions: [schema_function('my_func', 'text', ['integer'], 'sql', 'SELECT name FROM users WHERE id = $1')], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('CREATE OR REPLACE FUNCTION my_func(IN int) RETURNS text LANGUAGE sql AS $$SELECT name FROM users WHERE id = $1$$', $sqls[0]->toSql()); + } + + public function test_creates_added_sequence() : void + { + $s = schema('public'); + + $diff = new SchemaDiff( + $s, + $s, + addedSequences: [schema_sequence('users_id_seq')], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('CREATE SEQUENCE users_id_seq AS bigint START 1 INCREMENT 1 MINVALUE 1 CACHE 1 NO MAXVALUE', $sqls[0]->toSql()); + } + + public function test_creates_added_table() : void + { + $s = schema('public'); + + $diff = new SchemaDiff( + $s, + $s, + [schema_table('users', [schema_column_integer('id', false), schema_column_text('name')])], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('CREATE TABLE public.users (id int NOT NULL, name pg_catalog.text)', $sqls[0]->toSql()); + } + + public function test_creates_added_view() : void + { + $s = schema('public'); + + $diff = new SchemaDiff( + $s, + $s, + addedViews: [schema_view('active_users', 'SELECT * FROM users WHERE active = true')], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('CREATE VIEW active_users AS SELECT * FROM users WHERE active = true', $sqls[0]->toSql()); + } + + public function test_delegates_to_table_diff() : void + { + $s = schema('public'); + $sourceTable = schema_table('users', [schema_column_integer('id', false)]); + $targetTable = schema_table('users', [schema_column_integer('id', false), schema_column_text('name')]); + + $tableDiff = new TableDiff( + $sourceTable, + $targetTable, + [new Column('name', ColumnType::text(), true)], + ); + + $diff = new SchemaDiff( + $s, + $s, + modifiedTables: [$tableDiff], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER TABLE public.users ADD COLUMN name pg_catalog.text', $sqls[0]->toSql()); + } + + public function test_dependency_order() : void + { + $s = schema('public'); + + $diff = new SchemaDiff( + $s, + $s, + addedTables: [schema_table('users', [schema_column_integer('id', false)])], + removedViews: [schema_view('active_users', 'SELECT * FROM users WHERE active = true')], + addedExtensions: [schema_extension('uuid-ossp')], + ); + + $sqls = $diff->generate(); + + self::assertCount(3, $sqls); + self::assertSame('CREATE EXTENSION "uuid-ossp"', $sqls[0]->toSql()); + self::assertSame('CREATE TABLE public.users (id int NOT NULL)', $sqls[1]->toSql()); + self::assertSame('DROP VIEW active_users', $sqls[2]->toSql()); + } + + public function test_drops_all_removed_object_types() : void + { + $s = schema('public'); + + $diff = new SchemaDiff( + $s, + $s, + removedTables: [schema_table('users', [schema_column_integer('id', false)])], + removedSequences: [schema_sequence('users_id_seq')], + removedViews: [schema_view('active_users', select(literal(1))->toSql())], + removedMaterializedViews: [schema_materialized_view('mv_stats', select(literal(1))->toSql())], + removedFunctions: [schema_function('my_func', 'text')], + removedProcedures: [schema_procedure('cleanup')], + removedDomains: [schema_domain('email', ColumnType::text())], + removedExtensions: [schema_extension('pgcrypto')], + ); + + $sqls = $diff->generate(); + + self::assertSame('DROP MATERIALIZED VIEW mv_stats', $sqls[0]->toSql()); + self::assertSame('DROP VIEW active_users', $sqls[1]->toSql()); + self::assertSame('DROP TABLE public.users CASCADE', $sqls[2]->toSql()); + self::assertSame('DROP PROCEDURE cleanup', $sqls[3]->toSql()); + self::assertSame('DROP FUNCTION my_func', $sqls[4]->toSql()); + self::assertSame('DROP SEQUENCE users_id_seq', $sqls[5]->toSql()); + self::assertSame('DROP DOMAIN email CASCADE', $sqls[6]->toSql()); + self::assertSame('DROP EXTENSION pgcrypto', $sqls[7]->toSql()); + self::assertCount(8, $sqls); + } + + public function test_drops_removed_domain() : void + { + $s = schema('public'); + + $diff = new SchemaDiff( + $s, + $s, + removedDomains: [schema_domain('email', ColumnType::text())], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('DROP DOMAIN email CASCADE', $sqls[0]->toSql()); + } + + public function test_drops_removed_extension() : void + { + $s = schema('public'); + + $diff = new SchemaDiff( + $s, + $s, + removedExtensions: [schema_extension('uuid-ossp')], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('DROP EXTENSION "uuid-ossp"', $sqls[0]->toSql()); + } + + public function test_drops_removed_function() : void + { + $s = schema('public'); + + $diff = new SchemaDiff( + $s, + $s, + removedFunctions: [schema_function('my_func', 'text')], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('DROP FUNCTION my_func', $sqls[0]->toSql()); + } + + public function test_drops_removed_materialized_view() : void + { + $s = schema('public'); + + $diff = new SchemaDiff( + $s, + $s, + removedMaterializedViews: [schema_materialized_view('mv_stats', select(literal(1))->toSql())], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('DROP MATERIALIZED VIEW mv_stats', $sqls[0]->toSql()); + } + + public function test_drops_removed_procedure() : void + { + $s = schema('public'); + + $diff = new SchemaDiff( + $s, + $s, + removedProcedures: [schema_procedure('cleanup')], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('DROP PROCEDURE cleanup', $sqls[0]->toSql()); + } + + public function test_drops_removed_sequence() : void + { + $s = schema('public'); + + $diff = new SchemaDiff( + $s, + $s, + removedSequences: [schema_sequence('users_id_seq')], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('DROP SEQUENCE users_id_seq', $sqls[0]->toSql()); + } + + public function test_drops_removed_table() : void + { + $s = schema('public'); + + $diff = new SchemaDiff( + $s, + $s, + removedTables: [schema_table('users', [schema_column_integer('id', false)])], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('DROP TABLE public.users CASCADE', $sqls[0]->toSql()); + } + + public function test_drops_removed_view() : void + { + $s = schema('public'); + + $diff = new SchemaDiff( + $s, + $s, + removedViews: [schema_view('active_users', 'SELECT * FROM users WHERE active = true')], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('DROP VIEW active_users', $sqls[0]->toSql()); + } + + public function test_is_empty_when_all_arrays_empty() : void + { + $s = schema('public'); + + $diff = new SchemaDiff($s, $s); + + self::assertTrue($diff->isEmpty()); + } + + public function test_is_not_empty_when_added_domains() : void + { + $s = schema('public'); + + $diff = new SchemaDiff( + $s, + $s, + addedDomains: [new Domain('email', ColumnType::text())], + ); + + self::assertFalse($diff->isEmpty()); + } + + public function test_is_not_empty_when_added_extensions() : void + { + $s = schema('public'); + + $diff = new SchemaDiff( + $s, + $s, + addedExtensions: [schema_extension('uuid-ossp')], + ); + + self::assertFalse($diff->isEmpty()); + } + + public function test_is_not_empty_when_added_functions() : void + { + $s = schema('public'); + + $diff = new SchemaDiff( + $s, + $s, + addedFunctions: [schema_function('f', 'void')], + ); + + self::assertFalse($diff->isEmpty()); + } + + public function test_is_not_empty_when_added_procedures() : void + { + $s = schema('public'); + + $diff = new SchemaDiff( + $s, + $s, + addedProcedures: [schema_procedure('p')], + ); + + self::assertFalse($diff->isEmpty()); + } + + public function test_is_not_empty_when_added_tables() : void + { + $s = schema('public'); + $table = schema_table('users', [schema_column_integer('id', false)]); + + $diff = new SchemaDiff( + $s, + $s, + [$table], + ); + + self::assertFalse($diff->isEmpty()); + } + + public function test_is_not_empty_when_added_views() : void + { + $s = schema('public'); + + $diff = new SchemaDiff( + $s, + $s, + addedViews: [schema_view('v', select(literal(1))->toSql())], + ); + + self::assertFalse($diff->isEmpty()); + } + + public function test_is_not_empty_when_modified_sequences() : void + { + $s = schema('public'); + + $diff = new SchemaDiff( + $s, + $s, + modifiedSequences: [new SequenceDiff(schema_sequence('s1'), schema_sequence('s1', incrementBy: 5))], + ); + + self::assertFalse($diff->isEmpty()); + } + + public function test_is_not_empty_when_removed_extensions() : void + { + $s = schema('public'); + + $diff = new SchemaDiff( + $s, + $s, + removedExtensions: [schema_extension('uuid-ossp')], + ); + + self::assertFalse($diff->isEmpty()); + } + + public function test_is_not_empty_when_removed_materialized_views() : void + { + $s = schema('public'); + + $diff = new SchemaDiff( + $s, + $s, + removedMaterializedViews: [schema_materialized_view('mv', select(literal(1))->toSql())], + ); + + self::assertFalse($diff->isEmpty()); + } + + public function test_is_not_empty_when_removed_tables() : void + { + $s = schema('public'); + $table = schema_table('users', [schema_column_integer('id', false)]); + + $diff = new SchemaDiff( + $s, + $s, + removedTables: [$table], + ); + + self::assertFalse($diff->isEmpty()); + } + + public function test_is_not_empty_when_renamed_tables() : void + { + $s = schema('public'); + $table = schema_table('new_users', [schema_column_integer('id', false)]); + + $diff = new SchemaDiff( + $s, + $s, + renamedTables: ['public.old_users' => $table], + ); + + self::assertFalse($diff->isEmpty()); + } + + public function test_renames_table() : void + { + $s = schema('public'); + $table = schema_table('new_users', [schema_column_integer('id', false)]); + + $diff = new SchemaDiff( + $s, + $s, + renamedTables: ['public.old_users' => $table], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER TABLE public.old_users RENAME TO new_users', $sqls[0]->toSql()); + } + + public function test_returns_empty_when_no_changes() : void + { + $s = schema('public'); + + $diff = new SchemaDiff($s, $s); + + self::assertSame([], $diff->generate()); + } + + public function test_reversed_added_table() : void + { + $s = schema('public'); + + $diff = new SchemaDiff( + $s, + $s, + removedTables: [schema_table('users', [schema_column_integer('id', false), schema_column_text('name')])], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('DROP TABLE public.users CASCADE', $sqls[0]->toSql()); + } + + public function test_reversed_table_rename() : void + { + $s = schema('public'); + $table = schema_table('old_users', [schema_column_integer('id', false)]); + + $diff = new SchemaDiff( + $s, + $s, + renamedTables: ['public.new_users' => $table], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER TABLE public.new_users RENAME TO old_users', $sqls[0]->toSql()); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/SequenceDiffTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/SequenceDiffTest.php new file mode 100644 index 0000000000..f433d3bd10 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/SequenceDiffTest.php @@ -0,0 +1,173 @@ +generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER SEQUENCE users_id_seq CACHE 20', $sqls[0]->toSql()); + } + + public function test_generates_alter_cycle_to_no_cycle() : void + { + $diff = new SequenceDiff( + schema_sequence('users_id_seq', cycle: true), + schema_sequence('users_id_seq', cycle: false), + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER SEQUENCE users_id_seq NO CYCLE', $sqls[0]->toSql()); + } + + public function test_generates_alter_data_type() : void + { + $diff = new SequenceDiff( + schema_sequence('users_id_seq', dataType: 'bigint'), + schema_sequence('users_id_seq', dataType: 'integer'), + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER SEQUENCE users_id_seq AS int', $sqls[0]->toSql()); + } + + public function test_generates_alter_increment_by() : void + { + $diff = new SequenceDiff( + schema_sequence('users_id_seq'), + schema_sequence('users_id_seq', incrementBy: 10), + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER SEQUENCE users_id_seq INCREMENT 10', $sqls[0]->toSql()); + } + + public function test_generates_alter_min_value() : void + { + $diff = new SequenceDiff( + schema_sequence('users_id_seq', minValue: 1), + schema_sequence('users_id_seq', minValue: 50), + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER SEQUENCE users_id_seq MINVALUE 50', $sqls[0]->toSql()); + } + + public function test_generates_alter_multiple_properties() : void + { + $diff = new SequenceDiff( + schema_sequence('users_id_seq'), + schema_sequence('users_id_seq', incrementBy: 10, cycle: true, maxValue: 1000), + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER SEQUENCE users_id_seq INCREMENT 10 MAXVALUE 1000 CYCLE', $sqls[0]->toSql()); + } + + public function test_generates_alter_no_max_value() : void + { + $diff = new SequenceDiff( + schema_sequence('users_id_seq', maxValue: 1000), + schema_sequence('users_id_seq', maxValue: null), + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER SEQUENCE users_id_seq NO MAXVALUE', $sqls[0]->toSql()); + } + + public function test_generates_alter_owned_by() : void + { + $diff = new SequenceDiff( + schema_sequence('users_id_seq'), + schema_sequence('users_id_seq', ownedByTable: 'users', ownedByColumn: 'id'), + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER SEQUENCE users_id_seq OWNED BY users.id', $sqls[0]->toSql()); + } + + public function test_generates_alter_owned_by_none() : void + { + $diff = new SequenceDiff( + schema_sequence('users_id_seq', ownedByTable: 'users', ownedByColumn: 'id'), + schema_sequence('users_id_seq'), + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER SEQUENCE users_id_seq OWNED BY "none"', $sqls[0]->toSql()); + } + + public function test_generates_alter_start_value() : void + { + $diff = new SequenceDiff( + schema_sequence('users_id_seq', startValue: 1), + schema_sequence('users_id_seq', startValue: 100), + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER SEQUENCE users_id_seq START 100', $sqls[0]->toSql()); + } + + public function test_returns_empty_when_no_changes() : void + { + $diff = new SequenceDiff( + schema_sequence('users_id_seq'), + schema_sequence('users_id_seq'), + ); + + self::assertSame([], $diff->generate()); + } + + public function test_reversed_increment_change() : void + { + $diff = new SequenceDiff( + schema_sequence('users_id_seq', incrementBy: 10), + schema_sequence('users_id_seq', incrementBy: 1), + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER SEQUENCE users_id_seq INCREMENT 1', $sqls[0]->toSql()); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/SimilarTextStrategyTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/SimilarTextStrategyTest.php new file mode 100644 index 0000000000..d41e0988ea --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/SimilarTextStrategyTest.php @@ -0,0 +1,56 @@ +threshold()); + } + + public function test_default_threshold_is_50() : void + { + self::assertSame(50.0, (new SimilarTextStrategy())->threshold()); + } + + public function test_empty_strings_score_0() : void + { + self::assertSame(0.0, (new SimilarTextStrategy())->similarity('', '')); + } + + public function test_identical_names_score_100() : void + { + self::assertSame(100.0, (new SimilarTextStrategy())->similarity('column_name', 'column_name')); + } + + public function test_partial_overlap_scores_between_50_and_100() : void + { + self::assertEqualsWithDelta(66.67, (new SimilarTextStrategy())->similarity('last_name', 'full_name'), 0.01); + } + + public function test_realistic_column_rename_scores_above_80() : void + { + self::assertEqualsWithDelta(82.35, (new SimilarTextStrategy())->similarity('net_commission_cents', 'net_commission'), 0.01); + } + + public function test_strategies_rank_correctly_for_ambiguous_commission_columns() : void + { + $strategy = new SimilarTextStrategy(); + + $bestMatch = $strategy->similarity('net_commission_cents', 'net_commission'); + $crossMatch = $strategy->similarity('net_commission_cents', 'total_commission'); + + self::assertGreaterThan($crossMatch, $bestMatch); + } + + public function test_unrelated_names_score_below_threshold() : void + { + self::assertEqualsWithDelta(7.41, (new SimilarTextStrategy())->similarity('foo', 'xyz_completely_different'), 0.01); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/StrictRenameStrategyTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/StrictRenameStrategyTest.php new file mode 100644 index 0000000000..68cb456d14 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/StrictRenameStrategyTest.php @@ -0,0 +1,112 @@ +resolve([ + new RenameCandidate('net_commission', 'net_commission_cents'), + new RenameCandidate('net_commission', 'total_commission_cents'), + ]); + + self::assertSame([], $result); + } + + public function test_empty_candidates_returns_empty() : void + { + $strategy = new StrictRenameStrategy(); + + self::assertSame([], $strategy->resolve([])); + } + + public function test_mixed_ambiguous_and_unambiguous() : void + { + $strategy = new StrictRenameStrategy(); + + $result = $strategy->resolve([ + new RenameCandidate('unique_col', 'old_unique'), + new RenameCandidate('ambig_a', 'old_x'), + new RenameCandidate('ambig_a', 'old_y'), + ]); + + self::assertCount(1, $result); + self::assertSame('unique_col', $result[0]->addedName); + self::assertSame('old_unique', $result[0]->removedName); + } + + public function test_multiple_unambiguous_matches() : void + { + $strategy = new StrictRenameStrategy(); + + $result = $strategy->resolve([ + new RenameCandidate('col_a', 'col_x'), + new RenameCandidate('col_b', 'col_y'), + ]); + + self::assertCount(2, $result); + } + + public function test_reverse_ambiguity_two_added_one_removed_candidate() : void + { + $strategy = new StrictRenameStrategy(); + + $result = $strategy->resolve([ + new RenameCandidate('col_new_a', 'col_old'), + new RenameCandidate('col_new_b', 'col_old'), + ]); + + self::assertCount(1, $result); + self::assertSame('col_new_a', $result[0]->addedName); + self::assertSame('col_old', $result[0]->removedName); + } + + public function test_same_removed_matched_only_once() : void + { + $strategy = new StrictRenameStrategy(); + + $result = $strategy->resolve([ + new RenameCandidate('col_a', 'col_shared'), + new RenameCandidate('col_b', 'col_shared'), + ]); + + self::assertCount(1, $result); + self::assertSame('col_a', $result[0]->addedName); + self::assertSame('col_shared', $result[0]->removedName); + } + + public function test_three_way_ambiguity_no_matches() : void + { + $strategy = new StrictRenameStrategy(); + + $result = $strategy->resolve([ + new RenameCandidate('a', 'x'), + new RenameCandidate('a', 'y'), + new RenameCandidate('b', 'x'), + new RenameCandidate('b', 'y'), + ]); + + self::assertSame([], $result); + } + + public function test_unambiguous_single_match() : void + { + $strategy = new StrictRenameStrategy(); + + $result = $strategy->resolve([ + new RenameCandidate('full_name', 'name'), + ]); + + self::assertCount(1, $result); + self::assertSame('full_name', $result[0]->addedName); + self::assertSame('name', $result[0]->removedName); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/TableComparatorTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/TableComparatorTest.php new file mode 100644 index 0000000000..e9f376c2bb --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/TableComparatorTest.php @@ -0,0 +1,308 @@ +compare($source, $target); + + self::assertCount(0, $diff->addedColumns); + self::assertCount(1, $diff->removedColumns); + self::assertCount(1, $diff->modifiedColumns); + self::assertTrue($diff->modifiedColumns[0]->hasNameChanged()); + } + + public function test_column_added() : void + { + $comparator = new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), new ConstraintComparator(), new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + $source = schema_table('users', [schema_column_integer('id', false)]); + $target = schema_table('users', [schema_column_integer('id', false), schema_column_text('email')]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->addedColumns); + self::assertSame('email', $diff->addedColumns[0]->name); + } + + public function test_column_default_changed() : void + { + $comparator = new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), new ConstraintComparator(), new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + $source = schema_table('users', [schema_column('status', ColumnType::text(), default: null)]); + $target = schema_table('users', [schema_column('status', ColumnType::text(), default: "'active'")]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->modifiedColumns); + self::assertTrue($diff->modifiedColumns[0]->hasDefaultChanged()); + } + + public function test_column_generation_changed() : void + { + $comparator = new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), new ConstraintComparator(), new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + $source = schema_table('users', [schema_column('full_name', ColumnType::text(), isGenerated: false)]); + $target = schema_table('users', [schema_column('full_name', ColumnType::text(), isGenerated: true, generationExpression: "first_name || ' ' || last_name")]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->modifiedColumns); + self::assertTrue($diff->modifiedColumns[0]->hasGenerationChanged()); + } + + public function test_column_identity_changed() : void + { + $comparator = new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), new ConstraintComparator(), new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + $source = schema_table('users', [schema_column('id', ColumnType::integer(), nullable: false, isIdentity: false)]); + $target = schema_table('users', [schema_column('id', ColumnType::integer(), nullable: false, isIdentity: true, identityGeneration: IdentityGeneration::ALWAYS)]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->modifiedColumns); + self::assertTrue($diff->modifiedColumns[0]->hasIdentityChanged()); + } + + public function test_column_nullable_changed() : void + { + $comparator = new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), new ConstraintComparator(), new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + $source = schema_table('users', [schema_column('email', ColumnType::text(), nullable: true)]); + $target = schema_table('users', [schema_column('email', ColumnType::text(), nullable: false)]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->modifiedColumns); + self::assertTrue($diff->modifiedColumns[0]->hasNullableChanged()); + } + + public function test_column_removed() : void + { + $comparator = new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), new ConstraintComparator(), new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + $source = schema_table('users', [schema_column_integer('id', false), schema_column_text('email')]); + $target = schema_table('users', [schema_column_integer('id', false)]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->removedColumns); + self::assertSame('email', $diff->removedColumns[0]->name); + } + + public function test_column_rename_detected() : void + { + $comparator = new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), new ConstraintComparator(), new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + $source = schema_table('users', [schema_column_integer('id', false), schema_column_text('email')]); + $target = schema_table('users', [schema_column_integer('id', false), schema_column_text('mail')]); + + $diff = $comparator->compare($source, $target); + + self::assertSame([], $diff->addedColumns); + self::assertSame([], $diff->removedColumns); + self::assertCount(1, $diff->modifiedColumns); + self::assertTrue($diff->modifiedColumns[0]->hasNameChanged()); + self::assertSame('email', $diff->modifiedColumns[0]->source->name); + self::assertSame('mail', $diff->modifiedColumns[0]->target->name); + } + + public function test_column_type_changed() : void + { + $comparator = new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), new ConstraintComparator(), new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + $source = schema_table('users', [schema_column('email', ColumnType::text())]); + $target = schema_table('users', [schema_column('email', ColumnType::varchar(255))]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->modifiedColumns); + self::assertTrue($diff->modifiedColumns[0]->hasTypeChanged()); + } + + public function test_identical_tables_produce_empty_diff() : void + { + $comparator = new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), new ConstraintComparator(), new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + $table = schema_table('users', [schema_column_integer('id', false), schema_column_text('email')]); + + $diff = $comparator->compare($table, $table); + + self::assertTrue($diff->isEmpty()); + } + + public function test_primary_key_added() : void + { + $comparator = new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), new ConstraintComparator(), new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + $source = schema_table('users', [schema_column_integer('id', false)]); + $target = schema_table('users', [schema_column_integer('id', false)], primaryKey: schema_primary_key(['id'])); + + $diff = $comparator->compare($source, $target); + + self::assertNotNull($diff->addedPrimaryKey); + self::assertSame(['id'], $diff->addedPrimaryKey->columns); + self::assertNull($diff->removedPrimaryKey); + } + + public function test_primary_key_changed() : void + { + $comparator = new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), new ConstraintComparator(), new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + $source = schema_table('users', [schema_column_integer('id', false), schema_column_text('email')], primaryKey: schema_primary_key(['id'])); + $target = schema_table('users', [schema_column_integer('id', false), schema_column_text('email')], primaryKey: schema_primary_key(['id', 'email'])); + + $diff = $comparator->compare($source, $target); + + self::assertNotNull($diff->addedPrimaryKey); + self::assertNotNull($diff->removedPrimaryKey); + } + + public function test_primary_key_removed() : void + { + $comparator = new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), new ConstraintComparator(), new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + $source = schema_table('users', [schema_column_integer('id', false)], primaryKey: schema_primary_key(['id'])); + $target = schema_table('users', [schema_column_integer('id', false)]); + + $diff = $comparator->compare($source, $target); + + self::assertNull($diff->addedPrimaryKey); + self::assertNotNull($diff->removedPrimaryKey); + self::assertSame(['id'], $diff->removedPrimaryKey->columns); + } + + public function test_trigger_added() : void + { + $comparator = new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), new ConstraintComparator(), new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + $source = schema_table('users', [schema_column_integer('id', false)]); + $target = schema_table('users', [schema_column_integer('id', false)], triggers: [ + schema_trigger('trg_audit', 'users', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'audit_fn'), + ]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->addedTriggers); + self::assertSame('trg_audit', $diff->addedTriggers[0]->name); + } + + public function test_trigger_changed_events() : void + { + $comparator = new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), new ConstraintComparator(), new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + $source = schema_table('users', [schema_column_integer('id', false)], triggers: [ + schema_trigger('trg_audit', 'users', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'audit_fn'), + ]); + $target = schema_table('users', [schema_column_integer('id', false)], triggers: [ + schema_trigger('trg_audit', 'users', TriggerTiming::AFTER, [TriggerEvent::INSERT, TriggerEvent::UPDATE], 'audit_fn'), + ]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->addedTriggers); + self::assertCount(1, $diff->removedTriggers); + } + + public function test_trigger_changed_for_each_row() : void + { + $comparator = new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), new ConstraintComparator(), new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + $source = schema_table('users', [schema_column_integer('id', false)], triggers: [ + schema_trigger('trg_audit', 'users', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'audit_fn', forEachRow: false), + ]); + $target = schema_table('users', [schema_column_integer('id', false)], triggers: [ + schema_trigger('trg_audit', 'users', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'audit_fn', forEachRow: true), + ]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->addedTriggers); + self::assertCount(1, $diff->removedTriggers); + } + + public function test_trigger_changed_function_name() : void + { + $comparator = new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), new ConstraintComparator(), new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + $source = schema_table('users', [schema_column_integer('id', false)], triggers: [ + schema_trigger('trg_audit', 'users', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'audit_fn'), + ]); + $target = schema_table('users', [schema_column_integer('id', false)], triggers: [ + schema_trigger('trg_audit', 'users', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'log_fn'), + ]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->addedTriggers); + self::assertCount(1, $diff->removedTriggers); + } + + public function test_trigger_changed_table_name() : void + { + $comparator = new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), new ConstraintComparator(), new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + $source = schema_table('users', [schema_column_integer('id', false)], triggers: [ + schema_trigger('trg_audit', 'users', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'audit_fn'), + ]); + $target = schema_table('users', [schema_column_integer('id', false)], triggers: [ + schema_trigger('trg_audit', 'accounts', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'audit_fn'), + ]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->addedTriggers); + self::assertCount(1, $diff->removedTriggers); + } + + public function test_trigger_changed_timing() : void + { + $comparator = new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), new ConstraintComparator(), new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + $source = schema_table('users', [schema_column_integer('id', false)], triggers: [ + schema_trigger('trg_audit', 'users', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'audit_fn'), + ]); + $target = schema_table('users', [schema_column_integer('id', false)], triggers: [ + schema_trigger('trg_audit', 'users', TriggerTiming::BEFORE, [TriggerEvent::INSERT], 'audit_fn'), + ]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->addedTriggers); + self::assertCount(1, $diff->removedTriggers); + } + + public function test_trigger_changed_when_condition() : void + { + $comparator = new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), new ConstraintComparator(), new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + $source = schema_table('users', [schema_column_integer('id', false)], triggers: [ + schema_trigger('trg_audit', 'users', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'audit_fn', whenCondition: null), + ]); + $target = schema_table('users', [schema_column_integer('id', false)], triggers: [ + schema_trigger('trg_audit', 'users', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'audit_fn', whenCondition: 'NEW.active = true'), + ]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->addedTriggers); + self::assertCount(1, $diff->removedTriggers); + } + + public function test_trigger_removed() : void + { + $comparator = new TableComparator(new IndexComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())), new ConstraintComparator(), new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + $source = schema_table('users', [schema_column_integer('id', false)], triggers: [ + schema_trigger('trg_audit', 'users', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'audit_fn'), + ]); + $target = schema_table('users', [schema_column_integer('id', false)]); + + $diff = $comparator->compare($source, $target); + + self::assertCount(1, $diff->removedTriggers); + self::assertSame('trg_audit', $diff->removedTriggers[0]->name); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/TableDiffTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/TableDiffTest.php new file mode 100644 index 0000000000..a1a2ba0e63 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/TableDiffTest.php @@ -0,0 +1,905 @@ + 0', 'chk_users_age')], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER TABLE public.users ADD CONSTRAINT chk_users_age CHECK (age > 0)', $sqls[0]->toSql()); + } + + public function test_adds_check_constraint_with_no_inherit() : void + { + $source = schema_table('users', [schema_column_integer('id', false)]); + $target = schema_table('users', [schema_column_integer('id', false)]); + + $diff = new TableDiff( + $source, + $target, + addedCheckConstraints: [new SchemaCheckConstraint('age > 0', 'chk_age', true)], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertStringContainsString('NO INHERIT', $sqls[0]->toSql()); + } + + public function test_adds_column() : void + { + $source = schema_table('users', [schema_column_integer('id', false)]); + $target = schema_table('users', [schema_column_integer('id', false), schema_column_text('name')]); + + $diff = new TableDiff($source, $target, [schema_column_text('name')]); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER TABLE public.users ADD COLUMN name pg_catalog.text', $sqls[0]->toSql()); + } + + public function test_adds_column_with_generated_expression() : void + { + $source = schema_table('users', [schema_column_integer('id', false)]); + $target = schema_table('users', [schema_column_integer('id', false)]); + + $diff = new TableDiff( + $source, + $target, + [new Column('full_name', ColumnType::text(), true, isGenerated: true, generationExpression: "first_name || ' ' || last_name")], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertStringContainsString('ADD COLUMN', $sqls[0]->toSql()); + } + + public function test_adds_column_with_identity() : void + { + $source = schema_table('users', [schema_column_integer('id', false)]); + $target = schema_table('users', [schema_column_integer('id', false)]); + + $diff = new TableDiff( + $source, + $target, + [new Column('seq_id', ColumnType::integer(), false, isIdentity: true, identityGeneration: IdentityGeneration::ALWAYS)], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertStringContainsString('ADD COLUMN', $sqls[0]->toSql()); + } + + public function test_adds_column_with_not_null_and_default() : void + { + $source = schema_table('users', [schema_column_integer('id', false)]); + $target = schema_table('users', [schema_column_integer('id', false), schema_column_text('status', false, "'active'")]); + + $diff = new TableDiff($source, $target, [schema_column_text('status', false, "'active'")]); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame("ALTER TABLE public.users ADD COLUMN status pg_catalog.text NOT NULL DEFAULT 'active'", $sqls[0]->toSql()); + } + + public function test_adds_deferrable_foreign_key() : void + { + $source = schema_table('users', [schema_column_integer('id', false)]); + $target = schema_table('users', [schema_column_integer('id', false)]); + + $diff = new TableDiff( + $source, + $target, + addedForeignKeys: [new ForeignKey('fk_dept', ['dept_id'], 'public', 'departments', ['id'], ReferentialAction::NO_ACTION, ReferentialAction::CASCADE, true, true)], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertStringContainsString('DEFERRABLE', $sqls[0]->toSql()); + self::assertStringContainsString('INITIALLY DEFERRED', $sqls[0]->toSql()); + } + + public function test_adds_exclude_constraint() : void + { + $table = schema_table('users', [schema_column_integer('id', false)]); + + $diff = new TableDiff( + $table, + $table, + addedExcludeConstraints: [schema_exclude('USING gist (tsrange(start_date, end_date) WITH &&)', 'excl_dates_overlap')], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER TABLE public.users ADD CONSTRAINT excl_dates_overlap EXCLUDE USING gist ()', $sqls[0]->toSql()); + } + + public function test_adds_foreign_key() : void + { + $table = schema_table('users', [schema_column_integer('id', false)]); + + $diff = new TableDiff( + $table, + $table, + addedForeignKeys: [schema_foreign_key(['department_id'], 'departments', ['id'], 'fk_users_department')], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER TABLE public.users ADD CONSTRAINT fk_users_department FOREIGN KEY (department_id) REFERENCES public.departments (id)', $sqls[0]->toSql()); + } + + public function test_adds_index() : void + { + $table = schema_table('users', [schema_column_integer('id', false), schema_column_text('name')]); + + $diff = new TableDiff( + $table, + $table, + addedIndexes: [schema_index('idx_users_name', ['name'])], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('CREATE INDEX idx_users_name ON public.users (name)', $sqls[0]->toSql()); + } + + public function test_adds_inherit() : void + { + $source = schema_table('employees', [schema_column_integer('id', false)]); + $target = schema_table('employees', [schema_column_integer('id', false)], inherits: ['persons']); + + $diff = new TableDiff($source, $target, addedInherits: ['persons']); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER TABLE public.employees INHERIT persons', $sqls[0]->toSql()); + } + + public function test_adds_primary_key() : void + { + $table = schema_table('users', [schema_column_integer('id', false)]); + + $diff = new TableDiff( + $table, + $table, + addedPrimaryKey: schema_primary_key(['id'], 'pk_users'), + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER TABLE public.users ADD CONSTRAINT pk_users PRIMARY KEY (id)', $sqls[0]->toSql()); + } + + public function test_adds_trigger() : void + { + $table = schema_table('users', [schema_column_integer('id', false)]); + + $diff = new TableDiff( + $table, + $table, + addedTriggers: [schema_trigger('trg_users_audit', 'users', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'audit_function', true)], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('CREATE TRIGGER trg_users_audit AFTER INSERT ON public.users FOR EACH ROW EXECUTE FUNCTION audit_function()', $sqls[0]->toSql()); + } + + public function test_adds_trigger_with_before_timing() : void + { + $table = schema_table('users', [schema_column_integer('id', false)]); + + $diff = new TableDiff( + $table, + $table, + addedTriggers: [schema_trigger('trg_users_validate', 'users', TriggerTiming::BEFORE, [TriggerEvent::INSERT, TriggerEvent::UPDATE], 'validate_function', true)], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('CREATE TRIGGER trg_users_validate BEFORE INSERT OR UPDATE ON public.users FOR EACH ROW EXECUTE FUNCTION validate_function()', $sqls[0]->toSql()); + } + + public function test_adds_unique_constraint() : void + { + $table = schema_table('users', [schema_column_integer('id', false)]); + + $diff = new TableDiff( + $table, + $table, + addedUniqueConstraints: [schema_unique(['email'], 'uq_users_email')], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER TABLE public.users ADD CONSTRAINT uq_users_email UNIQUE (email)', $sqls[0]->toSql()); + } + + public function test_adds_unique_constraint_with_nulls_not_distinct() : void + { + $source = schema_table('users', [schema_column_integer('id', false)]); + $target = schema_table('users', [schema_column_integer('id', false)]); + + $diff = new TableDiff( + $source, + $target, + addedUniqueConstraints: [new SchemaUniqueConstraint(['email'], 'uq_email', true)], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertStringContainsString('NULLS NOT DISTINCT', $sqls[0]->toSql()); + } + + public function test_changes_tablespace() : void + { + $source = schema_table('users', [schema_column_integer('id', false)]); + $target = schema_table('users', [schema_column_integer('id', false)], tablespace: 'fast_storage'); + + $diff = new TableDiff($source, $target, tablespaceChanged: true); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER TABLE public.users SET TABLESPACE fast_storage', $sqls[0]->toSql()); + } + + public function test_delegates_to_column_diff() : void + { + $source = schema_table('users', [schema_column_text('name')]); + $target = schema_table('users', [schema_column_integer('name', false)]); + + $diff = new TableDiff( + $source, + $target, + modifiedColumns: [new ColumnDiff('public.users', schema_column_text('name'), schema_column_integer('name', false))], + ); + + $sqls = $diff->generate(); + + self::assertCount(2, $sqls); + self::assertSame('ALTER TABLE public.users ALTER COLUMN name TYPE int', $sqls[0]->toSql()); + self::assertSame('ALTER TABLE public.users ALTER COLUMN name SET NOT NULL', $sqls[1]->toSql()); + } + + public function test_dependency_order() : void + { + $source = schema_table('users', [schema_column_integer('id', false)]); + $target = schema_table('users', [schema_column_integer('id', false), schema_column_text('email')]); + + $diff = new TableDiff( + $source, + $target, + [schema_column_text('email')], + addedForeignKeys: [schema_foreign_key(['email'], 'emails', ['address'], 'fk_users_email')], + removedForeignKeys: [schema_foreign_key(['department_id'], 'departments', ['id'], 'fk_users_dept')], + ); + + $sqls = $diff->generate(); + + self::assertCount(3, $sqls); + self::assertSame('ALTER TABLE public.users DROP CONSTRAINT fk_users_dept', $sqls[0]->toSql()); + self::assertSame('ALTER TABLE public.users ADD COLUMN email pg_catalog.text', $sqls[1]->toSql()); + self::assertSame('ALTER TABLE public.users ADD CONSTRAINT fk_users_email FOREIGN KEY (email) REFERENCES public.emails (address)', $sqls[2]->toSql()); + } + + public function test_does_not_require_view_rebuild_when_only_column_added() : void + { + $source = schema_table('users', [schema_column_integer('id', false)]); + $target = schema_table('users', [schema_column_integer('id', false), schema_column_text('name')]); + + $diff = new TableDiff($source, $target, addedColumns: [schema_column_text('name')]); + + self::assertFalse($diff->requiresViewRebuild()); + } + + public function test_does_not_require_view_rebuild_when_only_default_changed() : void + { + $source = schema_table('users', [schema_column_integer('id', false), schema_column_integer('age')]); + $target = schema_table('users', [schema_column_integer('id', false), schema_column_integer('age', default: '0')]); + + $diff = new TableDiff( + $source, + $target, + modifiedColumns: [new ColumnDiff('public.users', schema_column_integer('age'), schema_column_integer('age', default: '0'))], + ); + + self::assertFalse($diff->requiresViewRebuild()); + } + + public function test_does_not_require_view_rebuild_when_only_nullable_changed() : void + { + $source = schema_table('users', [schema_column_integer('id', false), schema_column_text('name')]); + $target = schema_table('users', [schema_column_integer('id', false), schema_column_text('name', nullable: false)]); + + $diff = new TableDiff( + $source, + $target, + modifiedColumns: [new ColumnDiff('public.users', schema_column_text('name'), schema_column_text('name', nullable: false))], + ); + + self::assertFalse($diff->requiresViewRebuild()); + } + + public function test_drops_check_constraint() : void + { + $table = schema_table('users', [schema_column_integer('id', false)]); + + $diff = new TableDiff( + $table, + $table, + removedCheckConstraints: [schema_check('age > 0', 'chk_users_age')], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER TABLE public.users DROP CONSTRAINT chk_users_age', $sqls[0]->toSql()); + } + + public function test_drops_column() : void + { + $source = schema_table('users', [schema_column_integer('id', false), schema_column_text('name')]); + $target = schema_table('users', [schema_column_integer('id', false)]); + + $diff = new TableDiff( + $source, + $target, + removedColumns: [schema_column_text('name')], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER TABLE public.users DROP name', $sqls[0]->toSql()); + } + + public function test_drops_exclude_constraint() : void + { + $table = schema_table('users', [schema_column_integer('id', false)]); + + $diff = new TableDiff( + $table, + $table, + removedExcludeConstraints: [schema_exclude('USING gist (tsrange(start_date, end_date) WITH &&)', 'excl_dates_overlap')], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER TABLE public.users DROP CONSTRAINT excl_dates_overlap', $sqls[0]->toSql()); + } + + public function test_drops_foreign_key() : void + { + $table = schema_table('users', [schema_column_integer('id', false)]); + + $diff = new TableDiff( + $table, + $table, + removedForeignKeys: [schema_foreign_key(['department_id'], 'departments', ['id'], 'fk_users_department')], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER TABLE public.users DROP CONSTRAINT fk_users_department', $sqls[0]->toSql()); + } + + public function test_drops_index() : void + { + $table = schema_table('users', [schema_column_integer('id', false)]); + + $diff = new TableDiff( + $table, + $table, + removedIndexes: [schema_index('idx_users_name', ['name'])], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('DROP INDEX idx_users_name', $sqls[0]->toSql()); + } + + public function test_drops_primary_key() : void + { + $table = schema_table('users', [schema_column_integer('id', false)]); + + $diff = new TableDiff( + $table, + $table, + removedPrimaryKey: schema_primary_key(['id'], 'pk_users'), + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER TABLE public.users DROP CONSTRAINT pk_users', $sqls[0]->toSql()); + } + + public function test_drops_trigger() : void + { + $table = schema_table('users', [schema_column_integer('id', false)]); + + $diff = new TableDiff( + $table, + $table, + removedTriggers: [schema_trigger('trg_users_audit', 'users', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'audit_function', true)], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('DROP TRIGGER trg_users_audit ON public.users', $sqls[0]->toSql()); + } + + public function test_drops_unique_constraint() : void + { + $table = schema_table('users', [schema_column_integer('id', false)]); + + $diff = new TableDiff( + $table, + $table, + removedUniqueConstraints: [schema_unique(['email'], 'uq_users_email')], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER TABLE public.users DROP CONSTRAINT uq_users_email', $sqls[0]->toSql()); + } + + public function test_empty_diff() : void + { + $table = schema_table('users', [schema_column_integer('id', false)]); + + $diff = new TableDiff($table, $table); + + self::assertTrue($diff->isEmpty()); + } + + public function test_not_empty_when_column_added() : void + { + $source = schema_table('users', [schema_column_integer('id', false)]); + $target = schema_table('users', [ + schema_column_integer('id', false), + schema_column_text('name'), + ]); + + $diff = new TableDiff($source, $target, [schema_column_text('name')]); + + self::assertFalse($diff->isEmpty()); + } + + public function test_not_empty_when_column_modified() : void + { + $source = schema_table('users', [schema_column_text('name')]); + $target = schema_table('users', [schema_column_text('name', false)]); + + $diff = new TableDiff( + $source, + $target, + modifiedColumns: [new ColumnDiff('public.users', schema_column_text('name'), schema_column_text('name', false))], + ); + + self::assertFalse($diff->isEmpty()); + } + + public function test_not_empty_when_inherits_added() : void + { + $source = schema_table('employees', [schema_column_integer('id', false)]); + $target = schema_table('employees', [schema_column_integer('id', false)], inherits: ['persons']); + + $diff = new TableDiff($source, $target, addedInherits: ['persons']); + + self::assertFalse($diff->isEmpty()); + } + + public function test_not_empty_when_inherits_removed() : void + { + $source = schema_table('employees', [schema_column_integer('id', false)], inherits: ['persons']); + $target = schema_table('employees', [schema_column_integer('id', false)]); + + $diff = new TableDiff($source, $target, removedInherits: ['persons']); + + self::assertFalse($diff->isEmpty()); + } + + public function test_not_empty_when_partition_changed() : void + { + $source = schema_table('events', [schema_column_integer('id', false)]); + $target = schema_table('events', [schema_column_integer('id', false)], partitionStrategy: PartitionStrategy::RANGE, partitionColumns: ['id']); + + $diff = new TableDiff($source, $target, partitionChanged: true); + + self::assertFalse($diff->isEmpty()); + } + + public function test_not_empty_when_tablespace_changed() : void + { + $source = schema_table('users', [schema_column_integer('id', false)]); + $target = schema_table('users', [schema_column_integer('id', false)], tablespace: 'fast_storage'); + + $diff = new TableDiff($source, $target, tablespaceChanged: true); + + self::assertFalse($diff->isEmpty()); + } + + public function test_not_empty_when_unlogged_changed() : void + { + $source = schema_table('users', [schema_column_integer('id', false)]); + $target = schema_table('users', [schema_column_integer('id', false)], unlogged: true); + + $diff = new TableDiff($source, $target, unloggedChanged: true); + + self::assertFalse($diff->isEmpty()); + } + + public function test_partition_changed_throws_runtime_exception() : void + { + $source = schema_table('events', [schema_column_integer('id', false)]); + $target = schema_table('events', [schema_column_integer('id', false)], partitionStrategy: PartitionStrategy::RANGE, partitionColumns: ['id']); + + $diff = new TableDiff($source, $target, partitionChanged: true); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('Partition strategy change on table "public.events" cannot be applied via ALTER TABLE'); + + $diff->generate(); + } + + public function test_removes_inherit() : void + { + $source = schema_table('employees', [schema_column_integer('id', false)], inherits: ['persons']); + $target = schema_table('employees', [schema_column_integer('id', false)]); + + $diff = new TableDiff($source, $target, removedInherits: ['persons']); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER TABLE public.employees NO INHERIT persons', $sqls[0]->toSql()); + } + + public function test_renames_index() : void + { + $table = schema_table('users', [schema_column_integer('id', false)]); + + $diff = new TableDiff( + $table, + $table, + renamedIndexes: ['idx_users_name' => schema_index('idx_users_email', ['email'])], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER INDEX public.idx_users_name RENAME TO idx_users_email', $sqls[0]->toSql()); + } + + public function test_requires_view_rebuild_when_column_dropped() : void + { + $source = schema_table('users', [schema_column_integer('id', false), schema_column_text('name')]); + $target = schema_table('users', [schema_column_integer('id', false)]); + + $diff = new TableDiff($source, $target, removedColumns: [schema_column_text('name')]); + + self::assertTrue($diff->requiresViewRebuild()); + } + + public function test_requires_view_rebuild_when_column_renamed() : void + { + $source = schema_table('users', [schema_column_integer('id', false), schema_column_text('name')]); + $target = schema_table('users', [schema_column_integer('id', false), schema_column_text('full_name')]); + + $diff = new TableDiff( + $source, + $target, + modifiedColumns: [new ColumnDiff('public.users', schema_column_text('name'), schema_column_text('full_name'))], + ); + + self::assertTrue($diff->requiresViewRebuild()); + } + + public function test_requires_view_rebuild_when_column_type_changes() : void + { + $source = schema_table('users', [schema_column_integer('id', false), schema_column_integer('amount')]); + $target = schema_table('users', [schema_column_integer('id', false), schema_column_text('amount')]); + + $diff = new TableDiff( + $source, + $target, + modifiedColumns: [new ColumnDiff('public.users', schema_column_integer('amount'), schema_column_text('amount'))], + ); + + self::assertTrue($diff->requiresViewRebuild()); + } + + public function test_returns_empty_when_no_changes() : void + { + $table = schema_table('users', [schema_column_integer('id', false)]); + + $diff = new TableDiff($table, $table); + + self::assertSame([], $diff->generate()); + } + + public function test_reversed_add_column() : void + { + $source = schema_table('users', [schema_column_integer('id', false), schema_column_text('name')]); + $target = schema_table('users', [schema_column_integer('id', false)]); + + $diff = new TableDiff($target, $source, removedColumns: [schema_column_text('name')]); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER TABLE public.users DROP name', $sqls[0]->toSql()); + } + + public function test_reversed_add_index() : void + { + $table = schema_table('users', [schema_column_integer('id', false)]); + + $diff = new TableDiff( + $table, + $table, + removedIndexes: [schema_index('idx_name', ['name'])], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('DROP INDEX idx_name', $sqls[0]->toSql()); + } + + public function test_reversed_add_primary_key() : void + { + $table = schema_table('users', [schema_column_integer('id', false)]); + + $diff = new TableDiff( + $table, + $table, + removedPrimaryKey: schema_primary_key(['id'], 'pk_users'), + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER TABLE public.users DROP CONSTRAINT pk_users', $sqls[0]->toSql()); + } + + public function test_reversed_add_trigger() : void + { + $table = schema_table('users', [schema_column_integer('id', false)]); + + $diff = new TableDiff( + $table, + $table, + removedTriggers: [schema_trigger('trg_audit', 'users', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'audit_fn')], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertStringContainsString('DROP TRIGGER trg_audit', $sqls[0]->toSql()); + } + + public function test_reversed_drop_check_constraint() : void + { + $table = schema_table('users', [schema_column_integer('id', false)]); + + $diff = new TableDiff( + $table, + $table, + addedCheckConstraints: [schema_check('age > 0', 'chk_age')], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertStringContainsString('CHECK', $sqls[0]->toSql()); + } + + public function test_reversed_drop_foreign_key() : void + { + $table = schema_table('users', [schema_column_integer('id', false)]); + + $diff = new TableDiff( + $table, + $table, + addedForeignKeys: [schema_foreign_key(['dept_id'], 'departments', ['id'], 'fk_dept')], + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertStringContainsString('FOREIGN KEY', $sqls[0]->toSql()); + } + + public function test_reversed_inherit_changes() : void + { + $source = schema_table('employees', [schema_column_integer('id', false)], inherits: ['persons']); + $target = schema_table('employees', [schema_column_integer('id', false)]); + + $diff = new TableDiff($source, $target, removedInherits: ['persons']); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER TABLE public.employees NO INHERIT persons', $sqls[0]->toSql()); + } + + public function test_reversed_modified_column() : void + { + $source = schema_table('users', [schema_column_integer('name', false)]); + $target = schema_table('users', [schema_column_text('name')]); + + $diff = new TableDiff( + $source, + $target, + modifiedColumns: [new ColumnDiff('public.users', schema_column_integer('name', false), schema_column_text('name'))], + ); + + $sqls = $diff->generate(); + + self::assertCount(2, $sqls); + self::assertStringContainsString('TYPE', $sqls[0]->toSql()); + } + + public function test_reversed_unlogged_change() : void + { + $source = schema_table('users', [schema_column_integer('id', false)], unlogged: true); + $target = schema_table('users', [schema_column_integer('id', false)]); + + $diff = new TableDiff($source, $target, unloggedChanged: true); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER TABLE public.users SET LOGGED', $sqls[0]->toSql()); + } + + public function test_sets_logged() : void + { + $source = schema_table('users', [schema_column_integer('id', false)], unlogged: true); + $target = schema_table('users', [schema_column_integer('id', false)]); + + $diff = new TableDiff($source, $target, unloggedChanged: true); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER TABLE public.users SET LOGGED', $sqls[0]->toSql()); + } + + public function test_sets_unlogged() : void + { + $source = schema_table('users', [schema_column_integer('id', false)]); + $target = schema_table('users', [schema_column_integer('id', false)], unlogged: true); + + $diff = new TableDiff($source, $target, unloggedChanged: true); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('ALTER TABLE public.users SET UNLOGGED', $sqls[0]->toSql()); + } + + public function test_throws_when_dropping_unnamed_check_constraint() : void + { + $table = schema_table('users', [schema_column_integer('id', false)]); + + $diff = new TableDiff( + $table, + $table, + removedCheckConstraints: [schema_check('age > 0')], + ); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('Cannot drop unnamed check constraint on table "public.users"'); + + $diff->generate(); + } + + public function test_throws_when_dropping_unnamed_exclude_constraint() : void + { + $table = schema_table('users', [schema_column_integer('id', false)]); + + $diff = new TableDiff( + $table, + $table, + removedExcludeConstraints: [schema_exclude('USING gist (col WITH &&)')], + ); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('Cannot drop unnamed exclude constraint on table "public.users"'); + + $diff->generate(); + } + + public function test_throws_when_dropping_unnamed_foreign_key() : void + { + $table = schema_table('users', [schema_column_integer('id', false)]); + + $diff = new TableDiff( + $table, + $table, + removedForeignKeys: [schema_foreign_key(['department_id'], 'departments', ['id'])], + ); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('Cannot drop unnamed foreign key on table "public.users"'); + + $diff->generate(); + } + + public function test_throws_when_dropping_unnamed_primary_key() : void + { + $table = schema_table('users', [schema_column_integer('id', false)]); + + $diff = new TableDiff( + $table, + $table, + removedPrimaryKey: schema_primary_key(['id']), + ); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('Cannot drop unnamed primary key on table "public.users"'); + + $diff->generate(); + } + + public function test_throws_when_dropping_unnamed_unique_constraint() : void + { + $table = schema_table('users', [schema_column_integer('id', false)]); + + $diff = new TableDiff( + $table, + $table, + removedUniqueConstraints: [schema_unique(['email'])], + ); + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('Cannot drop unnamed unique constraint on table "public.users"'); + + $diff->generate(); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/TableStructureComparatorTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/TableStructureComparatorTest.php new file mode 100644 index 0000000000..d5345f57f1 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/TableStructureComparatorTest.php @@ -0,0 +1,220 @@ +detectTableRenames( + [schema_table('table_c', [schema_column_integer('id', false)])], + [schema_table('table_a', [schema_column_integer('id', false)]), schema_table('table_b', [schema_column_integer('id', false)])], + ); + + self::assertCount(0, $result->added); + self::assertCount(1, $result->removed); + self::assertCount(1, $result->renamed); + } + + public function test_detect_rename_not_triggered_when_columns_differ() : void + { + $comparator = new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + + $result = $comparator->detectTableRenames( + [schema_table('new_users', [schema_column_integer('id', false), schema_column_text('name')])], + [schema_table('old_users', [schema_column_integer('id', false)])], + ); + + self::assertCount(1, $result->added); + self::assertCount(1, $result->removed); + self::assertNull($result->renamed); + } + + public function test_detect_rename_when_structure_identical() : void + { + $comparator = new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + + $result = $comparator->detectTableRenames( + [schema_table('new_users', [schema_column_integer('id', false), schema_column_text('name')], schema_primary_key(['id']))], + [schema_table('old_users', [schema_column_integer('id', false), schema_column_text('name')], schema_primary_key(['id']))], + ); + + self::assertCount(0, $result->added); + self::assertCount(0, $result->removed); + self::assertCount(1, $result->renamed); + self::assertArrayHasKey('public.old_users', $result->renamed); + self::assertSame('new_users', $result->renamed['public.old_users']->name); + } + + public function test_identical_tables_are_structurally_equal() : void + { + $comparator = new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + $a = schema_table('users', [schema_column_integer('id', false), schema_column_text('name')], schema_primary_key(['id'])); + $b = schema_table('users', [schema_column_integer('id', false), schema_column_text('name')], schema_primary_key(['id'])); + + self::assertTrue($comparator->haveEqualStructure($a, $b)); + } + + public function test_tables_differ_by_column_count() : void + { + $comparator = new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + $a = schema_table('t', [schema_column_integer('id', false)]); + $b = schema_table('t', [schema_column_integer('id', false), schema_column_text('name')]); + + self::assertFalse($comparator->haveEqualStructure($a, $b)); + } + + public function test_tables_differ_by_column_nullable() : void + { + $comparator = new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + $a = schema_table('t', [schema_column_integer('id', false)]); + $b = schema_table('t', [schema_column_integer('id', true)]); + + self::assertFalse($comparator->haveEqualStructure($a, $b)); + } + + public function test_tables_differ_by_column_type() : void + { + $comparator = new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + $a = schema_table('t', [schema_column_integer('id', false), schema_column_text('name')]); + $b = schema_table('t', [schema_column_integer('id', false), schema_column_varchar('name', 255)]); + + self::assertFalse($comparator->haveEqualStructure($a, $b)); + } + + public function test_tables_differ_by_inherits() : void + { + $comparator = new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + $a = schema_table('t', [schema_column_integer('id', false)]); + $b = schema_table('t', [schema_column_integer('id', false)], inherits: ['parent']); + + self::assertFalse($comparator->haveEqualStructure($a, $b)); + } + + public function test_tables_differ_by_partition_strategy() : void + { + $comparator = new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + $a = schema_table('t', [schema_column_integer('id', false)]); + $b = schema_table('t', [schema_column_integer('id', false)], partitionStrategy: PartitionStrategy::RANGE, partitionColumns: ['id']); + + self::assertFalse($comparator->haveEqualStructure($a, $b)); + } + + public function test_tables_differ_by_primary_key() : void + { + $comparator = new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + $a = schema_table('t', [schema_column_integer('id', false)], schema_primary_key(['id'])); + $b = schema_table('t', [schema_column_integer('id', false)]); + + self::assertFalse($comparator->haveEqualStructure($a, $b)); + } + + public function test_tables_differ_by_tablespace() : void + { + $comparator = new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + $a = schema_table('t', [schema_column_integer('id', false)]); + $b = schema_table('t', [schema_column_integer('id', false)], tablespace: 'fast_storage'); + + self::assertFalse($comparator->haveEqualStructure($a, $b)); + } + + public function test_tables_differ_by_unlogged() : void + { + $comparator = new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + $a = schema_table('t', [schema_column_integer('id', false)]); + $b = schema_table('t', [schema_column_integer('id', false)], unlogged: true); + + self::assertFalse($comparator->haveEqualStructure($a, $b)); + } + + public function test_tables_not_equal_across_different_schemas() : void + { + $comparator = new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + $a = schema_table('t', [schema_column_integer('id', false)], schema: 'public'); + $b = schema_table('t', [schema_column_integer('id', false)], schema: 'audit'); + + self::assertFalse($comparator->haveEqualStructure($a, $b)); + } + + public function test_tables_with_different_constraint_names_are_structurally_equal() : void + { + $comparator = new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + $a = schema_table( + 'old', + [schema_column_integer('id', false), schema_column_text('email')], + uniqueConstraints: [schema_unique(['email'], 'uq_old_email')], + checkConstraints: [new CheckConstraint("email <> ''", 'chk_old')], + ); + $b = schema_table( + 'new', + [schema_column_integer('id', false), schema_column_text('email')], + uniqueConstraints: [schema_unique(['email'], 'uq_new_email')], + checkConstraints: [new CheckConstraint("email <> ''", 'chk_new')], + ); + + self::assertTrue($comparator->haveEqualStructure($a, $b)); + } + + public function test_tables_with_different_index_names_are_structurally_equal() : void + { + $comparator = new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + $a = schema_table('old', [schema_column_integer('id', false), schema_column_text('email')], indexes: [ + schema_index('idx_old_email', ['email']), + ]); + $b = schema_table('new', [schema_column_integer('id', false), schema_column_text('email')], indexes: [ + schema_index('idx_new_email', ['email']), + ]); + + self::assertTrue($comparator->haveEqualStructure($a, $b)); + } + + public function test_tables_with_different_index_structure_are_not_equal() : void + { + $comparator = new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + $a = schema_table('old', [schema_column_integer('id', false), schema_column_text('email')], indexes: [ + schema_index('idx_old', ['email']), + ]); + $b = schema_table('new', [schema_column_integer('id', false), schema_column_text('email')], indexes: [ + schema_index('idx_new', ['email'], unique: true), + ]); + + self::assertFalse($comparator->haveEqualStructure($a, $b)); + } + + public function test_tables_with_different_names_are_structurally_equal() : void + { + $comparator = new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + $a = schema_table('old_users', [schema_column_integer('id', false), schema_column_text('name')]); + $b = schema_table('new_users', [schema_column_integer('id', false), schema_column_text('name')]); + + self::assertTrue($comparator->haveEqualStructure($a, $b)); + } + + public function test_tables_with_different_trigger_names_are_structurally_equal() : void + { + $comparator = new TableStructureComparator(new GreedySimilarityRenameStrategy(new SimilarTextStrategy())); + $a = schema_table( + 'old', + [schema_column_integer('id', false)], + triggers: [schema_trigger('trg_old', 'old', TriggerTiming::BEFORE, [TriggerEvent::INSERT], 'my_func')], + ); + $b = schema_table( + 'new', + [schema_column_integer('id', false)], + triggers: [schema_trigger('trg_new', 'new', TriggerTiming::BEFORE, [TriggerEvent::INSERT], 'my_func')], + ); + + self::assertTrue($comparator->haveEqualStructure($a, $b)); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/ViewDependencyResolverTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/ViewDependencyResolverTest.php new file mode 100644 index 0000000000..de809eef7e --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/ViewDependencyResolverTest.php @@ -0,0 +1,145 @@ +resolve($catalog, ['public.orders']); + + self::assertTrue($result->isEmpty()); + } + + public function test_resolves_cascading_view_dependencies() : void + { + $catalog = new Catalog([ + schema( + 'data', + tables: [schema_table('events', [schema_column_integer('id', false), schema_column_text('type')])], + ), + schema( + 'report', + views: [schema_view('event_summary', 'SELECT * FROM data.events')], + ), + schema( + 'public', + views: [schema_view('dashboard', 'SELECT * FROM report.event_summary')], + ), + ]); + + $resolver = ast_view_dependency_resolver(); + $result = $resolver->resolve($catalog, ['data.events']); + + self::assertCount(2, $result->toDrop); + self::assertSame('public.dashboard', $result->toDrop[0]->qualifiedName()); + self::assertSame('report.event_summary', $result->toDrop[1]->qualifiedName()); + + self::assertCount(2, $result->toCreate); + self::assertSame('report.event_summary', $result->toCreate[0]->qualifiedName()); + self::assertSame('public.dashboard', $result->toCreate[1]->qualifiedName()); + } + + public function test_resolves_cross_schema_dependency() : void + { + $catalog = new Catalog([ + schema( + 'enriched', + tables: [schema_table('full_data', [schema_column_integer('id', false), schema_column_integer('amount')])], + ), + schema( + 'public', + views: [schema_view('enriched_full_data', 'SELECT * FROM enriched.full_data')], + ), + ]); + + $resolver = ast_view_dependency_resolver(); + $result = $resolver->resolve($catalog, ['enriched.full_data']); + + self::assertCount(1, $result->toDrop); + self::assertSame('public.enriched_full_data', $result->toDrop[0]->qualifiedName()); + self::assertInstanceOf(View::class, $result->toDrop[0]->view); + + self::assertCount(1, $result->toCreate); + self::assertSame('public.enriched_full_data', $result->toCreate[0]->qualifiedName()); + } + + public function test_resolves_materialized_view_depending_on_modified_table() : void + { + $catalog = new Catalog([ + schema( + 'public', + tables: [schema_table('orders', [schema_column_integer('id', false), schema_column_integer('total')])], + materializedViews: [schema_materialized_view('mv_order_stats', 'SELECT * FROM orders')], + ), + ]); + + $resolver = ast_view_dependency_resolver(); + $result = $resolver->resolve($catalog, ['public.orders']); + + self::assertCount(1, $result->toDrop); + self::assertSame('public.mv_order_stats', $result->toDrop[0]->qualifiedName()); + self::assertInstanceOf(MaterializedView::class, $result->toDrop[0]->view); + + self::assertCount(1, $result->toCreate); + self::assertSame('public.mv_order_stats', $result->toCreate[0]->qualifiedName()); + } + + public function test_resolves_view_depending_on_modified_table() : void + { + $catalog = new Catalog([ + schema( + 'public', + tables: [schema_table('users', [schema_column_integer('id', false), schema_column_text('name')])], + views: [schema_view('active_users', 'SELECT * FROM users')], + ), + ]); + + $resolver = ast_view_dependency_resolver(); + $result = $resolver->resolve($catalog, ['public.users']); + + self::assertCount(1, $result->toDrop); + self::assertSame('public.active_users', $result->toDrop[0]->qualifiedName()); + self::assertInstanceOf(View::class, $result->toDrop[0]->view); + + self::assertCount(1, $result->toCreate); + self::assertSame('public.active_users', $result->toCreate[0]->qualifiedName()); + } + + public function test_returns_empty_when_no_modified_tables() : void + { + $catalog = new Catalog([ + schema( + 'public', + tables: [schema_table('users', [schema_column_integer('id', false)])], + views: [schema_view('active_users', 'SELECT * FROM users')], + ), + ]); + + $resolver = ast_view_dependency_resolver(); + $result = $resolver->resolve($catalog, []); + + self::assertTrue($result->isEmpty()); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/ViewDiffTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/ViewDiffTest.php new file mode 100644 index 0000000000..31fcb93a48 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/Diff/ViewDiffTest.php @@ -0,0 +1,39 @@ +from(table('users'))->where(eq(col('active'), literal(true)))->toSql()), + schema_view('active_users', select(star())->from(table('users'))->where(and_(eq(col('active'), literal(true)), eq(col('verified'), literal(true))))->toSql()), + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('CREATE OR REPLACE VIEW active_users AS SELECT * FROM users WHERE active = true AND verified = true', $sqls[0]->toSql()); + } + + public function test_reversed_view_definition_change() : void + { + $diff = new ViewDiff( + schema_view('active_users', select(star())->from(table('users'))->where(and_(eq(col('active'), literal(true)), eq(col('verified'), literal(true))))->toSql()), + schema_view('active_users', select(star())->from(table('users'))->where(eq(col('active'), literal(true)))->toSql()), + ); + + $sqls = $diff->generate(); + + self::assertCount(1, $sqls); + self::assertSame('CREATE OR REPLACE VIEW active_users AS SELECT * FROM users WHERE active = true', $sqls[0]->toSql()); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/DomainTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/DomainTest.php new file mode 100644 index 0000000000..ce7caf6a44 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/DomainTest.php @@ -0,0 +1,60 @@ +name); + self::assertTrue($domain->nullable); + self::assertNull($domain->default); + self::assertSame([], $domain->checkConstraints); + } + + public function test_domain_with_constraints() : void + { + $domain = schema_domain( + 'positive_int', + column_type_integer(), + nullable: false, + default: '0', + checkConstraints: [schema_check('VALUE > 0', 'chk_positive')], + ); + + self::assertFalse($domain->nullable); + self::assertSame('0', $domain->default); + self::assertCount(1, $domain->checkConstraints); + self::assertSame('VALUE > 0', $domain->checkConstraints[0]->expression); + } + + public function test_to_sql_generates_create_domain() : void + { + self::assertSame( + 'CREATE DOMAIN email_address AS varchar(255)', + schema_domain('email_address', column_type_varchar(255))->toSql()->toSql(), + ); + } + + public function test_to_sql_generates_create_domain_with_constraints() : void + { + self::assertSame( + 'CREATE DOMAIN positive_int AS int NOT NULL DEFAULT 0 CONSTRAINT chk_positive CHECK (value > 0)', + schema_domain( + 'positive_int', + column_type_integer(), + nullable: false, + default: '0', + checkConstraints: [schema_check('VALUE > 0', 'chk_positive')], + )->toSql()->toSql(), + ); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/ExtensionTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/ExtensionTest.php new file mode 100644 index 0000000000..8cfb8e3198 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/ExtensionTest.php @@ -0,0 +1,44 @@ +name); + self::assertNull($ext->version); + } + + public function test_extension_with_version() : void + { + $ext = schema_extension('postgis', '3.4.0'); + + self::assertSame('postgis', $ext->name); + self::assertSame('3.4.0', $ext->version); + } + + public function test_to_sql_generates_create_extension() : void + { + self::assertSame( + 'CREATE EXTENSION "uuid-ossp"', + schema_extension('uuid-ossp')->toSql()->toSql(), + ); + } + + public function test_to_sql_generates_create_extension_with_version() : void + { + self::assertSame( + 'CREATE EXTENSION postgis VERSION "3.4.0"', + schema_extension('postgis', '3.4.0')->toSql()->toSql(), + ); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/ForeignKeyDependencyOrderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/ForeignKeyDependencyOrderTest.php new file mode 100644 index 0000000000..64a1d31a41 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/ForeignKeyDependencyOrderTest.php @@ -0,0 +1,221 @@ +expectException(SchemaException::class); + $this->expectExceptionMessage('Circular foreign key dependency'); + + (new ForeignKeyDependencyOrder())->order([$tableA, $tableB]); + } + + public function test_diamond_dependency() : void + { + $root = schema_table( + 'root', + [schema_column_integer('id')], + schema_primary_key(['id']), + schema: 'public', + ); + + $left = schema_table( + 'left_table', + [schema_column_integer('id'), schema_column_integer('root_id')], + schema_primary_key(['id']), + foreignKeys: [schema_foreign_key(['root_id'], 'root', ['id'])], + schema: 'public', + ); + + $right = schema_table( + 'right_table', + [schema_column_integer('id'), schema_column_integer('root_id')], + schema_primary_key(['id']), + foreignKeys: [schema_foreign_key(['root_id'], 'root', ['id'])], + schema: 'public', + ); + + $bottom = schema_table( + 'bottom', + [schema_column_integer('id'), schema_column_integer('left_id'), schema_column_integer('right_id')], + schema_primary_key(['id']), + foreignKeys: [ + schema_foreign_key(['left_id'], 'left_table', ['id']), + schema_foreign_key(['right_id'], 'right_table', ['id']), + ], + schema: 'public', + ); + + $result = (new ForeignKeyDependencyOrder())->order([$bottom, $left, $right, $root]); + + $names = \array_map(static fn ($t) => $t->name, $result); + + self::assertSame('root', $names[0]); + $leftIdx = \array_search('left_table', $names, true); + $rightIdx = \array_search('right_table', $names, true); + $bottomIdx = \array_search('bottom', $names, true); + self::assertGreaterThan($leftIdx, $bottomIdx); + self::assertGreaterThan($rightIdx, $bottomIdx); + } + + public function test_empty_list() : void + { + self::assertSame([], (new ForeignKeyDependencyOrder())->order([])); + } + + public function test_fk_referencing_table_outside_the_list_is_ignored() : void + { + $independent = schema_table( + 'independent', + [schema_column_integer('id')], + schema_primary_key(['id']), + schema: 'public', + ); + + $child = schema_table( + 'child', + [schema_column_integer('id'), schema_column_integer('external_id')], + schema_primary_key(['id']), + foreignKeys: [schema_foreign_key(['external_id'], 'external_table', ['id'], referenceSchema: 'other_schema')], + schema: 'public', + ); + + $result = (new ForeignKeyDependencyOrder())->order([$independent, $child]); + + self::assertCount(2, $result); + } + + public function test_linear_chain() : void + { + $grandparent = schema_table( + 'grandparent', + [schema_column_integer('id')], + schema_primary_key(['id']), + schema: 'public', + ); + + $parent = schema_table( + 'parent', + [schema_column_integer('id'), schema_column_integer('gp_id')], + schema_primary_key(['id']), + foreignKeys: [schema_foreign_key(['gp_id'], 'grandparent', ['id'])], + schema: 'public', + ); + + $child = schema_table( + 'child', + [schema_column_integer('id'), schema_column_integer('parent_id')], + schema_primary_key(['id']), + foreignKeys: [schema_foreign_key(['parent_id'], 'parent', ['id'])], + schema: 'public', + ); + + $result = (new ForeignKeyDependencyOrder())->order([$child, $parent, $grandparent]); + + $names = \array_map(static fn ($t) => $t->name, $result); + + self::assertSame(['grandparent', 'parent', 'child'], $names); + } + + public function test_self_referencing_fk() : void + { + $categories = schema_table( + 'categories', + [schema_column_integer('id'), schema_column_integer('parent_id')], + schema_primary_key(['id']), + foreignKeys: [schema_foreign_key(['parent_id'], 'categories', ['id'])], + schema: 'public', + ); + + $products = schema_table( + 'products', + [schema_column_integer('id'), schema_column_integer('category_id')], + schema_primary_key(['id']), + foreignKeys: [schema_foreign_key(['category_id'], 'categories', ['id'])], + schema: 'public', + ); + + $result = (new ForeignKeyDependencyOrder())->order([$products, $categories]); + + $names = \array_map(static fn ($t) => $t->name, $result); + + self::assertSame(['categories', 'products'], $names); + } + + public function test_single_table() : void + { + $table = schema_table( + 'users', + [schema_column_integer('id'), schema_column_text('name')], + schema_primary_key(['id']), + schema: 'public', + ); + + $result = (new ForeignKeyDependencyOrder())->order([$table]); + + self::assertCount(1, $result); + self::assertSame('users', $result[0]->name); + } + + public function test_tables_without_fks_preserve_order() : void + { + $tableA = schema_table( + 'alpha', + [schema_column_integer('id')], + schema_primary_key(['id']), + schema: 'public', + ); + + $tableB = schema_table( + 'beta', + [schema_column_integer('id')], + schema_primary_key(['id']), + schema: 'public', + ); + + $tableC = schema_table( + 'gamma', + [schema_column_integer('id')], + schema_primary_key(['id']), + schema: 'public', + ); + + $result = (new ForeignKeyDependencyOrder())->order([$tableA, $tableB, $tableC]); + + $names = \array_map(static fn ($t) => $t->name, $result); + + self::assertSame(['alpha', 'beta', 'gamma'], $names); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/FunctionTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/FunctionTest.php new file mode 100644 index 0000000000..b357c1f197 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/FunctionTest.php @@ -0,0 +1,138 @@ +name); + self::assertSame('timestamp with time zone', $func->returnType); + self::assertSame([], $func->argumentTypes); + self::assertSame('sql', $func->language); + self::assertNull($func->definition); + self::assertFalse($func->isStrict); + self::assertNull($func->volatility); + } + + public function test_function_with_all_options() : void + { + $func = schema_function( + 'add_numbers', + 'integer', + argumentTypes: ['integer', 'integer'], + language: 'plpgsql', + definition: 'BEGIN RETURN $1 + $2; END;', + isStrict: true, + volatility: FunctionVolatility::IMMUTABLE, + ); + + self::assertSame(['integer', 'integer'], $func->argumentTypes); + self::assertSame('plpgsql', $func->language); + self::assertTrue($func->isStrict); + self::assertSame(FunctionVolatility::IMMUTABLE, $func->volatility); + } + + public function test_to_sql_generates_create_function() : void + { + self::assertSame( + 'CREATE OR REPLACE FUNCTION add_numbers(IN int, IN int) RETURNS int LANGUAGE plpgsql RETURNS NULL ON NULL INPUT IMMUTABLE AS $$BEGIN RETURN $1 + $2; END;$$', + schema_function( + 'add_numbers', + 'integer', + argumentTypes: ['integer', 'integer'], + language: 'plpgsql', + definition: 'BEGIN RETURN $1 + $2; END;', + isStrict: true, + volatility: FunctionVolatility::IMMUTABLE, + )->toSql()->toSql(), + ); + } + + public function test_to_sql_generates_function_without_arguments() : void + { + self::assertSame( + 'CREATE OR REPLACE FUNCTION current_user_id() RETURNS int LANGUAGE sql AS $$SELECT 1$$', + schema_function( + 'current_user_id', + 'integer', + language: 'sql', + definition: 'SELECT 1', + )->toSql()->toSql(), + ); + } + + public function test_to_sql_generates_immutable_function_without_strict() : void + { + self::assertSame( + 'CREATE OR REPLACE FUNCTION pi_val() RETURNS double precision LANGUAGE sql IMMUTABLE AS $$SELECT 3.14159$$', + schema_function( + 'pi_val', + 'double precision', + language: 'sql', + definition: 'SELECT 3.14159', + volatility: FunctionVolatility::IMMUTABLE, + )->toSql()->toSql(), + ); + } + + public function test_to_sql_generates_stable_function() : void + { + self::assertSame( + 'CREATE OR REPLACE FUNCTION get_name(IN int) RETURNS text LANGUAGE sql STABLE AS $$SELECT name FROM users WHERE id = $1$$', + schema_function( + 'get_name', + 'text', + argumentTypes: ['integer'], + language: 'sql', + definition: 'SELECT name FROM users WHERE id = $1', + volatility: FunctionVolatility::STABLE, + )->toSql()->toSql(), + ); + } + + public function test_to_sql_generates_strict_function_without_volatility() : void + { + self::assertSame( + 'CREATE OR REPLACE FUNCTION double_it(IN int) RETURNS int LANGUAGE sql RETURNS NULL ON NULL INPUT AS $$SELECT $1 * 2$$', + schema_function( + 'double_it', + 'integer', + argumentTypes: ['integer'], + language: 'sql', + definition: 'SELECT $1 * 2', + isStrict: true, + )->toSql()->toSql(), + ); + } + + public function test_to_sql_generates_volatile_function() : void + { + self::assertSame( + 'CREATE OR REPLACE FUNCTION update_ts() RETURNS trigger LANGUAGE plpgsql VOLATILE AS $$BEGIN NEW.updated_at = now(); RETURN NEW; END;$$', + schema_function( + 'update_ts', + 'trigger', + language: 'plpgsql', + definition: 'BEGIN NEW.updated_at = now(); RETURN NEW; END;', + volatility: FunctionVolatility::VOLATILE, + )->toSql()->toSql(), + ); + } + + public function test_to_sql_returns_null_when_definition_null() : void + { + self::assertNull( + schema_function('now', 'timestamp with time zone')->toSql(), + ); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/IndexTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/IndexTest.php new file mode 100644 index 0000000000..1a01bd1ab7 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/IndexTest.php @@ -0,0 +1,126 @@ +name); + self::assertSame(['name'], $index->columns); + self::assertFalse($index->unique); + self::assertSame(IndexMethod::BTREE, $index->method); + self::assertFalse($index->primary); + self::assertNull($index->predicate); + } + + public function test_index_with_method() : void + { + $index = schema_index('idx_data_tags', ['tags'], method: IndexMethod::GIN); + + self::assertSame(IndexMethod::GIN, $index->method); + } + + public function test_index_with_predicate() : void + { + $index = schema_index('idx_active_users', ['email'], predicate: 'active = true'); + + self::assertSame('active = true', $index->predicate); + } + + public function test_is_equal_for_identical_indexes() : void + { + $a = schema_index('idx_users_name', ['name'], unique: true, method: IndexMethod::BTREE); + $b = schema_index('idx_users_name', ['name'], unique: true, method: IndexMethod::BTREE); + + self::assertTrue($a->isEqual($b)); + } + + public function test_is_equal_returns_false_when_columns_differ() : void + { + $a = schema_index('idx_users', ['name']); + $b = schema_index('idx_users', ['email']); + + self::assertFalse($a->isEqual($b)); + } + + public function test_is_equal_returns_false_when_method_differs() : void + { + $a = schema_index('idx_users', ['name'], method: IndexMethod::BTREE); + $b = schema_index('idx_users', ['name'], method: IndexMethod::GIN); + + self::assertFalse($a->isEqual($b)); + } + + public function test_is_equal_returns_false_when_name_differs() : void + { + $a = schema_index('idx_a', ['name']); + $b = schema_index('idx_b', ['name']); + + self::assertFalse($a->isEqual($b)); + } + + public function test_is_equal_returns_false_when_predicate_differs() : void + { + $a = schema_index('idx_users', ['name'], predicate: 'active = true'); + $b = schema_index('idx_users', ['name'], predicate: 'active = false'); + + self::assertFalse($a->isEqual($b)); + } + + public function test_is_equal_returns_false_when_unique_differs() : void + { + $a = schema_index('idx_users', ['name'], unique: false); + $b = schema_index('idx_users', ['name'], unique: true); + + self::assertFalse($a->isEqual($b)); + } + + public function test_is_equal_structure_returns_false_when_columns_differ() : void + { + $a = schema_index('idx_users', ['name']); + $b = schema_index('idx_users', ['email']); + + self::assertFalse($a->isEqualStructure($b)); + } + + public function test_is_equal_structure_returns_false_when_method_differs() : void + { + $a = schema_index('idx_users', ['name'], method: IndexMethod::BTREE); + $b = schema_index('idx_users', ['name'], method: IndexMethod::HASH); + + self::assertFalse($a->isEqualStructure($b)); + } + + public function test_is_equal_structure_returns_false_when_primary_differs() : void + { + $a = schema_index('idx_users', ['id'], primary: true); + $b = schema_index('idx_users', ['id'], primary: false); + + self::assertFalse($a->isEqualStructure($b)); + } + + public function test_is_equal_structure_returns_true_when_only_name_differs() : void + { + $a = schema_index('idx_a', ['name', 'email'], unique: true, method: IndexMethod::GIN, predicate: 'active = true'); + $b = schema_index('idx_b', ['name', 'email'], unique: true, method: IndexMethod::GIN, predicate: 'active = true'); + + self::assertTrue($a->isEqualStructure($b)); + } + + public function test_unique_index() : void + { + $index = schema_index('idx_users_email', ['email'], unique: true); + + self::assertTrue($index->unique); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/MaterializedViewDependencyOrderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/MaterializedViewDependencyOrderTest.php new file mode 100644 index 0000000000..fa5c4124dc --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/MaterializedViewDependencyOrderTest.php @@ -0,0 +1,75 @@ +expectException(SchemaException::class); + $this->expectExceptionMessage('Circular dependency detected between materialized views'); + + (new MaterializedViewDependencyOrder(new Parser()))->order([$viewA, $viewB]); + } + + public function test_empty_list() : void + { + self::assertSame([], (new MaterializedViewDependencyOrder(new Parser()))->order([])); + } + + public function test_linear_chain() : void + { + $base = new MaterializedView('base_mv', 'SELECT id, name FROM users'); + $top = new MaterializedView('top_mv', 'SELECT * FROM base_mv'); + + $result = (new MaterializedViewDependencyOrder(new Parser()))->order([$top, $base]); + + $names = \array_map(static fn (MaterializedView $v) => $v->name, $result); + + self::assertSame(['base_mv', 'top_mv'], $names); + } + + public function test_self_referencing_materialized_view() : void + { + $recursive = new MaterializedView('recursive_mv', 'SELECT * FROM recursive_mv'); + $other = new MaterializedView('other_mv', 'SELECT * FROM recursive_mv'); + + $result = (new MaterializedViewDependencyOrder(new Parser()))->order([$other, $recursive]); + + $names = \array_map(static fn (MaterializedView $v) => $v->name, $result); + + self::assertSame(['recursive_mv', 'other_mv'], $names); + } + + public function test_single_materialized_view() : void + { + $view = new MaterializedView('my_mv', 'SELECT * FROM users'); + + $result = (new MaterializedViewDependencyOrder(new Parser()))->order([$view]); + + self::assertCount(1, $result); + self::assertSame('my_mv', $result[0]->name); + } + + public function test_views_without_dependencies_preserve_order() : void + { + $viewA = new MaterializedView('alpha', 'SELECT 1 AS val'); + $viewB = new MaterializedView('beta', 'SELECT 2 AS val'); + + $result = (new MaterializedViewDependencyOrder(new Parser()))->order([$viewA, $viewB]); + + $names = \array_map(static fn (MaterializedView $v) => $v->name, $result); + + self::assertSame(['alpha', 'beta'], $names); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/MaterializedViewTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/MaterializedViewTest.php new file mode 100644 index 0000000000..e98714ea9b --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/MaterializedViewTest.php @@ -0,0 +1,105 @@ +from(table('users'))->toSql(); + $matview = schema_materialized_view('user_stats', $definition); + + self::assertSame('user_stats', $matview->name); + self::assertSame($definition, $matview->definition); + self::assertSame([], $matview->indexes); + } + + public function test_materialized_view_with_indexes() : void + { + $matview = schema_materialized_view( + 'user_stats', + select(col('id'), agg_count())->from(table('users'))->groupBy(col('id'))->toSql(), + indexes: [schema_index('idx_user_stats_id', ['id'], unique: true)], + ); + + self::assertCount(1, $matview->indexes); + self::assertSame('idx_user_stats_id', $matview->indexes[0]->name); + } + + public function test_to_sql_generates_create_materialized_view() : void + { + $sqls = schema_materialized_view( + 'user_stats', + select(col('id'), agg_count())->from(table('users'))->groupBy(col('id'))->toSql(), + )->toSql(); + + self::assertCount(1, $sqls); + self::assertSame( + 'CREATE MATERIALIZED VIEW user_stats AS SELECT id, count(*) FROM users GROUP BY id', + $sqls[0]->toSql(), + ); + } + + public function test_to_sql_generates_create_materialized_view_with_indexes() : void + { + $sqls = schema_materialized_view( + 'user_stats', + select(col('id'), agg_count())->from(table('users'))->groupBy(col('id'))->toSql(), + indexes: [schema_index('idx_user_stats_id', ['id'], unique: true)], + )->toSql(); + + self::assertCount(2, $sqls); + self::assertSame('CREATE MATERIALIZED VIEW user_stats AS SELECT id, count(*) FROM users GROUP BY id', $sqls[0]->toSql()); + self::assertSame('CREATE UNIQUE INDEX idx_user_stats_id ON user_stats (id)', $sqls[1]->toSql()); + } + + public function test_to_sql_generates_materialized_view_with_multiple_indexes() : void + { + $sqls = schema_materialized_view( + 'user_stats', + select(col('id'), agg_count())->from(table('users'))->groupBy(col('id'))->toSql(), + indexes: [ + schema_index('idx_upc_id', ['id'], unique: true), + schema_index('idx_upc_gin', ['metadata'], method: IndexMethod::GIN), + ], + )->toSql(); + + self::assertCount(3, $sqls); + self::assertSame('CREATE MATERIALIZED VIEW user_stats AS SELECT id, count(*) FROM users GROUP BY id', $sqls[0]->toSql()); + self::assertSame('CREATE UNIQUE INDEX idx_upc_id ON user_stats (id)', $sqls[1]->toSql()); + self::assertSame('CREATE INDEX idx_upc_gin ON user_stats USING gin (metadata)', $sqls[2]->toSql()); + } + + public function test_to_sql_generates_materialized_view_with_non_btree_index() : void + { + $sqls = schema_materialized_view( + 'user_stats', + select(col('id'), agg_count())->from(table('users'))->groupBy(col('id'))->toSql(), + indexes: [schema_index('idx_user_stats_gin', ['metadata'], method: IndexMethod::GIN)], + )->toSql(); + + self::assertCount(2, $sqls); + self::assertSame('CREATE MATERIALIZED VIEW user_stats AS SELECT id, count(*) FROM users GROUP BY id', $sqls[0]->toSql()); + self::assertSame('CREATE INDEX idx_user_stats_gin ON user_stats USING gin (metadata)', $sqls[1]->toSql()); + } + + public function test_to_sql_generates_materialized_view_with_unique_non_btree_index() : void + { + $sqls = schema_materialized_view( + 'user_stats', + select(col('id'), agg_count())->from(table('users'))->groupBy(col('id'))->toSql(), + indexes: [schema_index('idx_user_stats_hash', ['id'], unique: true, method: IndexMethod::HASH)], + )->toSql(); + + self::assertCount(2, $sqls); + self::assertSame('CREATE MATERIALIZED VIEW user_stats AS SELECT id, count(*) FROM users GROUP BY id', $sqls[0]->toSql()); + self::assertSame('CREATE UNIQUE INDEX idx_user_stats_hash ON user_stats USING hash (id)', $sqls[1]->toSql()); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/NoExecutionOrderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/NoExecutionOrderTest.php new file mode 100644 index 0000000000..5a0cc2206e --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/NoExecutionOrderTest.php @@ -0,0 +1,41 @@ +order([$tableC, $tableA, $tableB]); + + self::assertSame([$tableC, $tableA, $tableB], $result); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/ProcedureTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/ProcedureTest.php new file mode 100644 index 0000000000..52dad9a3b1 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/ProcedureTest.php @@ -0,0 +1,56 @@ +name); + self::assertSame([], $proc->argumentTypes); + self::assertSame('sql', $proc->language); + self::assertNull($proc->definition); + } + + public function test_procedure_with_arguments() : void + { + $proc = schema_procedure( + 'archive_user', + argumentTypes: ['integer', 'text'], + language: 'plpgsql', + definition: 'BEGIN DELETE FROM users WHERE id = $1; END;', + ); + + self::assertSame(['integer', 'text'], $proc->argumentTypes); + self::assertSame('plpgsql', $proc->language); + self::assertSame('BEGIN DELETE FROM users WHERE id = $1; END;', $proc->definition); + } + + public function test_to_sql_generates_create_procedure() : void + { + self::assertSame( + 'CREATE OR REPLACE PROCEDURE archive_user(IN int, IN text) LANGUAGE plpgsql AS $$BEGIN DELETE FROM users WHERE id = $1; END;$$', + schema_procedure( + 'archive_user', + argumentTypes: ['integer', 'text'], + language: 'plpgsql', + definition: 'BEGIN DELETE FROM users WHERE id = $1; END;', + )->toSql()->toSql(), + ); + } + + public function test_to_sql_returns_null_when_definition_null() : void + { + self::assertNull( + schema_procedure('cleanup_old_records')->toSql(), + ); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/SchemaTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/SchemaTest.php new file mode 100644 index 0000000000..00f8c3b36c --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/SchemaTest.php @@ -0,0 +1,649 @@ +from(table('users', 'app'))->where(eq(col('active'), literal(true)))->toSql()), + ], + materializedViews: [ + schema_materialized_view( + 'user_post_counts', + select(col('user_id'), agg_count()->as('post_count'))->from(table('posts', 'app'))->groupBy(col('user_id'))->toSql(), + indexes: [schema_index('idx_upc_user_id', ['user_id'], unique: true)], + ), + ], + functions: [ + schema_function( + 'update_timestamp', + 'trigger', + language: 'plpgsql', + definition: 'BEGIN NEW.updated_at = now(); RETURN NEW; END;', + volatility: FunctionVolatility::VOLATILE, + ), + ], + procedures: [ + schema_procedure( + 'cleanup_old_posts', + argumentTypes: ['integer'], + language: 'plpgsql', + definition: 'BEGIN DELETE FROM app.posts WHERE published_at < now() - make_interval(days => $1); END;', + ), + ], + domains: [ + schema_domain( + 'positive_int', + column_type_integer(), + nullable: false, + checkConstraints: [schema_check('VALUE > 0', 'chk_positive')], + ), + ], + extensions: [ + schema_extension('pgcrypto', '1.3'), + ], + ); + + self::assertSame('app', $schema->name); + self::assertCount(3, $schema->tables); + self::assertCount(1, $schema->sequences); + self::assertCount(1, $schema->views); + self::assertCount(1, $schema->materializedViews); + self::assertCount(1, $schema->functions); + self::assertCount(1, $schema->procedures); + self::assertCount(1, $schema->domains); + self::assertCount(1, $schema->extensions); + + $usersTable = $schema->table('users'); + self::assertCount(7, $usersTable->columns); + self::assertNotNull($usersTable->primaryKey); + self::assertCount(3, $usersTable->indexes); + self::assertCount(1, $usersTable->uniqueConstraints); + self::assertCount(1, $usersTable->checkConstraints); + + $postsTable = $schema->table('posts'); + self::assertCount(1, $postsTable->foreignKeys); + self::assertSame(ReferentialAction::CASCADE, $postsTable->foreignKeys[0]->onDelete); + self::assertCount(1, $postsTable->triggers); + self::assertTrue($postsTable->triggers[0]->forEachRow); + + $auditTable = $schema->table('audit_log'); + self::assertCount(1, $auditTable->excludeConstraints); + } + + public function test_has_table() : void + { + $schema = schema('public', tables: [ + schema_table('users', [schema_column_integer('id', nullable: false)]), + ]); + + self::assertTrue($schema->hasTable('users')); + self::assertFalse($schema->hasTable('missing')); + } + + public function test_merge_empty_schemas() : void + { + $result = schema('public')->merge(schema('public')); + + self::assertSame('public', $result->name); + self::assertSame([], $result->tables); + self::assertSame([], $result->sequences); + self::assertSame([], $result->views); + self::assertSame([], $result->materializedViews); + self::assertSame([], $result->functions); + self::assertSame([], $result->procedures); + self::assertSame([], $result->domains); + self::assertSame([], $result->extensions); + } + + public function test_merge_schemas_preserves_all_entity_types() : void + { + $first = schema( + 'public', + tables: [schema_table('users', [schema_column_integer('id', nullable: false)])], + sequences: [schema_sequence('seq_a')], + extensions: [schema_extension('pgcrypto')], + ); + $second = schema( + 'public', + views: [schema_view('active_users', select(star())->from(table('users'))->toSql())], + sequences: [schema_sequence('seq_b')], + ); + + $result = $first->merge($second); + + self::assertCount(1, $result->tables); + self::assertCount(2, $result->sequences); + self::assertCount(1, $result->views); + self::assertCount(1, $result->extensions); + } + + public function test_merge_schemas_same_sequence_later_overrides() : void + { + $first = schema('public', sequences: [ + schema_sequence('my_seq', dataType: 'integer', startValue: 1), + ]); + $second = schema('public', sequences: [ + schema_sequence('my_seq', dataType: 'bigint', startValue: 100), + ]); + + $result = $first->merge($second); + + self::assertCount(1, $result->sequences); + self::assertSame('bigint', $result->sequence('my_seq')->dataType); + self::assertSame(100, $result->sequence('my_seq')->startValue); + } + + public function test_merge_schemas_same_table_later_overrides() : void + { + $first = schema('public', tables: [ + schema_table('users', [schema_column_integer('id', nullable: false)]), + ]); + $second = schema('public', tables: [ + schema_table('users', [ + schema_column_integer('id', nullable: false), + schema_column_text('name'), + ]), + ]); + + $result = $first->merge($second); + + self::assertCount(2, $result->table('users')->columns); + self::assertSame('name', $result->table('users')->columns[1]->name); + } + + public function test_merge_schemas_with_different_tables() : void + { + $first = schema('public', tables: [ + schema_table('users', [schema_column_integer('id', nullable: false)]), + ]); + $second = schema('public', tables: [ + schema_table('posts', [schema_column_integer('id', nullable: false)]), + ]); + + $result = $first->merge($second); + + self::assertSame('public', $result->name); + self::assertTrue($result->hasTable('users')); + self::assertTrue($result->hasTable('posts')); + } + + public function test_schema_column_type_shortcuts_all_types() : void + { + $table = schema_table('all_types', [ + schema_column_integer('col_integer'), + schema_column_smallint('col_smallint'), + schema_column_bigint('col_bigint'), + schema_column_serial('col_serial'), + schema_column_small_serial('col_smallserial'), + schema_column_big_serial('col_bigserial'), + schema_column_boolean('col_boolean'), + schema_column_text('col_text'), + schema_column_varchar('col_varchar', 100), + schema_column_char('col_char', 5), + schema_column_numeric('col_numeric', 10, 2), + schema_column_real('col_real'), + schema_column_double_precision('col_double'), + schema_column_date('col_date'), + schema_column_time('col_time', 3), + schema_column_timestamp('col_timestamp'), + schema_column_timestamp_tz('col_timestamptz', 6), + schema_column_interval('col_interval'), + schema_column_uuid('col_uuid'), + schema_column_json('col_json'), + schema_column_jsonb('col_jsonb'), + schema_column_bytea('col_bytea'), + schema_column_inet('col_inet'), + schema_column_cidr('col_cidr'), + schema_column_macaddr('col_macaddr'), + schema_column('col_array', column_type_array(column_type_integer())), + schema_column('col_custom', column_type_custom('hstore')), + ]); + + self::assertCount(27, $table->columns); + self::assertFalse($table->column('col_serial')->nullable); + self::assertFalse($table->column('col_smallserial')->nullable); + self::assertFalse($table->column('col_bigserial')->nullable); + self::assertTrue($table->column('col_text')->nullable); + } + + public function test_schema_construction() : void + { + $schema = schema('public', tables: [ + schema_table('users', [schema_column_integer('id', nullable: false)]), + ]); + + self::assertSame('public', $schema->name); + self::assertCount(1, $schema->tables); + } + + public function test_schema_empty() : void + { + $s = schema('public'); + + self::assertSame([], $s->tables); + self::assertSame([], $s->sequences); + self::assertSame([], $s->views); + self::assertSame([], $s->materializedViews); + self::assertSame([], $s->functions); + self::assertSame([], $s->procedures); + self::assertSame([], $s->domains); + self::assertSame([], $s->extensions); + } + + public function test_schema_with_domains() : void + { + $s = schema('public', domains: [ + schema_domain('email', column_type_custom('text'), checkConstraints: [ + schema_check("VALUE ~* '^.+@.+$'"), + ]), + ]); + + self::assertCount(1, $s->domains); + self::assertCount(1, $s->domains[0]->checkConstraints); + } + + public function test_schema_with_extensions() : void + { + $s = schema('public', extensions: [ + schema_extension('uuid-ossp', '1.1'), + ]); + + self::assertCount(1, $s->extensions); + self::assertSame('uuid-ossp', $s->extensions[0]->name); + self::assertSame('1.1', $s->extensions[0]->version); + } + + public function test_schema_with_functions() : void + { + $s = schema('public', functions: [ + schema_function('add', 'integer', argumentTypes: ['integer', 'integer'], isStrict: true, volatility: FunctionVolatility::IMMUTABLE), + ]); + + self::assertCount(1, $s->functions); + self::assertTrue($s->functions[0]->isStrict); + self::assertSame(FunctionVolatility::IMMUTABLE, $s->functions[0]->volatility); + } + + public function test_schema_with_materialized_views() : void + { + $s = schema('public', materializedViews: [ + schema_materialized_view( + 'stats', + select(agg_count())->from(table('users'))->toSql(), + indexes: [schema_index('idx_stats', ['count'])], + ), + ]); + + self::assertCount(1, $s->materializedViews); + self::assertCount(1, $s->materializedViews[0]->indexes); + } + + public function test_schema_with_procedures() : void + { + $s = schema('public', procedures: [ + schema_procedure('cleanup', argumentTypes: ['integer'], language: 'plpgsql'), + ]); + + self::assertCount(1, $s->procedures); + self::assertSame('plpgsql', $s->procedures[0]->language); + } + + public function test_schema_with_sequences() : void + { + $s = schema('public', sequences: [ + schema_sequence('users_id_seq'), + ]); + + self::assertTrue($s->hasSequence('users_id_seq')); + self::assertFalse($s->hasSequence('missing')); + self::assertSame('users_id_seq', $s->sequence('users_id_seq')->name); + } + + public function test_schema_with_views() : void + { + $s = schema('public', views: [ + schema_view('active_users', select(star())->from(table('users'))->where(eq(col('active'), literal(true)))->toSql(), isUpdatable: true), + ]); + + self::assertCount(1, $s->views); + self::assertTrue($s->views[0]->isUpdatable); + } + + public function test_sequence_not_found_throws() : void + { + $this->expectException(SchemaException::class); + schema('public')->sequence('missing'); + } + + public function test_table_lookup() : void + { + $s = schema('public', tables: [ + schema_table('users', [schema_column_integer('id', nullable: false)]), + ]); + + self::assertSame('users', $s->table('users')->name); + } + + public function test_table_names() : void + { + $s = schema('public', tables: [ + schema_table('users', [schema_column_integer('id', nullable: false)]), + schema_table('posts', [schema_column_integer('id', nullable: false)]), + ]); + + self::assertSame(['users', 'posts'], $s->tableNames()); + } + + public function test_table_not_found_throws() : void + { + $this->expectException(TableNotFoundException::class); + schema('public')->table('missing'); + } + + public function test_table_with_all_constraint_types() : void + { + $table = schema_table( + 'orders', + [ + schema_column_serial('id'), + schema_column_integer('user_id', nullable: false), + schema_column_numeric('amount', 10, 2, nullable: false), + schema_column_varchar('status', 50, default: "'pending'"), + ], + primaryKey: schema_primary_key(['id'], 'orders_pkey'), + foreignKeys: [ + schema_foreign_key( + ['user_id'], + 'users', + ['id'], + name: 'fk_orders_user', + onDelete: ReferentialAction::CASCADE, + deferrable: true, + initiallyDeferred: true, + ), + ], + uniqueConstraints: [schema_unique(['user_id', 'status'], 'uq_user_status', nullsNotDistinct: true)], + checkConstraints: [schema_check('amount > 0', 'chk_positive_amount', noInherit: true)], + excludeConstraints: [schema_exclude('USING gist (tsrange WITH &&)')], + ); + + self::assertNotNull($table->primaryKey); + self::assertSame('orders_pkey', $table->primaryKey->name); + self::assertCount(1, $table->foreignKeys); + self::assertTrue($table->foreignKeys[0]->deferrable); + self::assertTrue($table->foreignKeys[0]->initiallyDeferred); + self::assertCount(1, $table->uniqueConstraints); + self::assertTrue($table->uniqueConstraints[0]->nullsNotDistinct); + self::assertCount(1, $table->checkConstraints); + self::assertTrue($table->checkConstraints[0]->noInherit); + self::assertCount(1, $table->excludeConstraints); + } + + public function test_table_with_multiple_triggers_and_events() : void + { + $table = schema_table( + 'orders', + [schema_column_serial('id')], + triggers: [ + schema_trigger('trg_before_insert', 'orders', TriggerTiming::BEFORE, [TriggerEvent::INSERT], 'validate_fn', forEachRow: true), + schema_trigger('trg_after_changes', 'orders', TriggerTiming::AFTER, [TriggerEvent::INSERT, TriggerEvent::UPDATE, TriggerEvent::DELETE], 'audit_fn', whenCondition: 'NEW.amount > 100'), + schema_trigger('trg_truncate', 'orders', TriggerTiming::AFTER, [TriggerEvent::TRUNCATE], 'cleanup_fn'), + ], + ); + + self::assertCount(3, $table->triggers); + self::assertSame(TriggerTiming::BEFORE, $table->triggers[0]->timing); + self::assertCount(3, $table->triggers[1]->events); + self::assertSame('NEW.amount > 100', $table->triggers[1]->whenCondition); + self::assertFalse($table->triggers[2]->forEachRow); + } + + public function test_to_sql_includes_all_object_types() : void + { + $sqls = schema( + 'public', + tables: [ + schema_table('users', [schema_column_integer('id', nullable: false)]), + ], + sequences: [ + schema_sequence('users_id_seq'), + ], + views: [ + schema_view('active_users', select(star())->from(table('users'))->toSql()), + ], + materializedViews: [ + schema_materialized_view( + 'user_counts', + select(agg_count())->from(table('users'))->toSql(), + ), + ], + functions: [ + schema_function( + 'get_one', + 'integer', + language: 'sql', + definition: 'SELECT 1', + ), + ], + procedures: [ + schema_procedure( + 'do_cleanup', + language: 'plpgsql', + definition: 'BEGIN END;', + ), + ], + domains: [ + schema_domain('positive_int', column_type_integer(), nullable: false), + ], + extensions: [ + schema_extension('pgcrypto'), + ], + )->toSql(); + + self::assertSame('CREATE EXTENSION pgcrypto', $sqls[0]->toSql()); + self::assertSame('CREATE DOMAIN positive_int AS int NOT NULL', $sqls[1]->toSql()); + self::assertSame('CREATE SEQUENCE users_id_seq AS bigint START 1 INCREMENT 1 MINVALUE 1 CACHE 1 NO MAXVALUE', $sqls[2]->toSql()); + self::assertSame('CREATE OR REPLACE FUNCTION get_one() RETURNS int LANGUAGE sql AS $$SELECT 1$$', $sqls[3]->toSql()); + self::assertSame('CREATE OR REPLACE PROCEDURE do_cleanup() LANGUAGE plpgsql AS $$BEGIN END;$$', $sqls[4]->toSql()); + self::assertSame('CREATE TABLE public.users (id int NOT NULL)', $sqls[5]->toSql()); + self::assertSame('CREATE VIEW active_users AS SELECT * FROM users', $sqls[6]->toSql()); + self::assertSame('CREATE MATERIALIZED VIEW user_counts AS SELECT count(*) FROM users', $sqls[7]->toSql()); + self::assertCount(8, $sqls); + } + + public function test_to_sql_includes_materialized_view_with_indexes() : void + { + $sqls = schema( + 'public', + materializedViews: [ + schema_materialized_view( + 'user_counts', + select(col('id'), agg_count())->from(table('users'))->groupBy(col('id'))->toSql(), + indexes: [schema_index('idx_uc_id', ['id'], unique: true)], + ), + ], + )->toSql(); + + self::assertSame('CREATE MATERIALIZED VIEW user_counts AS SELECT id, count(*) FROM users GROUP BY id', $sqls[0]->toSql()); + self::assertSame('CREATE UNIQUE INDEX idx_uc_id ON user_counts (id)', $sqls[1]->toSql()); + self::assertCount(2, $sqls); + } + + public function test_to_sql_mixes_functions_with_and_without_definitions() : void + { + $sqls = schema( + 'public', + functions: [ + schema_function('builtin_fn', 'integer'), + schema_function('my_fn', 'integer', language: 'sql', definition: 'SELECT 42'), + schema_function('another_builtin', 'text'), + ], + )->toSql(); + + self::assertCount(1, $sqls); + self::assertSame('CREATE OR REPLACE FUNCTION my_fn() RETURNS int LANGUAGE sql AS $$SELECT 42$$', $sqls[0]->toSql()); + } + + public function test_to_sql_skips_function_with_null_definition() : void + { + $sqls = schema( + 'public', + functions: [ + schema_function('builtin_fn', 'integer'), + ], + )->toSql(); + + self::assertSame([], $sqls); + } + + public function test_to_sql_skips_procedure_with_null_definition() : void + { + $sqls = schema( + 'public', + procedures: [ + schema_procedure('builtin_proc'), + ], + )->toSql(); + + self::assertSame([], $sqls); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/SequenceTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/SequenceTest.php new file mode 100644 index 0000000000..d95d4ed745 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/SequenceTest.php @@ -0,0 +1,57 @@ +name); + self::assertSame('bigint', $seq->dataType); + self::assertSame(1, $seq->startValue); + } + + public function test_sequence_owned_by() : void + { + $seq = schema_sequence('users_id_seq', ownedByTable: 'users', ownedByColumn: 'id'); + + self::assertSame('users', $seq->ownedByTable); + self::assertSame('id', $seq->ownedByColumn); + } + + public function test_sequence_with_all_options() : void + { + $seq = schema_sequence('custom_seq', dataType: 'integer', startValue: 100, minValue: 1, maxValue: 10000, incrementBy: 5, cycle: true, cacheValue: 10); + + self::assertSame('integer', $seq->dataType); + self::assertSame(100, $seq->startValue); + self::assertSame(10000, $seq->maxValue); + self::assertSame(5, $seq->incrementBy); + self::assertTrue($seq->cycle); + self::assertSame(10, $seq->cacheValue); + } + + public function test_to_sql_generates_create_sequence() : void + { + self::assertSame( + 'CREATE SEQUENCE users_id_seq AS bigint START 1 INCREMENT 1 MINVALUE 1 CACHE 1 NO MAXVALUE', + schema_sequence('users_id_seq')->toSql()->toSql(), + ); + } + + public function test_to_sql_generates_create_sequence_with_all_options() : void + { + self::assertSame( + 'CREATE SEQUENCE custom_seq AS int START 100 INCREMENT 5 MINVALUE 1 CACHE 10 MAXVALUE 10000 CYCLE OWNED BY users.id', + schema_sequence('custom_seq', dataType: 'integer', startValue: 100, minValue: 1, maxValue: 10000, incrementBy: 5, cycle: true, cacheValue: 10, ownedByTable: 'users', ownedByColumn: 'id')->toSql()->toSql(), + ); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/TableTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/TableTest.php new file mode 100644 index 0000000000..24e4432539 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/TableTest.php @@ -0,0 +1,809 @@ +column('name')->name); + } + + public function test_column_names() : void + { + $table = schema_table('users', [ + schema_column('id', column_type_integer(), nullable: false), + schema_column('name', column_type_varchar(255)), + ]); + + self::assertSame(['id', 'name'], $table->columnNames()); + } + + public function test_column_not_found_throws() : void + { + $table = schema_table('users', [ + schema_column('id', column_type_integer(), nullable: false), + ]); + + $this->expectException(ColumnNotFoundException::class); + $table->column('missing'); + } + + public function test_has_column() : void + { + $table = schema_table('users', [ + schema_column('id', column_type_integer(), nullable: false), + ]); + + self::assertTrue($table->hasColumn('id')); + self::assertFalse($table->hasColumn('missing')); + } + + public function test_qualified_name() : void + { + $table = schema_table('users', [ + schema_column('id', column_type_integer(), nullable: false), + ]); + + self::assertSame('public.users', $table->qualifiedName()); + } + + public function test_table_construction() : void + { + $table = schema_table('users', [ + schema_column('id', column_type_integer(), nullable: false), + schema_column('name', column_type_varchar(255)), + ]); + + self::assertSame('public', $table->schema); + self::assertSame('users', $table->name); + self::assertCount(2, $table->columns); + } + + public function test_table_with_foreign_keys() : void + { + $table = schema_table('posts', [ + schema_column('id', column_type_integer(), nullable: false), + schema_column('user_id', column_type_integer(), nullable: false), + ], foreignKeys: [ + schema_foreign_key(['user_id'], 'users', ['id']), + ]); + + self::assertCount(1, $table->foreignKeys); + self::assertSame('users', $table->foreignKeys[0]->referenceTable); + } + + public function test_table_with_indexes() : void + { + $table = schema_table('users', [ + schema_column('id', column_type_integer(), nullable: false), + schema_column('email', column_type_varchar(255)), + ], indexes: [ + schema_index('idx_users_email', ['email'], unique: true), + ]); + + self::assertCount(1, $table->indexes); + self::assertSame('idx_users_email', $table->indexes[0]->name); + self::assertTrue($table->indexes[0]->unique); + } + + public function test_table_with_primary_key() : void + { + $table = schema_table('users', [ + schema_column('id', column_type_integer(), nullable: false), + ], primaryKey: schema_primary_key(['id'])); + + self::assertNotNull($table->primaryKey); + self::assertSame(['id'], $table->primaryKey->columns); + } + + public function test_table_with_triggers() : void + { + $table = schema_table('users', [ + schema_column('id', column_type_integer(), nullable: false), + schema_column('updated_at', column_type_timestamptz()), + ], triggers: [ + schema_trigger('trg_update_timestamp', 'users', TriggerTiming::BEFORE, [TriggerEvent::UPDATE], 'update_timestamp', forEachRow: true), + ]); + + self::assertCount(1, $table->triggers); + self::assertSame('trg_update_timestamp', $table->triggers[0]->name); + } + + public function test_to_sql_generates_create_table() : void + { + $sqls = schema_table('users', [ + schema_column('id', column_type_integer(), nullable: false), + schema_column('name', column_type_varchar(255)), + ])->toSql(); + + self::assertCount(1, $sqls); + self::assertSame( + 'CREATE TABLE public.users (id int NOT NULL, name varchar(255))', + $sqls[0]->toSql(), + ); + } + + public function test_to_sql_generates_create_table_with_indexes() : void + { + $sqls = schema_table('users', [ + schema_column('id', column_type_integer(), nullable: false), + schema_column('email', column_type_varchar(255)), + ], indexes: [ + schema_index('idx_users_email', ['email'], unique: true), + ])->toSql(); + + self::assertCount(2, $sqls); + self::assertSame('CREATE TABLE public.users (id int NOT NULL, email varchar(255))', $sqls[0]->toSql()); + self::assertSame('CREATE UNIQUE INDEX idx_users_email ON public.users (email)', $sqls[1]->toSql()); + } + + public function test_to_sql_generates_create_table_with_primary_key() : void + { + $sqls = schema_table('users', [ + schema_column('id', column_type_integer(), nullable: false), + ], primaryKey: schema_primary_key(['id']))->toSql(); + + self::assertCount(1, $sqls); + self::assertSame( + 'CREATE TABLE public.users (id int NOT NULL, PRIMARY KEY (id))', + $sqls[0]->toSql(), + ); + } + + public function test_to_sql_generates_inherits() : void + { + $sqls = schema_table('employees', [ + schema_column('id', column_type_integer(), nullable: false), + schema_column('name', column_type_varchar(255)), + ], inherits: ['persons'])->toSql(); + + self::assertCount(1, $sqls); + self::assertSame( + 'CREATE TABLE public.employees (id int NOT NULL, name varchar(255)) INHERITS (persons)', + $sqls[0]->toSql(), + ); + } + + public function test_to_sql_generates_partition_by_hash() : void + { + $sqls = schema_table('events', [ + schema_column('id', column_type_integer(), nullable: false), + ], partitionStrategy: PartitionStrategy::HASH, partitionColumns: ['id'])->toSql(); + + self::assertCount(1, $sqls); + self::assertSame( + 'CREATE TABLE public.events (id int NOT NULL) PARTITION BY HASH (id)', + $sqls[0]->toSql(), + ); + } + + public function test_to_sql_generates_partition_by_list() : void + { + $sqls = schema_table('events', [ + schema_column('id', column_type_integer(), nullable: false), + schema_column('region', column_type_varchar(50), nullable: false), + ], partitionStrategy: PartitionStrategy::LIST, partitionColumns: ['region'])->toSql(); + + self::assertCount(1, $sqls); + self::assertSame( + 'CREATE TABLE public.events (id int NOT NULL, region varchar(50) NOT NULL) PARTITION BY LIST (region)', + $sqls[0]->toSql(), + ); + } + + public function test_to_sql_generates_partition_by_range() : void + { + $sqls = schema_table('events', [ + schema_column('id', column_type_integer(), nullable: false), + schema_column('name', column_type_varchar(255), nullable: false), + ], partitionStrategy: PartitionStrategy::RANGE, partitionColumns: ['name'])->toSql(); + + self::assertCount(1, $sqls); + self::assertSame( + 'CREATE TABLE public.events (id int NOT NULL, name varchar(255) NOT NULL) PARTITION BY RANGE (name)', + $sqls[0]->toSql(), + ); + } + + public function test_to_sql_generates_partition_with_tablespace() : void + { + $sqls = schema_table('events', [ + schema_column('id', column_type_integer(), nullable: false), + schema_column('name', column_type_varchar(255), nullable: false), + ], partitionStrategy: PartitionStrategy::RANGE, partitionColumns: ['name'], tablespace: 'fast_storage')->toSql(); + + self::assertCount(1, $sqls); + self::assertSame( + 'CREATE TABLE public.events (id int NOT NULL, name varchar(255) NOT NULL) PARTITION BY RANGE (name) TABLESPACE fast_storage', + $sqls[0]->toSql(), + ); + } + + public function test_to_sql_generates_tablespace() : void + { + $sqls = schema_table('events', [ + schema_column('id', column_type_integer(), nullable: false), + ], tablespace: 'fast_storage')->toSql(); + + self::assertCount(1, $sqls); + self::assertSame( + 'CREATE TABLE public.events (id int NOT NULL) TABLESPACE fast_storage', + $sqls[0]->toSql(), + ); + } + + public function test_to_sql_generates_unlogged_table() : void + { + $sqls = schema_table('events', [ + schema_column('id', column_type_integer(), nullable: false), + schema_column('name', column_type_varchar(255)), + ], unlogged: true)->toSql(); + + self::assertCount(1, $sqls); + self::assertSame( + 'CREATE UNLOGGED TABLE public.events (id int NOT NULL, name varchar(255))', + $sqls[0]->toSql(), + ); + } + + public function test_to_sql_with_all_constraint_types() : void + { + $sqls = schema_table( + 'orders', + [ + schema_column('id', column_type_integer(), nullable: false), + schema_column('user_id', column_type_integer(), nullable: false), + schema_column('amount', column_type_integer(), nullable: false), + schema_column('email', column_type_varchar(255), nullable: false), + ], + primaryKey: schema_primary_key(['id']), + indexes: [ + schema_index('idx_orders_user_id', ['user_id']), + ], + foreignKeys: [ + schema_foreign_key(['user_id'], 'users', ['id'], onDelete: ReferentialAction::CASCADE), + ], + uniqueConstraints: [ + schema_unique(['email']), + ], + checkConstraints: [ + schema_check('amount > 0'), + ], + triggers: [ + schema_trigger('trg_audit', 'orders', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'audit_function'), + ], + )->toSql(); + + self::assertCount(3, $sqls); + self::assertSame( + 'CREATE TABLE public.orders (id int NOT NULL, user_id int NOT NULL, amount int NOT NULL, email varchar(255) NOT NULL, PRIMARY KEY (id), UNIQUE (email), CHECK (amount > 0), FOREIGN KEY (user_id) REFERENCES public.users (id) ON DELETE CASCADE)', + $sqls[0]->toSql(), + ); + self::assertSame( + 'CREATE INDEX idx_orders_user_id ON public.orders (user_id)', + $sqls[1]->toSql(), + ); + self::assertSame( + 'CREATE TRIGGER trg_audit AFTER INSERT ON public.orders EXECUTE FUNCTION audit_function()', + $sqls[2]->toSql(), + ); + } + + public function test_to_sql_with_check_constraint() : void + { + $sqls = schema_table('products', [ + schema_column('id', column_type_integer(), nullable: false), + schema_column('price', column_type_integer(), nullable: false), + ], checkConstraints: [ + schema_check('price > 0'), + ])->toSql(); + + self::assertCount(1, $sqls); + self::assertSame( + 'CREATE TABLE public.products (id int NOT NULL, price int NOT NULL, CHECK (price > 0))', + $sqls[0]->toSql(), + ); + } + + public function test_to_sql_with_check_constraint_no_inherit() : void + { + $sqls = schema_table('products', [ + schema_column('id', column_type_integer(), nullable: false), + schema_column('price', column_type_integer(), nullable: false), + ], checkConstraints: [ + schema_check('price > 0', noInherit: true), + ])->toSql(); + + self::assertCount(1, $sqls); + self::assertSame( + 'CREATE TABLE public.products (id int NOT NULL, price int NOT NULL, CHECK (price > 0) NO INHERIT)', + $sqls[0]->toSql(), + ); + } + + public function test_to_sql_with_column_default() : void + { + $sqls = schema_table('users', [ + schema_column('id', column_type_integer(), nullable: false), + schema_column('status', column_type_varchar(50), default: "'active'"), + ])->toSql(); + + self::assertCount(1, $sqls); + self::assertSame( + "CREATE TABLE public.users (id int NOT NULL, status varchar(50) DEFAULT 'active')", + $sqls[0]->toSql(), + ); + } + + public function test_to_sql_with_column_default_numeric() : void + { + $sqls = schema_table('products', [ + schema_column('id', column_type_integer(), nullable: false), + schema_column('quantity', column_type_integer(), default: '0'), + ])->toSql(); + + self::assertCount(1, $sqls); + self::assertSame( + 'CREATE TABLE public.products (id int NOT NULL, quantity int DEFAULT 0)', + $sqls[0]->toSql(), + ); + } + + public function test_to_sql_with_column_generated_expression() : void + { + $sqls = schema_table('users', [ + schema_column('first_name', column_type_varchar(100)), + schema_column('last_name', column_type_varchar(100)), + schema_column('full_name', column_type_text(), isGenerated: true, generationExpression: "first_name || ' ' || last_name"), + ])->toSql(); + + self::assertCount(1, $sqls); + self::assertSame( + "CREATE TABLE public.users (first_name varchar(100), last_name varchar(100), full_name pg_catalog.text GENERATED ALWAYS AS ((first_name || ' ') || last_name) STORED)", + $sqls[0]->toSql(), + ); + } + + public function test_to_sql_with_column_identity_always() : void + { + $sqls = schema_table('users', [ + schema_column('id', column_type_integer(), nullable: false, isIdentity: true, identityGeneration: IdentityGeneration::ALWAYS), + schema_column('name', column_type_varchar(255)), + ])->toSql(); + + self::assertCount(1, $sqls); + self::assertSame( + 'CREATE TABLE public.users (id int NOT NULL GENERATED ALWAYS AS IDENTITY, name varchar(255))', + $sqls[0]->toSql(), + ); + } + + public function test_to_sql_with_composite_unique_constraint() : void + { + $sqls = schema_table('user_roles', [ + schema_column('user_id', column_type_integer(), nullable: false), + schema_column('role_id', column_type_integer(), nullable: false), + ], uniqueConstraints: [ + schema_unique(['user_id', 'role_id'], name: 'uq_user_role'), + ])->toSql(); + + self::assertCount(1, $sqls); + self::assertSame( + 'CREATE TABLE public.user_roles (user_id int NOT NULL, role_id int NOT NULL, CONSTRAINT uq_user_role UNIQUE (user_id, role_id))', + $sqls[0]->toSql(), + ); + } + + public function test_to_sql_with_custom_schema() : void + { + $sqls = schema_table('users', [ + schema_column('id', column_type_integer(), nullable: false), + ], schema: 'myschema')->toSql(); + + self::assertCount(1, $sqls); + self::assertSame( + 'CREATE TABLE myschema.users (id int NOT NULL)', + $sqls[0]->toSql(), + ); + } + + public function test_to_sql_with_deferrable_foreign_key() : void + { + $sqls = schema_table('orders', [ + schema_column('id', column_type_integer(), nullable: false), + schema_column('user_id', column_type_integer(), nullable: false), + ], foreignKeys: [ + schema_foreign_key( + ['user_id'], + 'users', + ['id'], + deferrable: true, + initiallyDeferred: true, + ), + ])->toSql(); + + self::assertCount(1, $sqls); + self::assertSame( + 'CREATE TABLE public.orders (id int NOT NULL, user_id int NOT NULL, FOREIGN KEY (user_id) REFERENCES public.users (id) DEFERRABLE INITIALLY DEFERRED)', + $sqls[0]->toSql(), + ); + } + + public function test_to_sql_with_foreign_key_constraint() : void + { + $sqls = schema_table('orders', [ + schema_column('id', column_type_integer(), nullable: false), + schema_column('user_id', column_type_integer(), nullable: false), + ], foreignKeys: [ + schema_foreign_key( + ['user_id'], + 'users', + ['id'], + onDelete: ReferentialAction::CASCADE, + onUpdate: ReferentialAction::RESTRICT, + ), + ])->toSql(); + + self::assertCount(1, $sqls); + self::assertSame( + 'CREATE TABLE public.orders (id int NOT NULL, user_id int NOT NULL, FOREIGN KEY (user_id) REFERENCES public.users (id) ON UPDATE RESTRICT ON DELETE CASCADE)', + $sqls[0]->toSql(), + ); + } + + public function test_to_sql_with_foreign_key_custom_reference_schema() : void + { + $sqls = schema_table('orders', [ + schema_column('id', column_type_integer(), nullable: false), + schema_column('product_id', column_type_integer(), nullable: false), + ], foreignKeys: [ + schema_foreign_key( + ['product_id'], + 'products', + ['id'], + referenceSchema: 'catalog', + ), + ])->toSql(); + + self::assertCount(1, $sqls); + self::assertSame( + 'CREATE TABLE public.orders (id int NOT NULL, product_id int NOT NULL, FOREIGN KEY (product_id) REFERENCES catalog.products (id))', + $sqls[0]->toSql(), + ); + } + + public function test_to_sql_with_foreign_key_default_actions() : void + { + $sqls = schema_table('orders', [ + schema_column('id', column_type_integer(), nullable: false), + schema_column('user_id', column_type_integer(), nullable: false), + ], foreignKeys: [ + schema_foreign_key(['user_id'], 'users', ['id']), + ])->toSql(); + + self::assertCount(1, $sqls); + self::assertSame( + 'CREATE TABLE public.orders (id int NOT NULL, user_id int NOT NULL, FOREIGN KEY (user_id) REFERENCES public.users (id))', + $sqls[0]->toSql(), + ); + } + + public function test_to_sql_with_foreign_key_set_null_on_delete() : void + { + $sqls = schema_table('comments', [ + schema_column('id', column_type_integer(), nullable: false), + schema_column('user_id', column_type_integer()), + ], foreignKeys: [ + schema_foreign_key( + ['user_id'], + 'users', + ['id'], + onDelete: ReferentialAction::SET_NULL, + ), + ])->toSql(); + + self::assertCount(1, $sqls); + self::assertSame( + 'CREATE TABLE public.comments (id int NOT NULL, user_id int, FOREIGN KEY (user_id) REFERENCES public.users (id) ON DELETE SET NULL)', + $sqls[0]->toSql(), + ); + } + + public function test_to_sql_with_gin_index() : void + { + $sqls = schema_table('documents', [ + schema_column('id', column_type_integer(), nullable: false), + schema_column('metadata', column_type_jsonb()), + ], indexes: [ + schema_index('idx_documents_metadata', ['metadata'], method: IndexMethod::GIN), + ])->toSql(); + + self::assertCount(2, $sqls); + self::assertSame( + 'CREATE INDEX idx_documents_metadata ON public.documents USING gin (metadata)', + $sqls[1]->toSql(), + ); + } + + public function test_to_sql_with_gist_index() : void + { + $sqls = schema_table('events', [ + schema_column('id', column_type_integer(), nullable: false), + schema_column('range_col', column_type_text()), + ], indexes: [ + schema_index('idx_events_range', ['range_col'], method: IndexMethod::GIST), + ])->toSql(); + + self::assertCount(2, $sqls); + self::assertSame( + 'CREATE INDEX idx_events_range ON public.events USING gist (range_col)', + $sqls[1]->toSql(), + ); + } + + public function test_to_sql_with_hash_index() : void + { + $sqls = schema_table('users', [ + schema_column('id', column_type_integer(), nullable: false), + schema_column('email', column_type_varchar(255)), + ], indexes: [ + schema_index('idx_users_email_hash', ['email'], method: IndexMethod::HASH), + ])->toSql(); + + self::assertCount(2, $sqls); + self::assertSame( + 'CREATE INDEX idx_users_email_hash ON public.users USING hash (email)', + $sqls[1]->toSql(), + ); + } + + public function test_to_sql_with_multiple_indexes() : void + { + $sqls = schema_table('users', [ + schema_column('id', column_type_integer(), nullable: false), + schema_column('email', column_type_varchar(255)), + schema_column('name', column_type_varchar(255)), + ], indexes: [ + schema_index('idx_users_email', ['email'], unique: true), + schema_index('idx_users_name', ['name']), + ])->toSql(); + + self::assertCount(3, $sqls); + self::assertSame('CREATE UNIQUE INDEX idx_users_email ON public.users (email)', $sqls[1]->toSql()); + self::assertSame('CREATE INDEX idx_users_name ON public.users (name)', $sqls[2]->toSql()); + } + + public function test_to_sql_with_multiple_triggers() : void + { + $sqls = schema_table('users', [ + schema_column('id', column_type_integer(), nullable: false), + ], triggers: [ + schema_trigger('trg_before', 'users', TriggerTiming::BEFORE, [TriggerEvent::INSERT], 'before_func', forEachRow: true), + schema_trigger('trg_after', 'users', TriggerTiming::AFTER, [TriggerEvent::UPDATE], 'after_func'), + ])->toSql(); + + self::assertCount(3, $sqls); + self::assertSame('CREATE TRIGGER trg_before BEFORE INSERT ON public.users FOR EACH ROW EXECUTE FUNCTION before_func()', $sqls[1]->toSql()); + self::assertSame('CREATE TRIGGER trg_after AFTER UPDATE ON public.users EXECUTE FUNCTION after_func()', $sqls[2]->toSql()); + } + + public function test_to_sql_with_named_check_constraint() : void + { + $sqls = schema_table('products', [ + schema_column('id', column_type_integer(), nullable: false), + schema_column('price', column_type_integer(), nullable: false), + ], checkConstraints: [ + schema_check('price > 0', name: 'positive_price'), + ])->toSql(); + + self::assertCount(1, $sqls); + self::assertSame( + 'CREATE TABLE public.products (id int NOT NULL, price int NOT NULL, CONSTRAINT positive_price CHECK (price > 0))', + $sqls[0]->toSql(), + ); + } + + public function test_to_sql_with_named_foreign_key_constraint() : void + { + $sqls = schema_table('orders', [ + schema_column('id', column_type_integer(), nullable: false), + schema_column('user_id', column_type_integer(), nullable: false), + ], foreignKeys: [ + schema_foreign_key( + ['user_id'], + 'users', + ['id'], + name: 'fk_orders_user_id', + ), + ])->toSql(); + + self::assertCount(1, $sqls); + self::assertSame( + 'CREATE TABLE public.orders (id int NOT NULL, user_id int NOT NULL, CONSTRAINT fk_orders_user_id FOREIGN KEY (user_id) REFERENCES public.users (id))', + $sqls[0]->toSql(), + ); + } + + public function test_to_sql_with_named_primary_key() : void + { + $sqls = schema_table('users', [ + schema_column('id', column_type_integer(), nullable: false), + ], primaryKey: schema_primary_key(['id'], name: 'pk_users'))->toSql(); + + self::assertCount(1, $sqls); + self::assertSame( + 'CREATE TABLE public.users (id int NOT NULL, CONSTRAINT pk_users PRIMARY KEY (id))', + $sqls[0]->toSql(), + ); + } + + public function test_to_sql_with_named_unique_constraint() : void + { + $sqls = schema_table('users', [ + schema_column('id', column_type_integer(), nullable: false), + schema_column('email', column_type_varchar(255), nullable: false), + ], uniqueConstraints: [ + schema_unique(['email'], name: 'uq_users_email'), + ])->toSql(); + + self::assertCount(1, $sqls); + self::assertSame( + 'CREATE TABLE public.users (id int NOT NULL, email varchar(255) NOT NULL, CONSTRAINT uq_users_email UNIQUE (email))', + $sqls[0]->toSql(), + ); + } + + public function test_to_sql_with_non_unique_index() : void + { + $sqls = schema_table('users', [ + schema_column('id', column_type_integer(), nullable: false), + schema_column('name', column_type_varchar(255)), + ], indexes: [ + schema_index('idx_users_name', ['name']), + ])->toSql(); + + self::assertCount(2, $sqls); + self::assertSame( + 'CREATE INDEX idx_users_name ON public.users (name)', + $sqls[1]->toSql(), + ); + } + + public function test_to_sql_with_trigger_after_insert() : void + { + $sqls = schema_table('users', [ + schema_column('id', column_type_integer(), nullable: false), + ], triggers: [ + schema_trigger('trg_audit', 'users', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'audit_function'), + ])->toSql(); + + self::assertCount(2, $sqls); + self::assertSame( + 'CREATE TRIGGER trg_audit AFTER INSERT ON public.users EXECUTE FUNCTION audit_function()', + $sqls[1]->toSql(), + ); + } + + public function test_to_sql_with_trigger_before_delete() : void + { + $sqls = schema_table('users', [ + schema_column('id', column_type_integer(), nullable: false), + ], triggers: [ + schema_trigger('trg_prevent_delete', 'users', TriggerTiming::BEFORE, [TriggerEvent::DELETE], 'prevent_delete_func', forEachRow: true), + ])->toSql(); + + self::assertCount(2, $sqls); + self::assertSame( + 'CREATE TRIGGER trg_prevent_delete BEFORE DELETE ON public.users FOR EACH ROW EXECUTE FUNCTION prevent_delete_func()', + $sqls[1]->toSql(), + ); + } + + public function test_to_sql_with_trigger_before_update_for_each_row() : void + { + $sqls = schema_table('users', [ + schema_column('id', column_type_integer(), nullable: false), + schema_column('updated_at', column_type_timestamptz()), + ], triggers: [ + schema_trigger('trg_update_timestamp', 'users', TriggerTiming::BEFORE, [TriggerEvent::UPDATE], 'update_timestamp', forEachRow: true), + ])->toSql(); + + self::assertCount(2, $sqls); + self::assertSame( + 'CREATE TRIGGER trg_update_timestamp BEFORE UPDATE ON public.users FOR EACH ROW EXECUTE FUNCTION update_timestamp()', + $sqls[1]->toSql(), + ); + } + + public function test_to_sql_with_trigger_instead_of() : void + { + $sqls = schema_table('users_view', [ + schema_column('id', column_type_integer(), nullable: false), + ], triggers: [ + schema_trigger('trg_view_insert', 'users_view', TriggerTiming::INSTEAD_OF, [TriggerEvent::INSERT], 'insert_to_users', forEachRow: true), + ])->toSql(); + + self::assertCount(2, $sqls); + self::assertSame( + 'CREATE TRIGGER trg_view_insert INSTEAD OF INSERT ON public.users_view FOR EACH ROW EXECUTE FUNCTION insert_to_users()', + $sqls[1]->toSql(), + ); + } + + public function test_to_sql_with_trigger_multiple_events() : void + { + $sqls = schema_table('users', [ + schema_column('id', column_type_integer(), nullable: false), + ], triggers: [ + schema_trigger('trg_audit', 'users', TriggerTiming::AFTER, [TriggerEvent::INSERT, TriggerEvent::UPDATE], 'audit_function', forEachRow: true), + ])->toSql(); + + self::assertCount(2, $sqls); + self::assertSame( + 'CREATE TRIGGER trg_audit AFTER INSERT OR UPDATE ON public.users FOR EACH ROW EXECUTE FUNCTION audit_function()', + $sqls[1]->toSql(), + ); + } + + public function test_to_sql_with_trigger_without_for_each_row() : void + { + $sqls = schema_table('users', [ + schema_column('id', column_type_integer(), nullable: false), + ], triggers: [ + schema_trigger('trg_statement', 'users', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'process_batch'), + ])->toSql(); + + self::assertCount(2, $sqls); + self::assertSame( + 'CREATE TRIGGER trg_statement AFTER INSERT ON public.users EXECUTE FUNCTION process_batch()', + $sqls[1]->toSql(), + ); + } + + public function test_to_sql_with_unique_constraint() : void + { + $sqls = schema_table('users', [ + schema_column('id', column_type_integer(), nullable: false), + schema_column('email', column_type_varchar(255), nullable: false), + ], uniqueConstraints: [ + schema_unique(['email']), + ])->toSql(); + + self::assertCount(1, $sqls); + self::assertSame( + 'CREATE TABLE public.users (id int NOT NULL, email varchar(255) NOT NULL, UNIQUE (email))', + $sqls[0]->toSql(), + ); + } + + public function test_to_sql_with_unique_constraint_nulls_not_distinct() : void + { + $sqls = schema_table('users', [ + schema_column('id', column_type_integer(), nullable: false), + schema_column('email', column_type_varchar(255)), + ], uniqueConstraints: [ + schema_unique(['email'], nullsNotDistinct: true), + ])->toSql(); + + self::assertCount(1, $sqls); + self::assertSame( + 'CREATE TABLE public.users (id int NOT NULL, email varchar(255), UNIQUE NULLS NOT DISTINCT (email))', + $sqls[0]->toSql(), + ); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/TriggerTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/TriggerTest.php new file mode 100644 index 0000000000..bf49b4cd23 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/TriggerTest.php @@ -0,0 +1,121 @@ + 0'); + $b = schema_trigger('trg_audit', 'orders', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'audit_fn', forEachRow: true, whenCondition: 'NEW.x > 0'); + + self::assertTrue($a->isEqual($b)); + } + + public function test_is_equal_returns_false_when_events_differ() : void + { + $a = schema_trigger('trg_audit', 'orders', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'audit_fn'); + $b = schema_trigger('trg_audit', 'orders', TriggerTiming::AFTER, [TriggerEvent::UPDATE], 'audit_fn'); + + self::assertFalse($a->isEqual($b)); + } + + public function test_is_equal_returns_false_when_function_name_differs() : void + { + $a = schema_trigger('trg_audit', 'orders', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'fn_a'); + $b = schema_trigger('trg_audit', 'orders', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'fn_b'); + + self::assertFalse($a->isEqual($b)); + } + + public function test_is_equal_returns_false_when_name_differs() : void + { + $a = schema_trigger('trg_a', 'orders', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'audit_fn'); + $b = schema_trigger('trg_b', 'orders', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'audit_fn'); + + self::assertFalse($a->isEqual($b)); + } + + public function test_is_equal_returns_false_when_table_name_differs() : void + { + $a = schema_trigger('trg_audit', 'orders', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'audit_fn'); + $b = schema_trigger('trg_audit', 'users', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'audit_fn'); + + self::assertFalse($a->isEqual($b)); + } + + public function test_is_equal_returns_false_when_timing_differs() : void + { + $a = schema_trigger('trg_audit', 'orders', TriggerTiming::BEFORE, [TriggerEvent::INSERT], 'audit_fn'); + $b = schema_trigger('trg_audit', 'orders', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'audit_fn'); + + self::assertFalse($a->isEqual($b)); + } + + public function test_is_equal_structure_returns_false_when_for_each_row_differs() : void + { + $a = schema_trigger('trg_audit', 'orders', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'audit_fn', forEachRow: true); + $b = schema_trigger('trg_audit', 'orders', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'audit_fn', forEachRow: false); + + self::assertFalse($a->isEqualStructure($b)); + } + + public function test_is_equal_structure_returns_false_when_timing_differs() : void + { + $a = schema_trigger('trg_audit', 'orders', TriggerTiming::BEFORE, [TriggerEvent::INSERT], 'audit_fn'); + $b = schema_trigger('trg_audit', 'orders', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'audit_fn'); + + self::assertFalse($a->isEqualStructure($b)); + } + + public function test_is_equal_structure_returns_false_when_when_condition_differs() : void + { + $a = schema_trigger('trg_audit', 'orders', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'audit_fn', whenCondition: 'NEW.x > 0'); + $b = schema_trigger('trg_audit', 'orders', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'audit_fn', whenCondition: 'NEW.x > 100'); + + self::assertFalse($a->isEqualStructure($b)); + } + + public function test_is_equal_structure_returns_true_when_only_name_and_table_differ() : void + { + $a = schema_trigger('trg_a', 'orders', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'audit_fn', forEachRow: true, whenCondition: 'NEW.x > 0'); + $b = schema_trigger('trg_b', 'users', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'audit_fn', forEachRow: true, whenCondition: 'NEW.x > 0'); + + self::assertTrue($a->isEqualStructure($b)); + } + + public function test_trigger_construction() : void + { + $trigger = schema_trigger('trg_audit', 'orders', TriggerTiming::AFTER, [TriggerEvent::INSERT], 'audit_function'); + + self::assertSame('trg_audit', $trigger->name); + self::assertSame('orders', $trigger->tableName); + self::assertSame(TriggerTiming::AFTER, $trigger->timing); + self::assertSame([TriggerEvent::INSERT], $trigger->events); + self::assertSame('audit_function', $trigger->functionName); + self::assertFalse($trigger->forEachRow); + self::assertNull($trigger->whenCondition); + } + + public function test_trigger_for_each_row() : void + { + $trigger = schema_trigger('trg_update', 'users', TriggerTiming::BEFORE, [TriggerEvent::UPDATE], 'update_fn', forEachRow: true); + + self::assertTrue($trigger->forEachRow); + } + + public function test_trigger_with_when_condition() : void + { + $trigger = schema_trigger('trg_check', 'orders', TriggerTiming::BEFORE, [TriggerEvent::INSERT, TriggerEvent::UPDATE], 'check_fn', whenCondition: 'NEW.amount > 1000'); + + self::assertSame('NEW.amount > 1000', $trigger->whenCondition); + self::assertCount(2, $trigger->events); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/ViewDependencyOrderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/ViewDependencyOrderTest.php new file mode 100644 index 0000000000..18523c93cf --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/ViewDependencyOrderTest.php @@ -0,0 +1,88 @@ +expectException(SchemaException::class); + $this->expectExceptionMessage('Circular view dependency'); + + (new ViewDependencyOrder(new \Flow\PostgreSql\Parser()))->order([$viewA, $viewB]); + } + + public function test_empty_list() : void + { + self::assertSame([], (new ViewDependencyOrder(new \Flow\PostgreSql\Parser()))->order([])); + } + + public function test_linear_chain() : void + { + $base = new View('base_view', 'SELECT id, name FROM users'); + $middle = new View('middle_view', 'SELECT id FROM base_view WHERE id > 0'); + $top = new View('top_view', 'SELECT * FROM middle_view'); + + $result = (new ViewDependencyOrder(new \Flow\PostgreSql\Parser()))->order([$top, $middle, $base]); + + $names = \array_map(static fn (View $v) => $v->name, $result); + + self::assertSame(['base_view', 'middle_view', 'top_view'], $names); + } + + public function test_self_referencing_view() : void + { + $recursive = new View('recursive_view', 'SELECT * FROM recursive_view'); + $other = new View('other_view', 'SELECT * FROM recursive_view'); + + $result = (new ViewDependencyOrder(new \Flow\PostgreSql\Parser()))->order([$other, $recursive]); + + $names = \array_map(static fn (View $v) => $v->name, $result); + + self::assertSame(['recursive_view', 'other_view'], $names); + } + + public function test_single_view() : void + { + $view = new View('my_view', 'SELECT * FROM users'); + + $result = (new ViewDependencyOrder(new \Flow\PostgreSql\Parser()))->order([$view]); + + self::assertCount(1, $result); + self::assertSame('my_view', $result[0]->name); + } + + public function test_view_referencing_external_table_is_not_affected() : void + { + $viewA = new View('view_a', 'SELECT * FROM external_table'); + $viewB = new View('view_b', 'SELECT * FROM another_external'); + + $result = (new ViewDependencyOrder(new \Flow\PostgreSql\Parser()))->order([$viewA, $viewB]); + + self::assertCount(2, $result); + self::assertSame('view_a', $result[0]->name); + self::assertSame('view_b', $result[1]->name); + } + + public function test_views_without_dependencies_preserve_order() : void + { + $viewA = new View('alpha', 'SELECT 1 AS val'); + $viewB = new View('beta', 'SELECT 2 AS val'); + $viewC = new View('gamma', 'SELECT 3 AS val'); + + $result = (new ViewDependencyOrder(new \Flow\PostgreSql\Parser()))->order([$viewA, $viewB, $viewC]); + + $names = \array_map(static fn (View $v) => $v->name, $result); + + self::assertSame(['alpha', 'beta', 'gamma'], $names); + } +} diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/ViewTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/ViewTest.php new file mode 100644 index 0000000000..e3ec1ec2f5 --- /dev/null +++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/Schema/ViewTest.php @@ -0,0 +1,37 @@ +from(table('users'))->toSql())->toSql()->toSql(), + ); + } + + public function test_view_construction() : void + { + $definition = select(star())->from(table('users'))->where(eq(col('active'), literal(true)))->toSql(); + $view = schema_view('active_users', $definition); + + self::assertSame('active_users', $view->name); + self::assertSame($definition, $view->definition); + self::assertFalse($view->isUpdatable); + } + + public function test_view_updatable() : void + { + $view = schema_view('user_emails', select(col('id'), col('email'))->from(table('users'))->toSql(), isUpdatable: true); + + self::assertTrue($view->isUpdatable); + } +} diff --git a/src/lib/telemetry/composer.json b/src/lib/telemetry/composer.json index 825c61986c..9b8401be03 100644 --- a/src/lib/telemetry/composer.json +++ b/src/lib/telemetry/composer.json @@ -10,7 +10,7 @@ ], "require": { "php": "~8.3.0 || ~8.4.0 || ~8.5.0", - "composer-runtime-api": "^2.0", + "composer-runtime-api": "^2.2", "psr/clock": "^1.0", "symfony/polyfill-mbstring": "^1.33" }, diff --git a/tools/blackfire/composer.lock b/tools/blackfire/composer.lock index 0f9e0bc0aa..b140173823 100644 --- a/tools/blackfire/composer.lock +++ b/tools/blackfire/composer.lock @@ -85,16 +85,16 @@ }, { "name": "composer/ca-bundle", - "version": "1.5.10", + "version": "1.5.11", "source": { "type": "git", "url": "https://github.com/composer/ca-bundle.git", - "reference": "961a5e4056dd2e4a2eedcac7576075947c28bf63" + "reference": "68ff39175e8e94a4bb1d259407ce51a6a60f09e6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/ca-bundle/zipball/961a5e4056dd2e4a2eedcac7576075947c28bf63", - "reference": "961a5e4056dd2e4a2eedcac7576075947c28bf63", + "url": "https://api.github.com/repos/composer/ca-bundle/zipball/68ff39175e8e94a4bb1d259407ce51a6a60f09e6", + "reference": "68ff39175e8e94a4bb1d259407ce51a6a60f09e6", "shasum": "" }, "require": { @@ -141,7 +141,7 @@ "support": { "irc": "irc://irc.freenode.org/composer", "issues": "https://github.com/composer/ca-bundle/issues", - "source": "https://github.com/composer/ca-bundle/tree/1.5.10" + "source": "https://github.com/composer/ca-bundle/tree/1.5.11" }, "funding": [ { @@ -153,7 +153,7 @@ "type": "github" } ], - "time": "2025-12-08T15:06:51+00:00" + "time": "2026-03-30T09:16:10+00:00" } ], "aliases": [], @@ -165,5 +165,5 @@ "platform-dev": { "php": "~8.3.0 || ~8.4.0 || ~8.5.0" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.9.0" } diff --git a/tools/box/composer.lock b/tools/box/composer.lock index c8ef65e087..6326c71473 100644 --- a/tools/box/composer.lock +++ b/tools/box/composer.lock @@ -1528,16 +1528,16 @@ }, { "name": "justinrainbow/json-schema", - "version": "v6.7.2", + "version": "6.8.0", "source": { "type": "git", "url": "https://github.com/jsonrainbow/json-schema.git", - "reference": "6fea66c7204683af437864e7c4e7abf383d14bc0" + "reference": "89ac92bcfe5d0a8a4433c7b89d394553ae7250cc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/6fea66c7204683af437864e7c4e7abf383d14bc0", - "reference": "6fea66c7204683af437864e7c4e7abf383d14bc0", + "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/89ac92bcfe5d0a8a4433c7b89d394553ae7250cc", + "reference": "89ac92bcfe5d0a8a4433c7b89d394553ae7250cc", "shasum": "" }, "require": { @@ -1597,9 +1597,9 @@ ], "support": { "issues": "https://github.com/jsonrainbow/json-schema/issues", - "source": "https://github.com/jsonrainbow/json-schema/tree/v6.7.2" + "source": "https://github.com/jsonrainbow/json-schema/tree/6.8.0" }, - "time": "2026-02-15T15:06:22+00:00" + "time": "2026-04-02T12:43:11+00:00" }, { "name": "kelunik/certificate", @@ -2760,16 +2760,16 @@ }, { "name": "symfony/console", - "version": "v7.4.7", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "e1e6770440fb9c9b0cf725f81d1361ad1835329d" + "reference": "1e92e39c51f95b88e3d66fa2d9f06d1fb45dd707" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/e1e6770440fb9c9b0cf725f81d1361ad1835329d", - "reference": "e1e6770440fb9c9b0cf725f81d1361ad1835329d", + "url": "https://api.github.com/repos/symfony/console/zipball/1e92e39c51f95b88e3d66fa2d9f06d1fb45dd707", + "reference": "1e92e39c51f95b88e3d66fa2d9f06d1fb45dd707", "shasum": "" }, "require": { @@ -2834,7 +2834,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.4.7" + "source": "https://github.com/symfony/console/tree/v7.4.8" }, "funding": [ { @@ -2854,7 +2854,7 @@ "type": "tidelift" } ], - "time": "2026-03-06T14:06:20+00:00" + "time": "2026-03-30T13:54:39+00:00" }, { "name": "symfony/deprecation-contracts", @@ -3001,16 +3001,16 @@ }, { "name": "symfony/filesystem", - "version": "v7.4.6", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "3ebc794fa5315e59fd122561623c2e2e4280538e" + "reference": "58b9790d12f9670b7f53a1c1738febd3108970a5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/3ebc794fa5315e59fd122561623c2e2e4280538e", - "reference": "3ebc794fa5315e59fd122561623c2e2e4280538e", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/58b9790d12f9670b7f53a1c1738febd3108970a5", + "reference": "58b9790d12f9670b7f53a1c1738febd3108970a5", "shasum": "" }, "require": { @@ -3047,7 +3047,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v7.4.6" + "source": "https://github.com/symfony/filesystem/tree/v7.4.8" }, "funding": [ { @@ -3067,20 +3067,20 @@ "type": "tidelift" } ], - "time": "2026-02-25T16:50:00+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/finder", - "version": "v7.4.6", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "8655bf1076b7a3a346cb11413ffdabff50c7ffcf" + "reference": "e0be088d22278583a82da281886e8c3592fbf149" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/8655bf1076b7a3a346cb11413ffdabff50c7ffcf", - "reference": "8655bf1076b7a3a346cb11413ffdabff50c7ffcf", + "url": "https://api.github.com/repos/symfony/finder/zipball/e0be088d22278583a82da281886e8c3592fbf149", + "reference": "e0be088d22278583a82da281886e8c3592fbf149", "shasum": "" }, "require": { @@ -3115,7 +3115,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.6" + "source": "https://github.com/symfony/finder/tree/v7.4.8" }, "funding": [ { @@ -3135,7 +3135,7 @@ "type": "tidelift" } ], - "time": "2026-01-29T09:40:50+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/polyfill-ctype", @@ -3638,16 +3638,16 @@ }, { "name": "symfony/process", - "version": "v7.4.5", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "608476f4604102976d687c483ac63a79ba18cc97" + "reference": "60f19cd3badc8de688421e21e4305eba50f8089a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/608476f4604102976d687c483ac63a79ba18cc97", - "reference": "608476f4604102976d687c483ac63a79ba18cc97", + "url": "https://api.github.com/repos/symfony/process/zipball/60f19cd3badc8de688421e21e4305eba50f8089a", + "reference": "60f19cd3badc8de688421e21e4305eba50f8089a", "shasum": "" }, "require": { @@ -3679,7 +3679,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.4.5" + "source": "https://github.com/symfony/process/tree/v7.4.8" }, "funding": [ { @@ -3699,7 +3699,7 @@ "type": "tidelift" } ], - "time": "2026-01-26T15:07:59+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/service-contracts", @@ -3790,16 +3790,16 @@ }, { "name": "symfony/string", - "version": "v7.4.6", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "9f209231affa85aa930a5e46e6eb03381424b30b" + "reference": "114ac57257d75df748eda23dd003878080b8e688" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/9f209231affa85aa930a5e46e6eb03381424b30b", - "reference": "9f209231affa85aa930a5e46e6eb03381424b30b", + "url": "https://api.github.com/repos/symfony/string/zipball/114ac57257d75df748eda23dd003878080b8e688", + "reference": "114ac57257d75df748eda23dd003878080b8e688", "shasum": "" }, "require": { @@ -3857,7 +3857,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.4.6" + "source": "https://github.com/symfony/string/tree/v7.4.8" }, "funding": [ { @@ -3877,20 +3877,20 @@ "type": "tidelift" } ], - "time": "2026-02-09T09:33:46+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/var-dumper", - "version": "v7.4.6", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "045321c440ac18347b136c63d2e9bf28a2dc0291" + "reference": "9510c3966f749a1d1ff0059e1eabef6cc621e7fd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/045321c440ac18347b136c63d2e9bf28a2dc0291", - "reference": "045321c440ac18347b136c63d2e9bf28a2dc0291", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/9510c3966f749a1d1ff0059e1eabef6cc621e7fd", + "reference": "9510c3966f749a1d1ff0059e1eabef6cc621e7fd", "shasum": "" }, "require": { @@ -3944,7 +3944,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v7.4.6" + "source": "https://github.com/symfony/var-dumper/tree/v7.4.8" }, "funding": [ { @@ -3964,7 +3964,7 @@ "type": "tidelift" } ], - "time": "2026-02-15T10:53:20+00:00" + "time": "2026-03-30T13:44:50+00:00" }, { "name": "thecodingmachine/safe", @@ -4177,5 +4177,5 @@ "platform-dev": { "php": "~8.3.0 || ~8.4.0 || ~8.5.0" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.9.0" } diff --git a/tools/cs-fixer/composer.lock b/tools/cs-fixer/composer.lock index 3fc71c0c63..1e8989281e 100644 --- a/tools/cs-fixer/composer.lock +++ b/tools/cs-fixer/composer.lock @@ -1253,16 +1253,16 @@ }, { "name": "symfony/console", - "version": "v7.4.7", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "e1e6770440fb9c9b0cf725f81d1361ad1835329d" + "reference": "1e92e39c51f95b88e3d66fa2d9f06d1fb45dd707" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/e1e6770440fb9c9b0cf725f81d1361ad1835329d", - "reference": "e1e6770440fb9c9b0cf725f81d1361ad1835329d", + "url": "https://api.github.com/repos/symfony/console/zipball/1e92e39c51f95b88e3d66fa2d9f06d1fb45dd707", + "reference": "1e92e39c51f95b88e3d66fa2d9f06d1fb45dd707", "shasum": "" }, "require": { @@ -1327,7 +1327,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.4.7" + "source": "https://github.com/symfony/console/tree/v7.4.8" }, "funding": [ { @@ -1347,7 +1347,7 @@ "type": "tidelift" } ], - "time": "2026-03-06T14:06:20+00:00" + "time": "2026-03-30T13:54:39+00:00" }, { "name": "symfony/deprecation-contracts", @@ -1418,16 +1418,16 @@ }, { "name": "symfony/event-dispatcher", - "version": "v7.4.4", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "dc2c0eba1af673e736bb851d747d266108aea746" + "reference": "f57b899fa736fd71121168ef268f23c206083f0a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/dc2c0eba1af673e736bb851d747d266108aea746", - "reference": "dc2c0eba1af673e736bb851d747d266108aea746", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/f57b899fa736fd71121168ef268f23c206083f0a", + "reference": "f57b899fa736fd71121168ef268f23c206083f0a", "shasum": "" }, "require": { @@ -1479,7 +1479,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v7.4.4" + "source": "https://github.com/symfony/event-dispatcher/tree/v7.4.8" }, "funding": [ { @@ -1499,7 +1499,7 @@ "type": "tidelift" } ], - "time": "2026-01-05T11:45:34+00:00" + "time": "2026-03-30T13:54:39+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -1579,16 +1579,16 @@ }, { "name": "symfony/filesystem", - "version": "v7.4.6", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "3ebc794fa5315e59fd122561623c2e2e4280538e" + "reference": "58b9790d12f9670b7f53a1c1738febd3108970a5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/3ebc794fa5315e59fd122561623c2e2e4280538e", - "reference": "3ebc794fa5315e59fd122561623c2e2e4280538e", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/58b9790d12f9670b7f53a1c1738febd3108970a5", + "reference": "58b9790d12f9670b7f53a1c1738febd3108970a5", "shasum": "" }, "require": { @@ -1625,7 +1625,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v7.4.6" + "source": "https://github.com/symfony/filesystem/tree/v7.4.8" }, "funding": [ { @@ -1645,20 +1645,20 @@ "type": "tidelift" } ], - "time": "2026-02-25T16:50:00+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/finder", - "version": "v7.4.6", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "8655bf1076b7a3a346cb11413ffdabff50c7ffcf" + "reference": "e0be088d22278583a82da281886e8c3592fbf149" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/8655bf1076b7a3a346cb11413ffdabff50c7ffcf", - "reference": "8655bf1076b7a3a346cb11413ffdabff50c7ffcf", + "url": "https://api.github.com/repos/symfony/finder/zipball/e0be088d22278583a82da281886e8c3592fbf149", + "reference": "e0be088d22278583a82da281886e8c3592fbf149", "shasum": "" }, "require": { @@ -1693,7 +1693,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.6" + "source": "https://github.com/symfony/finder/tree/v7.4.8" }, "funding": [ { @@ -1713,20 +1713,20 @@ "type": "tidelift" } ], - "time": "2026-01-29T09:40:50+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/options-resolver", - "version": "v7.4.0", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "b38026df55197f9e39a44f3215788edf83187b80" + "reference": "2888fcdc4dc2fd5f7c7397be78631e8af12e02b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/b38026df55197f9e39a44f3215788edf83187b80", - "reference": "b38026df55197f9e39a44f3215788edf83187b80", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/2888fcdc4dc2fd5f7c7397be78631e8af12e02b4", + "reference": "2888fcdc4dc2fd5f7c7397be78631e8af12e02b4", "shasum": "" }, "require": { @@ -1764,7 +1764,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v7.4.0" + "source": "https://github.com/symfony/options-resolver/tree/v7.4.8" }, "funding": [ { @@ -1784,7 +1784,7 @@ "type": "tidelift" } ], - "time": "2025-11-12T15:39:26+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/polyfill-ctype", @@ -2367,16 +2367,16 @@ }, { "name": "symfony/process", - "version": "v7.4.5", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "608476f4604102976d687c483ac63a79ba18cc97" + "reference": "60f19cd3badc8de688421e21e4305eba50f8089a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/608476f4604102976d687c483ac63a79ba18cc97", - "reference": "608476f4604102976d687c483ac63a79ba18cc97", + "url": "https://api.github.com/repos/symfony/process/zipball/60f19cd3badc8de688421e21e4305eba50f8089a", + "reference": "60f19cd3badc8de688421e21e4305eba50f8089a", "shasum": "" }, "require": { @@ -2408,7 +2408,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.4.5" + "source": "https://github.com/symfony/process/tree/v7.4.8" }, "funding": [ { @@ -2428,7 +2428,7 @@ "type": "tidelift" } ], - "time": "2026-01-26T15:07:59+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/service-contracts", @@ -2519,16 +2519,16 @@ }, { "name": "symfony/stopwatch", - "version": "v7.4.0", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "8a24af0a2e8a872fb745047180649b8418303084" + "reference": "70a852d72fec4d51efb1f48dcd968efcaf5ccb89" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/8a24af0a2e8a872fb745047180649b8418303084", - "reference": "8a24af0a2e8a872fb745047180649b8418303084", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/70a852d72fec4d51efb1f48dcd968efcaf5ccb89", + "reference": "70a852d72fec4d51efb1f48dcd968efcaf5ccb89", "shasum": "" }, "require": { @@ -2561,7 +2561,7 @@ "description": "Provides a way to profile code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/stopwatch/tree/v7.4.0" + "source": "https://github.com/symfony/stopwatch/tree/v7.4.8" }, "funding": [ { @@ -2581,20 +2581,20 @@ "type": "tidelift" } ], - "time": "2025-08-04T07:05:15+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/string", - "version": "v7.4.6", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "9f209231affa85aa930a5e46e6eb03381424b30b" + "reference": "114ac57257d75df748eda23dd003878080b8e688" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/9f209231affa85aa930a5e46e6eb03381424b30b", - "reference": "9f209231affa85aa930a5e46e6eb03381424b30b", + "url": "https://api.github.com/repos/symfony/string/zipball/114ac57257d75df748eda23dd003878080b8e688", + "reference": "114ac57257d75df748eda23dd003878080b8e688", "shasum": "" }, "require": { @@ -2652,7 +2652,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.4.6" + "source": "https://github.com/symfony/string/tree/v7.4.8" }, "funding": [ { @@ -2672,7 +2672,7 @@ "type": "tidelift" } ], - "time": "2026-02-09T09:33:46+00:00" + "time": "2026-03-24T13:12:05+00:00" } ], "aliases": [], @@ -2684,5 +2684,5 @@ "platform-dev": { "php": "~8.3.0 || ~8.4.0 || ~8.5.0" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.9.0" } diff --git a/tools/infection/composer.lock b/tools/infection/composer.lock index 178fce247c..3581df553a 100644 --- a/tools/infection/composer.lock +++ b/tools/infection/composer.lock @@ -664,16 +664,16 @@ }, { "name": "justinrainbow/json-schema", - "version": "v6.7.2", + "version": "6.8.0", "source": { "type": "git", "url": "https://github.com/jsonrainbow/json-schema.git", - "reference": "6fea66c7204683af437864e7c4e7abf383d14bc0" + "reference": "89ac92bcfe5d0a8a4433c7b89d394553ae7250cc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/6fea66c7204683af437864e7c4e7abf383d14bc0", - "reference": "6fea66c7204683af437864e7c4e7abf383d14bc0", + "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/89ac92bcfe5d0a8a4433c7b89d394553ae7250cc", + "reference": "89ac92bcfe5d0a8a4433c7b89d394553ae7250cc", "shasum": "" }, "require": { @@ -733,9 +733,9 @@ ], "support": { "issues": "https://github.com/jsonrainbow/json-schema/issues", - "source": "https://github.com/jsonrainbow/json-schema/tree/v6.7.2" + "source": "https://github.com/jsonrainbow/json-schema/tree/6.8.0" }, - "time": "2026-02-15T15:06:22+00:00" + "time": "2026-04-02T12:43:11+00:00" }, { "name": "marc-mabe/php-enum", @@ -1440,16 +1440,16 @@ }, { "name": "symfony/console", - "version": "v7.4.7", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "e1e6770440fb9c9b0cf725f81d1361ad1835329d" + "reference": "1e92e39c51f95b88e3d66fa2d9f06d1fb45dd707" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/e1e6770440fb9c9b0cf725f81d1361ad1835329d", - "reference": "e1e6770440fb9c9b0cf725f81d1361ad1835329d", + "url": "https://api.github.com/repos/symfony/console/zipball/1e92e39c51f95b88e3d66fa2d9f06d1fb45dd707", + "reference": "1e92e39c51f95b88e3d66fa2d9f06d1fb45dd707", "shasum": "" }, "require": { @@ -1514,7 +1514,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.4.7" + "source": "https://github.com/symfony/console/tree/v7.4.8" }, "funding": [ { @@ -1534,7 +1534,7 @@ "type": "tidelift" } ], - "time": "2026-03-06T14:06:20+00:00" + "time": "2026-03-30T13:54:39+00:00" }, { "name": "symfony/deprecation-contracts", @@ -1605,16 +1605,16 @@ }, { "name": "symfony/filesystem", - "version": "v7.4.6", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "3ebc794fa5315e59fd122561623c2e2e4280538e" + "reference": "58b9790d12f9670b7f53a1c1738febd3108970a5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/3ebc794fa5315e59fd122561623c2e2e4280538e", - "reference": "3ebc794fa5315e59fd122561623c2e2e4280538e", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/58b9790d12f9670b7f53a1c1738febd3108970a5", + "reference": "58b9790d12f9670b7f53a1c1738febd3108970a5", "shasum": "" }, "require": { @@ -1651,7 +1651,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v7.4.6" + "source": "https://github.com/symfony/filesystem/tree/v7.4.8" }, "funding": [ { @@ -1671,20 +1671,20 @@ "type": "tidelift" } ], - "time": "2026-02-25T16:50:00+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/finder", - "version": "v7.4.6", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "8655bf1076b7a3a346cb11413ffdabff50c7ffcf" + "reference": "e0be088d22278583a82da281886e8c3592fbf149" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/8655bf1076b7a3a346cb11413ffdabff50c7ffcf", - "reference": "8655bf1076b7a3a346cb11413ffdabff50c7ffcf", + "url": "https://api.github.com/repos/symfony/finder/zipball/e0be088d22278583a82da281886e8c3592fbf149", + "reference": "e0be088d22278583a82da281886e8c3592fbf149", "shasum": "" }, "require": { @@ -1719,7 +1719,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.6" + "source": "https://github.com/symfony/finder/tree/v7.4.8" }, "funding": [ { @@ -1739,7 +1739,7 @@ "type": "tidelift" } ], - "time": "2026-01-29T09:40:50+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/polyfill-ctype", @@ -2078,16 +2078,16 @@ }, { "name": "symfony/process", - "version": "v7.4.5", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "608476f4604102976d687c483ac63a79ba18cc97" + "reference": "60f19cd3badc8de688421e21e4305eba50f8089a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/608476f4604102976d687c483ac63a79ba18cc97", - "reference": "608476f4604102976d687c483ac63a79ba18cc97", + "url": "https://api.github.com/repos/symfony/process/zipball/60f19cd3badc8de688421e21e4305eba50f8089a", + "reference": "60f19cd3badc8de688421e21e4305eba50f8089a", "shasum": "" }, "require": { @@ -2119,7 +2119,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.4.5" + "source": "https://github.com/symfony/process/tree/v7.4.8" }, "funding": [ { @@ -2139,7 +2139,7 @@ "type": "tidelift" } ], - "time": "2026-01-26T15:07:59+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/service-contracts", @@ -2230,16 +2230,16 @@ }, { "name": "symfony/string", - "version": "v7.4.6", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "9f209231affa85aa930a5e46e6eb03381424b30b" + "reference": "114ac57257d75df748eda23dd003878080b8e688" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/9f209231affa85aa930a5e46e6eb03381424b30b", - "reference": "9f209231affa85aa930a5e46e6eb03381424b30b", + "url": "https://api.github.com/repos/symfony/string/zipball/114ac57257d75df748eda23dd003878080b8e688", + "reference": "114ac57257d75df748eda23dd003878080b8e688", "shasum": "" }, "require": { @@ -2297,7 +2297,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.4.6" + "source": "https://github.com/symfony/string/tree/v7.4.8" }, "funding": [ { @@ -2317,7 +2317,7 @@ "type": "tidelift" } ], - "time": "2026-02-09T09:33:46+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "thecodingmachine/safe", @@ -2530,5 +2530,5 @@ "platform-dev": { "php": "~8.3.0 || ~8.4.0 || ~8.5.0" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.9.0" } diff --git a/tools/monorepo/composer.lock b/tools/monorepo/composer.lock index bd9f5e7373..fc723635a2 100644 --- a/tools/monorepo/composer.lock +++ b/tools/monorepo/composer.lock @@ -69,5 +69,5 @@ "platform-dev": { "php": "~8.3.0 || ~8.4.0 || ~8.5.0" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.9.0" } diff --git a/tools/phpdocumentor/composer.lock b/tools/phpdocumentor/composer.lock index 7758df5c6d..bc35c586d0 100644 --- a/tools/phpdocumentor/composer.lock +++ b/tools/phpdocumentor/composer.lock @@ -267,5 +267,5 @@ "platform-dev": { "php": "~8.3.0 || ~8.4.0 || ~8.5.0" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.9.0" } diff --git a/tools/phpstan/composer.lock b/tools/phpstan/composer.lock index ab11b68e07..5489bb0634 100644 --- a/tools/phpstan/composer.lock +++ b/tools/phpstan/composer.lock @@ -9,11 +9,11 @@ "packages-dev": [ { "name": "phpstan/phpstan", - "version": "2.1.44", + "version": "2.1.46", "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/4a88c083c668b2c364a425c9b3171b2d9ea5d218", - "reference": "4a88c083c668b2c364a425c9b3171b2d9ea5d218", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/a193923fc2d6325ef4e741cf3af8c3e8f54dbf25", + "reference": "a193923fc2d6325ef4e741cf3af8c3e8f54dbf25", "shasum": "" }, "require": { @@ -58,20 +58,20 @@ "type": "github" } ], - "time": "2026-03-25T17:34:21+00:00" + "time": "2026-04-01T09:25:14+00:00" }, { "name": "spaze/phpstan-disallowed-calls", - "version": "v4.9.0", + "version": "v4.9.2", "source": { "type": "git", "url": "https://github.com/spaze/phpstan-disallowed-calls.git", - "reference": "e80372a55bdad13d22a62fdf2116a67a5438c34b" + "reference": "cc78e77f9f8f2bd3d66c7c88cd9c9e07762a0d87" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spaze/phpstan-disallowed-calls/zipball/e80372a55bdad13d22a62fdf2116a67a5438c34b", - "reference": "e80372a55bdad13d22a62fdf2116a67a5438c34b", + "url": "https://api.github.com/repos/spaze/phpstan-disallowed-calls/zipball/cc78e77f9f8f2bd3d66c7c88cd9c9e07762a0d87", + "reference": "cc78e77f9f8f2bd3d66c7c88cd9c9e07762a0d87", "shasum": "" }, "require": { @@ -111,13 +111,13 @@ "homepage": "https://www.michalspacek.cz" } ], - "description": "PHPStan rules to detect disallowed method & function calls, constant, namespace, attribute & superglobal usages, with powerful rules to re-allow a call or a usage in places where it should be allowed.", + "description": "PHPStan rules to detect disallowed method & function calls, constant, namespace, attribute, property & superglobal usages, with powerful rules to re-allow a call or a usage in places where it should be allowed.", "keywords": [ "static analysis" ], "support": { "issues": "https://github.com/spaze/phpstan-disallowed-calls/issues", - "source": "https://github.com/spaze/phpstan-disallowed-calls/tree/v4.9.0" + "source": "https://github.com/spaze/phpstan-disallowed-calls/tree/v4.9.2" }, "funding": [ { @@ -125,7 +125,7 @@ "type": "github" } ], - "time": "2026-03-13T22:27:50+00:00" + "time": "2026-03-31T22:26:59+00:00" } ], "aliases": [], @@ -137,5 +137,5 @@ "platform-dev": { "php": "~8.3.0 || ~8.4.0 || ~8.5.0" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.9.0" } diff --git a/tools/phpunit/composer.lock b/tools/phpunit/composer.lock index 71a8b86c70..338e67fcf4 100644 --- a/tools/phpunit/composer.lock +++ b/tools/phpunit/composer.lock @@ -1798,5 +1798,5 @@ "platform-dev": { "php": "~8.3.0 || ~8.4.0 || ~8.5.0" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.9.0" } diff --git a/tools/rector/composer.lock b/tools/rector/composer.lock index 4f6a8582a2..37515f7f65 100644 --- a/tools/rector/composer.lock +++ b/tools/rector/composer.lock @@ -9,11 +9,11 @@ "packages-dev": [ { "name": "phpstan/phpstan", - "version": "2.1.44", + "version": "2.1.46", "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/4a88c083c668b2c364a425c9b3171b2d9ea5d218", - "reference": "4a88c083c668b2c364a425c9b3171b2d9ea5d218", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/a193923fc2d6325ef4e741cf3af8c3e8f54dbf25", + "reference": "a193923fc2d6325ef4e741cf3af8c3e8f54dbf25", "shasum": "" }, "require": { @@ -58,7 +58,7 @@ "type": "github" } ], - "time": "2026-03-25T17:34:21+00:00" + "time": "2026-04-01T09:25:14+00:00" }, { "name": "rector/rector", @@ -130,5 +130,5 @@ "platform-dev": { "php": "~8.3.0 || ~8.4.0 || ~8.5.0" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.9.0" } diff --git a/web/landing/assets/codemirror/completions/dsl.js b/web/landing/assets/codemirror/completions/dsl.js index adca23daeb..f330d11824 100644 --- a/web/landing/assets/codemirror/completions/dsl.js +++ b/web/landing/assets/codemirror/completions/dsl.js @@ -156,7 +156,7 @@ const dslFunctions = [ apply: snippet("\\Flow\\ETL\\DSL\\all(" + "$" + "{" + "1:functions" + "}" + ")"), boost: 10 }, { - label: "all_sub_select", + label: "all_", type: "function", detail: "flow\u002Ddsl\u002Dhelpers", info: () => { @@ -171,7 +171,7 @@ const dslFunctions = [ ` return div }, - apply: snippet("\\Flow\\PostgreSql\\DSL\\all_sub_select(" + "$" + "{" + "1:left" + "}" + ", " + "$" + "{" + "2:operator" + "}" + ", " + "$" + "{" + "3:subquery" + "}" + ")"), + apply: snippet("\\Flow\\PostgreSql\\DSL\\all_(" + "$" + "{" + "1:left" + "}" + ", " + "$" + "{" + "2:operator" + "}" + ", " + "$" + "{" + "3:subquery" + "}" + ")"), boost: 10 }, { label: "alter", @@ -276,7 +276,7 @@ const dslFunctions = [ apply: snippet("\\Flow\\ETL\\DSL\\any(" + "$" + "{" + "1:values" + "}" + ")"), boost: 10 }, { - label: "any_sub_select", + label: "any_", type: "function", detail: "flow\u002Ddsl\u002Dhelpers", info: () => { @@ -291,7 +291,7 @@ const dslFunctions = [ ` return div }, - apply: snippet("\\Flow\\PostgreSql\\DSL\\any_sub_select(" + "$" + "{" + "1:left" + "}" + ", " + "$" + "{" + "2:operator" + "}" + ", " + "$" + "{" + "3:subquery" + "}" + ")"), + apply: snippet("\\Flow\\PostgreSql\\DSL\\any_(" + "$" + "{" + "1:left" + "}" + ", " + "$" + "{" + "2:operator" + "}" + ", " + "$" + "{" + "3:subquery" + "}" + ")"), boost: 10 }, { label: "append", @@ -1725,7 +1725,7 @@ const dslFunctions = [ apply: snippet("\\Flow\\PostgreSql\\DSL\\conditions()"), boost: 10 }, { - label: "cond_and", + label: "and_", type: "function", detail: "flow\u002Ddsl\u002Dhelpers", info: () => { @@ -1740,7 +1740,7 @@ const dslFunctions = [ ` return div }, - apply: snippet("\\Flow\\PostgreSql\\DSL\\cond_and(" + "$" + "{" + "1:conditions" + "}" + ")"), + apply: snippet("\\Flow\\PostgreSql\\DSL\\and_(" + "$" + "{" + "1:conditions" + "}" + ")"), boost: 10 }, { label: "cond_false", @@ -1761,7 +1761,7 @@ const dslFunctions = [ apply: snippet("\\Flow\\PostgreSql\\DSL\\cond_false()"), boost: 10 }, { - label: "cond_not", + label: "not_", type: "function", detail: "flow\u002Ddsl\u002Dhelpers", info: () => { @@ -1776,10 +1776,10 @@ const dslFunctions = [ ` return div }, - apply: snippet("\\Flow\\PostgreSql\\DSL\\cond_not(" + "$" + "{" + "1:condition" + "}" + ")"), + apply: snippet("\\Flow\\PostgreSql\\DSL\\not_(" + "$" + "{" + "1:condition" + "}" + ")"), boost: 10 }, { - label: "cond_or", + label: "or_", type: "function", detail: "flow\u002Ddsl\u002Dhelpers", info: () => { @@ -1794,7 +1794,7 @@ const dslFunctions = [ ` return div }, - apply: snippet("\\Flow\\PostgreSql\\DSL\\cond_or(" + "$" + "{" + "1:conditions" + "}" + ")"), + apply: snippet("\\Flow\\PostgreSql\\DSL\\or_(" + "$" + "{" + "1:conditions" + "}" + ")"), boost: 10 }, { label: "cond_true", @@ -4566,7 +4566,7 @@ const dslFunctions = [ apply: snippet("\\Flow\\PostgreSql\\DSL\\gt(" + "$" + "{" + "1:left" + "}" + ", " + "$" + "{" + "2:right" + "}" + ")"), boost: 10 }, { - label: "gte", + label: "ge", type: "function", detail: "flow\u002Ddsl\u002Dhelpers", info: () => { @@ -4581,7 +4581,7 @@ const dslFunctions = [ ` return div }, - apply: snippet("\\Flow\\PostgreSql\\DSL\\gte(" + "$" + "{" + "1:left" + "}" + ", " + "$" + "{" + "2:right" + "}" + ")"), + apply: snippet("\\Flow\\PostgreSql\\DSL\\ge(" + "$" + "{" + "1:left" + "}" + ", " + "$" + "{" + "2:right" + "}" + ")"), boost: 10 }, { label: "hash", @@ -4995,7 +4995,7 @@ const dslFunctions = [ apply: snippet("\\Flow\\ETL\\DSL\\int_schema(" + "$" + "{" + "1:name" + "}" + ", " + "$" + "{" + "2:nullable" + "}" + ", " + "$" + "{" + "3:metadata" + "}" + ")"), boost: 10 }, { - label: "is_distinct_from", + label: "distinct_from", type: "function", detail: "flow\u002Ddsl\u002Dhelpers", info: () => { @@ -5010,10 +5010,10 @@ const dslFunctions = [ ` return div }, - apply: snippet("\\Flow\\PostgreSql\\DSL\\is_distinct_from(" + "$" + "{" + "1:left" + "}" + ", " + "$" + "{" + "2:right" + "}" + ", " + "$" + "{" + "3:not" + "}" + ")"), + apply: snippet("\\Flow\\PostgreSql\\DSL\\distinct_from(" + "$" + "{" + "1:left" + "}" + ", " + "$" + "{" + "2:right" + "}" + ", " + "$" + "{" + "3:not" + "}" + ")"), boost: 10 }, { - label: "is_in", + label: "in_", type: "function", detail: "flow\u002Ddsl\u002Dhelpers", info: () => { @@ -5028,7 +5028,7 @@ const dslFunctions = [ ` return div }, - apply: snippet("\\Flow\\PostgreSql\\DSL\\is_in(" + "$" + "{" + "1:expr" + "}" + ", " + "$" + "{" + "2:values" + "}" + ")"), + apply: snippet("\\Flow\\PostgreSql\\DSL\\in_(" + "$" + "{" + "1:expr" + "}" + ", " + "$" + "{" + "2:values" + "}" + ")"), boost: 10 }, { label: "is_null", @@ -5634,7 +5634,7 @@ const dslFunctions = [ apply: snippet("\\Flow\\PostgreSql\\DSL\\lt(" + "$" + "{" + "1:left" + "}" + ", " + "$" + "{" + "2:right" + "}" + ")"), boost: 10 }, { - label: "lte", + label: "le", type: "function", detail: "flow\u002Ddsl\u002Dhelpers", info: () => { @@ -5649,7 +5649,7 @@ const dslFunctions = [ ` return div }, - apply: snippet("\\Flow\\PostgreSql\\DSL\\lte(" + "$" + "{" + "1:left" + "}" + ", " + "$" + "{" + "2:right" + "}" + ")"), + apply: snippet("\\Flow\\PostgreSql\\DSL\\le(" + "$" + "{" + "1:left" + "}" + ", " + "$" + "{" + "2:right" + "}" + ")"), boost: 10 }, { label: "manual_detector", @@ -6018,7 +6018,7 @@ const dslFunctions = [ apply: snippet("\\Flow\\Filesystem\\DSL\\native_local_filesystem()"), boost: 10 }, { - label: "neq", + label: "ne", type: "function", detail: "flow\u002Ddsl\u002Dhelpers", info: () => { @@ -6033,7 +6033,7 @@ const dslFunctions = [ ` return div }, - apply: snippet("\\Flow\\PostgreSql\\DSL\\neq(" + "$" + "{" + "1:left" + "}" + ", " + "$" + "{" + "2:right" + "}" + ")"), + apply: snippet("\\Flow\\PostgreSql\\DSL\\ne(" + "$" + "{" + "1:left" + "}" + ", " + "$" + "{" + "2:right" + "}" + ")"), boost: 10 }, { label: "not", diff --git a/web/landing/composer.json b/web/landing/composer.json index e15c705a9b..c366c8090c 100644 --- a/web/landing/composer.json +++ b/web/landing/composer.json @@ -99,7 +99,7 @@ "league/commonmark": "^2.4", "presta/sitemap-bundle": "^4.1", "symfony/mime": "^7.2", - "symfony/string": "^7.3" + "symfony/string": "^7.4" }, "require-dev": { "symfony/web-profiler-bundle": "^6.4", diff --git a/web/landing/resources/dsl.json b/web/landing/resources/dsl.json index 6e0adb5439..ee70a4daea 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":218,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_reading","option":"data_frame"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_writing","option":"overwrite"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEFsaWFzIGZvciBkYXRhX2ZyYW1lKCkgOiBGbG93LgogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":226,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_reading","option":"data_frame"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_writing","option":"overwrite"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":232,"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"},{"name":"filesystem","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":"TelemetryOptions","namespace":"Flow\\ETL\\Config\\Telemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":251,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"EXTRACTOR"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_reading","option":"data_frame"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_writing","option":"overwrite"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":258,"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}],"return_type":[{"name":"PathPartitionsExtractor","namespace":"Flow\\ETL\\Extractor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"EXTRACTOR"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\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":270,"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"}],"return_type":[{"name":"ArrayExtractor","namespace":"Flow\\ETL\\Extractor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"EXTRACTOR"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_reading","option":"array"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_reading","option":"data_frame"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBpdGVyYWJsZTxhcnJheTxtaXhlZD4+ICRhcnJheQogKiBAcGFyYW0gbnVsbHxTY2hlbWEgJHNjaGVtYSAtIEBkZXByZWNhdGVkIHVzZSB3aXRoU2NoZW1hKCkgbWV0aG9kIGluc3RlYWQKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":287,"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"}],"return_type":[{"name":"CacheExtractor","namespace":"Flow\\ETL\\Extractor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":303,"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\\ETL\\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":309,"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\\ETL\\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":315,"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}],"return_type":[{"name":"FilesExtractor","namespace":"Flow\\ETL\\Extractor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":321,"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\\Serializer\\NativePHPSerializer::..."}],"return_type":[{"name":"FilesystemCache","namespace":"Flow\\ETL\\Cache\\Implementation","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":330,"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\\ETL\\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":343,"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\\ETL\\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":349,"slug":"from-pipeline","name":"from_pipeline","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"pipeline","type":[{"name":"Pipeline","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":"PipelineExtractor","namespace":"Flow\\ETL\\Extractor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":355,"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\\ETL\\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":361,"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\\ETL\\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":370,"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\\ETL\\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-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\\ETL\\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":"to-callable","name":"to_callable","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"callable","type":[{"name":"callable","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"CallbackLoader","namespace":"Flow\\ETL\\Loader","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":394,"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\\ETL\\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":408,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"LOADER"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_writing","option":"array"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENvbnZlcnQgcm93cyB0byBhbiBhcnJheSBhbmQgc3RvcmUgdGhlbSBpbiBwYXNzZWQgYXJyYXkgdmFyaWFibGUuCiAqCiAqIEBwYXJhbSBhcnJheTxhcnJheS1rZXksIG1peGVkPiAkYXJyYXkKICoKICogQHBhcmFtLW91dCBhcnJheTxhcnJheTxtaXhlZD4+ICRhcnJheQogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":415,"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\\ETL\\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":421,"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\\ETL\\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":427,"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\\ETL\\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":433,"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\\ETL\\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":439,"slug":"to-transformation","name":"to_transformation","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"transformer","type":[{"name":"Transformer","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"Transformation","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"loader","type":[{"name":"Loader","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"TransformerLoader","namespace":"Flow\\ETL\\Loader","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":445,"slug":"to-branch","name":"to_branch","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"condition","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"loader","type":[{"name":"Loader","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"BranchingLoader","namespace":"Flow\\ETL\\Loader","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":451,"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\\ETL\\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":461,"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\\ETL\\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":470,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"TRANSFORMER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxzdHJpbmcsIHN0cmluZz4gJHJlbmFtZXMgTWFwIG9mIG9sZF9uYW1lID0+IG5ld19uYW1lCiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":479,"slug":"bool-entry","name":"bool_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":"value","type":[{"name":"bool","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gRW50cnk8P2Jvb2w+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":488,"slug":"boolean-entry","name":"boolean_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":"value","type":[{"name":"bool","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gRW50cnk8P2Jvb2w+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":497,"slug":"datetime-entry","name":"datetime_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":"value","type":[{"name":"DateTimeInterface","namespace":"","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":false,"is_nullable":true,"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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gRW50cnk8P1xEYXRlVGltZUludGVyZmFjZT4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":506,"slug":"time-entry","name":"time_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":"value","type":[{"name":"DateInterval","namespace":"","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":false,"is_nullable":true,"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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gRW50cnk8P1xEYXRlSW50ZXJ2YWw+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":515,"slug":"date-entry","name":"date_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":"value","type":[{"name":"DateTimeInterface","namespace":"","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":false,"is_nullable":true,"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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gRW50cnk8P1xEYXRlVGltZUludGVyZmFjZT4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":524,"slug":"int-entry","name":"int_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":"value","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gRW50cnk8P2ludD4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":533,"slug":"integer-entry","name":"integer_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":"value","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gRW50cnk8P2ludD4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":542,"slug":"enum-entry","name":"enum_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":"enum","type":[{"name":"UnitEnum","namespace":"","is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gRW50cnk8P1xVbml0RW51bT4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":551,"slug":"float-entry","name":"float_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":"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":"null","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gRW50cnk8P2Zsb2F0PgogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":562,"slug":"json-entry","name":"json_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":"data","type":[{"name":"Json","namespace":"Flow\\Types\\Value","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},{"name":"null","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBudWxsfGFycmF5PGFycmF5LWtleSwgbWl4ZWQ+fEpzb258c3RyaW5nICRkYXRhCiAqCiAqIEByZXR1cm4gRW50cnk8P0pzb24+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":575,"slug":"json-object-entry","name":"json_object_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":"data","type":[{"name":"Json","namespace":"Flow\\Types\\Value","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},{"name":"null","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBudWxsfGFycmF5PGFycmF5LWtleSwgbWl4ZWQ+fEpzb258c3RyaW5nICRkYXRhCiAqCiAqIEB0aHJvd3MgSW52YWxpZEFyZ3VtZW50RXhjZXB0aW9uCiAqCiAqIEByZXR1cm4gRW50cnk8P0pzb24+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":592,"slug":"str-entry","name":"str_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":"value","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gRW50cnk8P3N0cmluZz4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":610,"slug":"null-entry","name":"null_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":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFRoaXMgZnVuY3Rpb25zIGlzIGFuIGFsaWFzIGZvciBjcmVhdGluZyBzdHJpbmcgZW50cnkgZnJvbSBudWxsLgogKiBUaGUgbWFpbiBkaWZmZXJlbmNlIGJldHdlZW4gdXNpbmcgdGhpcyBmdW5jdGlvbiBhbiBzaW1wbHkgc3RyX2VudHJ5IHdpdGggc2Vjb25kIGFyZ3VtZW50IG51bGwKICogaXMgdGhhdCB0aGlzIGZ1bmN0aW9uIHdpbGwgYWxzbyBrZWVwIGEgbm90ZSBpbiB0aGUgbWV0YWRhdGEgdGhhdCB0eXBlIG1pZ2h0IG5vdCBiZSBmaW5hbC4KICogRm9yIGV4YW1wbGUgd2hlbiB3ZSBuZWVkIHRvIGd1ZXNzIGNvbHVtbiB0eXBlIGZyb20gcm93cyBiZWNhdXNlIHNjaGVtYSB3YXMgbm90IHByb3ZpZGVkLAogKiBhbmQgZ2l2ZW4gY29sdW1uIGluIHRoZSBmaXJzdCByb3cgaXMgbnVsbCwgaXQgbWlnaHQgc3RpbGwgY2hhbmdlIG9uY2Ugd2UgZ2V0IHRvIHRoZSBzZWNvbmQgcm93LgogKiBUaGF0IG1ldGFkYXRhIGlzIHVzZWQgdG8gZGV0ZXJtaW5lIGlmIHN0cmluZ19lbnRyeSB3YXMgY3JlYXRlZCBmcm9tIG51bGwgb3Igbm90LgogKgogKiBCeSBkZXNpZ24gZmxvdyBhc3N1bWVzIHdoZW4gZ3Vlc3NpbmcgY29sdW1uIHR5cGUgdGhhdCBudWxsIHdvdWxkIGJlIGEgc3RyaW5nICh0aGUgbW9zdCBmbGV4aWJsZSB0eXBlKS4KICoKICogQHJldHVybiBFbnRyeTw\/c3RyaW5nPgogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":619,"slug":"string-entry","name":"string_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":"value","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gRW50cnk8P3N0cmluZz4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":628,"slug":"uuid-entry","name":"uuid_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":"value","type":[{"name":"Uuid","namespace":"Flow\\Types\\Value","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":false,"is_nullable":true,"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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gRW50cnk8P1xGbG93XFR5cGVzXFZhbHVlXFV1aWQ+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":637,"slug":"xml-entry","name":"xml_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":"value","type":[{"name":"DOMDocument","namespace":"","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":false,"is_nullable":true,"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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gRW50cnk8P1xET01Eb2N1bWVudD4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":646,"slug":"xml-element-entry","name":"xml_element_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":"value","type":[{"name":"DOMElement","namespace":"","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":false,"is_nullable":true,"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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gRW50cnk8P1xET01FbGVtZW50PgogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":655,"slug":"html-entry","name":"html_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":"value","type":[{"name":"Dom\\HTMLDocument","namespace":null,"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":false,"is_nullable":true,"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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gRW50cnk8P0hUTUxEb2N1bWVudD4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":664,"slug":"html-element-entry","name":"html_element_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":"value","type":[{"name":"Dom\\HTMLElement","namespace":null,"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":false,"is_nullable":true,"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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gRW50cnk8P0hUTUxFbGVtZW50PgogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":673,"slug":"entries","name":"entries","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"entries","type":[{"name":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"Entries","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBFbnRyeTxtaXhlZD4gLi4uJGVudHJpZXMKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":687,"slug":"struct-entry","name":"struct_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":"value","type":[{"name":"array","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":"StructureType","namespace":"Flow\\Types\\Type\\Logical","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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSA\/YXJyYXk8c3RyaW5nLCBtaXhlZD4gJHZhbHVlCiAqIEBwYXJhbSBTdHJ1Y3R1cmVUeXBlPFQ+ICR0eXBlCiAqCiAqIEByZXR1cm4gRW50cnk8P2FycmF5PHN0cmluZywgVD4+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":701,"slug":"structure-entry","name":"structure_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":"value","type":[{"name":"array","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":"StructureType","namespace":"Flow\\Types\\Type\\Logical","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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSA\/YXJyYXk8c3RyaW5nLCBtaXhlZD4gJHZhbHVlCiAqIEBwYXJhbSBTdHJ1Y3R1cmVUeXBlPFQ+ICR0eXBlCiAqCiAqIEByZXR1cm4gRW50cnk8P2FycmF5PHN0cmluZywgVD4+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":715,"slug":"list-entry","name":"list_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":"value","type":[{"name":"array","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":"ListType","namespace":"Flow\\Types\\Type\\Logical","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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBudWxsfGxpc3Q8bWl4ZWQ+ICR2YWx1ZQogKiBAcGFyYW0gTGlzdFR5cGU8VD4gJHR5cGUKICoKICogQHJldHVybiBFbnRyeTxtaXhlZD4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":730,"slug":"map-entry","name":"map_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":"value","type":[{"name":"array","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null},{"name":"mapType","type":[{"name":"MapType","namespace":"Flow\\Types\\Type\\Logical","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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUS2V5IG9mIGFycmF5LWtleQogKiBAdGVtcGxhdGUgVFZhbHVlCiAqCiAqIEBwYXJhbSA\/YXJyYXk8YXJyYXkta2V5LCBtaXhlZD4gJHZhbHVlCiAqIEBwYXJhbSBNYXBUeXBlPFRLZXksIFRWYWx1ZT4gJG1hcFR5cGUKICoKICogQHJldHVybiBFbnRyeTw\/YXJyYXk8VEtleSwgVFZhbHVlPj4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":739,"slug":"row","name":"row","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"entry","type":[{"name":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"Row","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBFbnRyeTxtaXhlZD4gLi4uJGVudHJ5CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":745,"slug":"rows","name":"rows","namespace":"Flow\\ETL\\DSL","parameters":[{"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":755,"slug":"rows-partitioned","name":"rows_partitioned","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"rows","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":"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":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\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxSb3c+ICRyb3dzCiAqIEBwYXJhbSBhcnJheTxcRmxvd1xGaWxlc3lzdGVtXFBhcnRpdGlvbnxzdHJpbmc+fFBhcnRpdGlvbnMgJHBhcnRpdGlvbnMKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":764,"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":"EntryReference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":774,"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":"EntryReference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"columns","option":"create"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIEFuIGFsaWFzIGZvciBgcmVmYC4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":781,"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":"EntryReference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"columns","option":"create"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":787,"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\\ETL\\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":793,"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\\ETL\\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":799,"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\\ETL\\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":805,"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\\ETL\\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":811,"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\\ETL\\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":817,"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\\ETL\\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":826,"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\\ETL\\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":832,"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\\ETL\\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":841,"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\\ETL\\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":847,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":854,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"columns","option":"create"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":860,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"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":"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":872,"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":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":881,"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\\ETL\\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":887,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":896,"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\\ETL\\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":906,"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\\ETL\\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":915,"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\\ETL\\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":921,"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":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"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":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":927,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":933,"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":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"Sort","namespace":"Flow\\ETL\\Function\\ArraySort","is_nullable":false,"is_variadic":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":"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":946,"slug":"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":"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":"ArrayReverse","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":952,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":958,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":964,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":970,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":976,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":982,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":992,"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\\ETL\\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":1001,"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\\ETL\\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":1010,"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\\ETL\\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":1016,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"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":"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\\ETL\\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":1031,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"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":"count","name":"count","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"function","type":[{"name":"EntryReference","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\\ETL\\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":1050,"slug":"call","name":"call","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"callable","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"callable","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":"return_type","type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"CallUserFunc","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIENhbGxzIGEgdXNlci1kZWZpbmVkIGZ1bmN0aW9uIHdpdGggdGhlIGdpdmVuIHBhcmFtZXRlcnMuCiAqCiAqIEBwYXJhbSBjYWxsYWJsZXxTY2FsYXJGdW5jdGlvbiAkY2FsbGFibGUKICogQHBhcmFtIGFycmF5PG1peGVkPiAkcGFyYW1ldGVycwogKiBAcGFyYW0gbnVsbHxUeXBlPG1peGVkPiAkcmV0dXJuX3R5cGUKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1079,"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":"skip_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":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"entry_prefix","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":"ArrayUnpack","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxhcnJheS1rZXksIG1peGVkPnxTY2FsYXJGdW5jdGlvbiAkYXJyYXkKICogQHBhcmFtIGFycmF5PGFycmF5LWtleSwgbWl4ZWQ+fFNjYWxhckZ1bmN0aW9uICRza2lwX2tleXMKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1105,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIEV4cGFuZHMgZWFjaCB2YWx1ZSBpbnRvIGVudHJ5LCBpZiB0aGVyZSBhcmUgbW9yZSB0aGFuIG9uZSB2YWx1ZSwgbXVsdGlwbGUgcm93cyB3aWxsIGJlIGNyZWF0ZWQuCiAqIEFycmF5IGtleXMgYXJlIGlnbm9yZWQsIG9ubHkgdmFsdWVzIGFyZSB1c2VkIHRvIGNyZWF0ZSBuZXcgcm93cy4KICoKICogQmVmb3JlOgogKiAgICstLSstLS0tLS0tLS0tLS0tLS0tLS0tKwogKiAgIHxpZHwgICAgICAgICAgICAgIGFycmF5fAogKiAgICstLSstLS0tLS0tLS0tLS0tLS0tLS0tKwogKiAgIHwgMXx7ImEiOjEsImIiOjIsImMiOjN9fAogKiAgICstLSstLS0tLS0tLS0tLS0tLS0tLS0tKwogKgogKiBBZnRlcjoKICogICArLS0rLS0tLS0tLS0rCiAqICAgfGlkfGV4cGFuZGVkfAogKiAgICstLSstLS0tLS0tLSsKICogICB8IDF8ICAgICAgIDF8CiAqICAgfCAxfCAgICAgICAyfAogKiAgIHwgMXwgICAgICAgM3wKICogICArLS0rLS0tLS0tLS0rCiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1111,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"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":"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1123,"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},{"name":"null","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1129,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"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":"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"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":"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"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":"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1153,"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\\ETL\\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":1159,"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\\ETL\\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":1165,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1171,"slug":"to-timezone","name":"to_timezone","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"value","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"DateTimeInterface","namespace":"","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"timeZone","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"DateTimeZone","namespace":"","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ToTimeZone","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1177,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1183,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1189,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1195,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1201,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1207,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1213,"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":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_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":"Regex","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1219,"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":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_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":"RegexAll","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1225,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1231,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1237,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1243,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1254,"slug":"to-entry","name":"to_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":"data","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":"entryFactory","type":[{"name":"EntryFactory","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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxtaXhlZD4gJGRhdGEKICoKICogQHJldHVybiBFbnRyeTxtaXhlZD4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1265,"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":"entryFactory","type":[{"name":"EntryFactory","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"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":"[]"},{"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":"Row","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxhcnJheTxtaXhlZD4+fGFycmF5PG1peGVkfHN0cmluZz4gJGRhdGEKICogQHBhcmFtIGFycmF5PFBhcnRpdGlvbj58UGFydGl0aW9ucyAkcGFydGl0aW9ucwogKiBAcGFyYW0gbnVsbHxTY2hlbWEgJHNjaGVtYQogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1310,"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":"entryFactory","type":[{"name":"EntryFactory","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"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":"[]"},{"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":"Rows","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxhcnJheTxtaXhlZD4+fGFycmF5PG1peGVkfHN0cmluZz4gJGRhdGEKICogQHBhcmFtIGFycmF5PFBhcnRpdGlvbj58UGFydGl0aW9ucyAkcGFydGl0aW9ucwogKiBAcGFyYW0gbnVsbHxTY2hlbWEgJHNjaGVtYQogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1339,"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\\ETL\\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":1345,"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\\ETL\\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":1351,"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\\ETL\\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":1357,"slug":"average","name":"average","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"ref","type":[{"name":"EntryReference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"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\\ETL\\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":1363,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1369,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1375,"slug":"collect","name":"collect","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"ref","type":[{"name":"EntryReference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","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\\ETL\\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":1381,"slug":"string-agg","name":"string_agg","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"ref","type":[{"name":"EntryReference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"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\\ETL\\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":1387,"slug":"collect-unique","name":"collect_unique","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"ref","type":[{"name":"EntryReference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","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\\ETL\\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":1393,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1399,"slug":"sum","name":"sum","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"ref","type":[{"name":"EntryReference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Sum","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":1405,"slug":"first","name":"first","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"ref","type":[{"name":"EntryReference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","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\\ETL\\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":1411,"slug":"last","name":"last","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"ref","type":[{"name":"EntryReference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","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\\ETL\\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":1417,"slug":"max","name":"max","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"ref","type":[{"name":"EntryReference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","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\\ETL\\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":1423,"slug":"min","name":"min","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"ref","type":[{"name":"EntryReference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","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\\ETL\\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":1429,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1440,"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\\ETL\\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":1449,"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\\ETL\\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":1458,"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\\ETL\\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":1467,"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\\ETL\\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":1477,"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":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":1483,"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\\ETL\\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":1489,"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\\ETL\\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":1495,"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\\ETL\\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":1504,"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\\ETL\\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":1516,"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\\ETL\\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":1525,"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\\ETL\\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":1531,"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\\ETL\\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":"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\\ETL\\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":1546,"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\\ETL\\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":1552,"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\\ETL\\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":1558,"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\\ETL\\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":"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUS2V5IG9mIGFycmF5LWtleQogKiBAdGVtcGxhdGUgVFZhbHVlCiAqCiAqIEBwYXJhbSBNYXBUeXBlPFRLZXksIFRWYWx1ZT58VHlwZTxhcnJheTxUS2V5LCBUVmFsdWU+PiAkdHlwZQogKgogKiBAcmV0dXJuIE1hcERlZmluaXRpb248VEtleSwgVFZhbHVlPgogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1586,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBMaXN0VHlwZTxUPnxUeXBlPGxpc3Q8VD4+ICR0eXBlCiAqCiAqIEByZXR1cm4gTGlzdERlZmluaXRpb248VD4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1600,"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\\ETL\\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":1606,"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":"StringDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1612,"slug":"datetime-schema","name":"datetime_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"DateTimeDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":1618,"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\\ETL\\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":1624,"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\\ETL\\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":1630,"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\\ETL\\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":1636,"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\\ETL\\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":1642,"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\\ETL\\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":1648,"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\\ETL\\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":1654,"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\\ETL\\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":1667,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBTdHJ1Y3R1cmVUeXBlPFQ+fFR5cGU8YXJyYXk8c3RyaW5nLCBUPj4gJHR5cGUKICoKICogQHJldHVybiBTdHJ1Y3R1cmVEZWZpbml0aW9uPFQ+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1674,"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\\ETL\\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":1687,"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\\ETL\\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":1720,"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\\ETL\\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":1746,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1752,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1758,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1764,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1773,"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\\ETL\\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":1779,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1788,"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\\ETL\\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":1794,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1803,"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\\ETL\\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":1809,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"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":"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\\ETL\\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":1824,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1834,"slug":"execution-strict","name":"execution_strict","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"ExecutionMode","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEluIHRoaXMgbW9kZSwgZnVuY3Rpb25zIHRocm93cyBleGNlcHRpb25zIGlmIHRoZSBnaXZlbiBlbnRyeSBpcyBub3QgZm91bmQKICogb3IgcGFzc2VkIHBhcmFtZXRlcnMgYXJlIGludmFsaWQuCiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1843,"slug":"execution-lenient","name":"execution_lenient","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"ExecutionMode","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEluIHRoaXMgbW9kZSwgZnVuY3Rpb25zIHJldHVybnMgbnVsbHMgaW5zdGVhZCBvZiB0aHJvd2luZyBleGNlcHRpb25zLgogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1849,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1855,"slug":"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\\ETL\\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":1861,"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\\ETL\\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":1867,"slug":"compare-all","name":"compare_all","namespace":"Flow\\ETL\\DSL","parameters":[{"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\\ETL\\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":1873,"slug":"compare-any","name":"compare_any","namespace":"Flow\\ETL\\DSL","parameters":[{"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\\ETL\\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":"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"join","example":"join"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"join","example":"join_each"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxcRmxvd1xFVExcSm9pblxDb21wYXJpc29ufHN0cmluZz58Q29tcGFyaXNvbiAkY29tcGFyaXNvbnMKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1890,"slug":"compare-entries-by-name","name":"compare_entries_by_name","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"order","type":[{"name":"Order","namespace":"Flow\\ETL\\Transformer\\OrderEntries","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Transformer\\OrderEntries\\Order::..."}],"return_type":[{"name":"Comparator","namespace":"Flow\\ETL\\Transformer\\OrderEntries","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1896,"slug":"compare-entries-by-name-desc","name":"compare_entries_by_name_desc","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"Comparator","namespace":"Flow\\ETL\\Transformer\\OrderEntries","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1905,"slug":"compare-entries-by-type","name":"compare_entries_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":"Order","namespace":"Flow\\ETL\\Transformer\\OrderEntries","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Transformer\\OrderEntries\\Order::..."}],"return_type":[{"name":"Comparator","namespace":"Flow\\ETL\\Transformer\\OrderEntries","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxjbGFzcy1zdHJpbmc8RW50cnk8bWl4ZWQ+PiwgaW50PiAkcHJpb3JpdGllcwogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1914,"slug":"compare-entries-by-type-desc","name":"compare_entries_by_type_desc","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":"[...]"}],"return_type":[{"name":"Comparator","namespace":"Flow\\ETL\\Transformer\\OrderEntries","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxjbGFzcy1zdHJpbmc8RW50cnk8bWl4ZWQ+PiwgaW50PiAkcHJpb3JpdGllcwogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1923,"slug":"compare-entries-by-type-and-name","name":"compare_entries_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":"Order","namespace":"Flow\\ETL\\Transformer\\OrderEntries","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Transformer\\OrderEntries\\Order::..."}],"return_type":[{"name":"Comparator","namespace":"Flow\\ETL\\Transformer\\OrderEntries","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxjbGFzcy1zdHJpbmc8RW50cnk8bWl4ZWQ+PiwgaW50PiAkcHJpb3JpdGllcwogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1936,"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\\ETL\\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":1970,"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":"NativePHPRandomValueGenerator","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\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1976,"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":"NativePHPRandomValueGenerator","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\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1982,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1990,"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\\ETL\\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":2007,"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\\ETL\\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":2024,"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\\ETL\\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":2041,"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\\ETL\\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":2047,"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\\ETL\\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":2053,"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\\ETL\\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":"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\\ETL\\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":"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\\ETL\\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":2079,"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\\ETL\\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":2085,"slug":"retry-any-throwable","name":"retry_any_throwable","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"limit","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"AnyThrowable","namespace":"Flow\\ETL\\Retry\\RetryStrategy","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":2094,"slug":"retry-on-exception-types","name":"retry_on_exception_types","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"exception_types","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"limit","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"OnExceptionTypes","namespace":"Flow\\ETL\\Retry\\RetryStrategy","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxjbGFzcy1zdHJpbmc8XFRocm93YWJsZT4+ICRleGNlcHRpb25fdHlwZXMKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2100,"slug":"delay-linear","name":"delay_linear","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"delay","type":[{"name":"Duration","namespace":"Flow\\ETL\\Time","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"increment","type":[{"name":"Duration","namespace":"Flow\\ETL\\Time","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Linear","namespace":"Flow\\ETL\\Retry\\DelayFactory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":2106,"slug":"delay-exponential","name":"delay_exponential","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"base","type":[{"name":"Duration","namespace":"Flow\\ETL\\Time","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"multiplier","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"2"},{"name":"max_delay","type":[{"name":"Duration","namespace":"Flow\\ETL\\Time","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Exponential","namespace":"Flow\\ETL\\Retry\\DelayFactory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":2115,"slug":"delay-jitter","name":"delay_jitter","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"delay","type":[{"name":"DelayFactory","namespace":"Flow\\ETL\\Retry","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"jitter_factor","type":[{"name":"float","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Jitter","namespace":"Flow\\ETL\\Retry\\DelayFactory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBmbG9hdCAkaml0dGVyX2ZhY3RvciBhIHZhbHVlIGJldHdlZW4gMCBhbmQgMSByZXByZXNlbnRpbmcgdGhlIG1heGltdW0gcGVyY2VudGFnZSBvZiBqaXR0ZXIgdG8gYXBwbHkKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2121,"slug":"delay-fixed","name":"delay_fixed","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"delay","type":[{"name":"Duration","namespace":"Flow\\ETL\\Time","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Fixed","namespace":"Flow\\ETL\\Retry\\DelayFactory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":2127,"slug":"duration-seconds","name":"duration_seconds","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"seconds","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Duration","namespace":"Flow\\ETL\\Time","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":2133,"slug":"duration-milliseconds","name":"duration_milliseconds","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"milliseconds","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Duration","namespace":"Flow\\ETL\\Time","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":2139,"slug":"duration-microseconds","name":"duration_microseconds","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"microseconds","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Duration","namespace":"Flow\\ETL\\Time","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":2145,"slug":"duration-minutes","name":"duration_minutes","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"minutes","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Duration","namespace":"Flow\\ETL\\Time","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":2151,"slug":"write-with-retries","name":"write_with_retries","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"loader","type":[{"name":"Loader","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"retry_strategy","type":[{"name":"RetryStrategy","namespace":"Flow\\ETL\\Retry","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Retry\\RetryStrategy\\AnyThrowable::..."},{"name":"delay_factory","type":[{"name":"DelayFactory","namespace":"Flow\\ETL\\Retry","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Retry\\DelayFactory\\Fixed\\FixedMilliseconds::..."},{"name":"sleep","type":[{"name":"Sleep","namespace":"Flow\\ETL\\Time","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Time\\SystemSleep::..."}],"return_type":[{"name":"RetryLoader","namespace":"Flow\\ETL\\Loader","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":2161,"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\\ETL\\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":13,"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}],"return_type":[{"name":"AvroExtractor","namespace":"Flow\\ETL\\Adapter\\Avro\\FlixTech","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":21,"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"}],"return_type":[{"name":"AvroLoader","namespace":"Flow\\ETL\\Adapter\\Avro\\FlixTech","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":14,"slug":"bar-chart","name":"bar_chart","namespace":"Flow\\ETL\\Adapter\\ChartJS","parameters":[{"name":"label","type":[{"name":"EntryReference","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\\ETL\\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":20,"slug":"line-chart","name":"line_chart","namespace":"Flow\\ETL\\Adapter\\ChartJS","parameters":[{"name":"label","type":[{"name":"EntryReference","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\\ETL\\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":26,"slug":"pie-chart","name":"pie_chart","namespace":"Flow\\ETL\\Adapter\\ChartJS","parameters":[{"name":"label","type":[{"name":"EntryReference","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\\ETL\\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":32,"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\\ETL\\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":43,"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"}],"return_type":[{"name":"ChartJSLoader","namespace":"Flow\\ETL\\Adapter\\ChartJS","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":71,"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\\ETL\\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":25,"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":"1000"},{"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":"CSVExtractor","namespace":"Flow\\ETL\\Adapter\\CSV","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CSV","type":"EXTRACTOR"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_reading","option":"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":70,"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'"}],"return_type":[{"name":"CSVLoader","namespace":"Flow\\ETL\\Adapter\\CSV","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":95,"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\\ETL\\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":36,"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\\ETL\\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":56,"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\\ETL\\Attribute","arguments":{"module":"DOCTRINE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBDb25uZWN0aW9uICRjb25uZWN0aW9uCiAqIEBwYXJhbSBzdHJpbmd8VGFibGUgJHRhYmxlCiAqIEBwYXJhbSBhcnJheTxPcmRlckJ5PnxPcmRlckJ5ICRvcmRlcl9ieQogKiBAcGFyYW0gaW50ICRwYWdlX3NpemUKICogQHBhcmFtIG51bGx8aW50ICRtYXhpbXVtCiAqCiAqIEB0aHJvd3MgSW52YWxpZEFyZ3VtZW50RXhjZXB0aW9uCiAqLw=="},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":83,"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\\ETL\\Attribute","arguments":{"module":"DOCTRINE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBDb25uZWN0aW9uICRjb25uZWN0aW9uCiAqIEBwYXJhbSBpbnQgJHBhZ2Vfc2l6ZQogKiBAcGFyYW0gbnVsbHxpbnQgJG1heGltdW0gLSBtYXhpbXVtIGNhbiBhbHNvIGJlIHRha2VuIGZyb20gYSBxdWVyeSBidWlsZGVyLCAkbWF4aW11bSBob3dldmVyIGlzIHVzZWQgcmVnYXJkbGVzcyBvZiB0aGUgcXVlcnkgYnVpbGRlciBpZiBpdCdzIHNldAogKiBAcGFyYW0gaW50ICRvZmZzZXQgLSBvZmZzZXQgY2FuIGFsc28gYmUgdGFrZW4gZnJvbSBhIHF1ZXJ5IGJ1aWxkZXIsICRvZmZzZXQgaG93ZXZlciBpcyB1c2VkIHJlZ2FyZGxlc3Mgb2YgdGhlIHF1ZXJ5IGJ1aWxkZXIgaWYgaXQncyBzZXQgdG8gbm9uIDAgdmFsdWUKICov"},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":104,"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\\ETL\\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\\ETL\\Attribute","arguments":{"module":"DOCTRINE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBudWxsfFBhcmFtZXRlcnNTZXQgJHBhcmFtZXRlcnNfc2V0IC0gZWFjaCBvbmUgcGFyYW1ldGVycyBhcnJheSB3aWxsIGJlIGV2YWx1YXRlZCBhcyBuZXcgcXVlcnkKICogQHBhcmFtIGFycmF5PGludHxzdHJpbmcsIERiYWxBcnJheVR5cGV8RGJhbFBhcmFtZXRlclR5cGV8RGJhbFR5cGV8aW50fHN0cmluZz4gJHR5cGVzCiAqLw=="},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":147,"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\\ETL\\Attribute","arguments":{"module":"DOCTRINE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBkZXByZWNhdGVkIHVzZSBmcm9tX2RiYWxfcXVlcmllcygpIGluc3RlYWQKICoKICogQHBhcmFtIG51bGx8UGFyYW1ldGVyc1NldCAkcGFyYW1ldGVyc19zZXQgLSBlYWNoIG9uZSBwYXJhbWV0ZXJzIGFycmF5IHdpbGwgYmUgZXZhbHVhdGVkIGFzIG5ldyBxdWVyeQogKiBAcGFyYW0gYXJyYXk8aW50fHN0cmluZywgRGJhbEFycmF5VHlwZXxEYmFsUGFyYW1ldGVyVHlwZXxEYmFsVHlwZXxpbnR8c3RyaW5nPiAkdHlwZXMKICov"},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":161,"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\\ETL\\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":182,"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\\ETL\\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":208,"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\\ETL\\Attribute","arguments":{"module":"DOCTRINE","type":"LOADER"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_writing","option":"database_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":228,"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\\ETL\\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":248,"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\\ETL\\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":265,"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\\ETL\\Attribute","arguments":{"module":"DOCTRINE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENvbnZlcnRzIGEgRmxvd1xFVExcU2NoZW1hIHRvIGEgRG9jdHJpbmVcREJBTFxTY2hlbWFcVGFibGUuCiAqCiAqIEBwYXJhbSBTY2hlbWEgJHNjaGVtYQogKiBAcGFyYW0gYXJyYXk8YXJyYXkta2V5LCBtaXhlZD4gJHRhYmxlX29wdGlvbnMKICogQHBhcmFtIGFycmF5PGNsYXNzLXN0cmluZzxcRmxvd1xUeXBlc1xUeXBlPG1peGVkPj4sIGNsYXNzLXN0cmluZzxcRG9jdHJpbmVcREJBTFxUeXBlc1xUeXBlPj4gJHR5cGVzX21hcAogKi8="},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":278,"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\\ETL\\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":289,"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\\ETL\\Attribute","arguments":{"module":"DOCTRINE","type":"HELPER"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_writing","option":"database_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":298,"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\\ETL\\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":308,"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\\ETL\\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":318,"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\\ETL\\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":339,"slug":"to-dbal-transaction","name":"to_dbal_transaction","namespace":"Flow\\ETL\\Adapter\\Doctrine","parameters":[{"name":"connection","type":[{"name":"Connection","namespace":"Doctrine\\DBAL","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"loaders","type":[{"name":"Loader","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"TransactionalDbalLoader","namespace":"Flow\\ETL\\Adapter\\Doctrine","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"DOCTRINE","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEV4ZWN1dGUgbXVsdGlwbGUgbG9hZGVycyB3aXRoaW4gYSBkYXRhYmFzZSB0cmFuc2FjdGlvbi4KICogRWFjaCBiYXRjaCBvZiByb3dzIHdpbGwgYmUgcHJvY2Vzc2VkIGluIGl0cyBvd24gdHJhbnNhY3Rpb24uCiAqIElmIGFueSBsb2FkZXIgZmFpbHMsIHRoZSBlbnRpcmUgYmF0Y2ggd2lsbCBiZSByb2xsZWQgYmFjay4KICoKICogQHBhcmFtIGFycmF5PHN0cmluZywgbWl4ZWQ+fENvbm5lY3Rpb24gJGNvbm5lY3Rpb24KICogQHBhcmFtIExvYWRlciAuLi4kbG9hZGVycyAtIExvYWRlcnMgdG8gZXhlY3V0ZSB3aXRoaW4gdGhlIHRyYW5zYWN0aW9uCiAqCiAqIEB0aHJvd3MgSW52YWxpZEFyZ3VtZW50RXhjZXB0aW9uCiAqLw=="},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":349,"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},{"name":"int","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\\ETL\\Attribute","arguments":{"module":"DOCTRINE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":355,"slug":"pagination-key-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},{"name":"int","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\\ETL\\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":361,"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\\ETL\\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":18,"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}],"return_type":[{"name":"ExcelExtractor","namespace":"Flow\\ETL\\Adapter\\Excel","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":25,"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}],"return_type":[{"name":"ExcelLoader","namespace":"Flow\\ETL\\Adapter\\Excel","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":31,"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\\ETL\\Attribute","arguments":{"module":"EXCEL","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-elasticsearch\/src\/Flow\/ETL\/Adapter\/Elasticsearch\/functions.php","start_line_in_file":36,"slug":"to-es-bulk-index","name":"to_es_bulk_index","namespace":"Flow\\ETL\\Adapter\\Elasticsearch","parameters":[{"name":"config","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":"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},{"name":"id_factory","type":[{"name":"IdFactory","namespace":"Flow\\ETL\\Adapter\\Elasticsearch","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":"ElasticsearchLoader","namespace":"Flow\\ETL\\Adapter\\Elasticsearch\\ElasticsearchPHP","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"ELASTIC_SEARCH","type":"LOADER"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_writing","option":"elasticsearch"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIGh0dHBzOi8vd3d3LmVsYXN0aWMuY28vZ3VpZGUvZW4vZWxhc3RpY3NlYXJjaC9yZWZlcmVuY2UvbWFzdGVyL2RvY3MtYnVsay5odG1sLgogKgogKiBJbiBvcmRlciB0byBjb250cm9sIHRoZSBzaXplIG9mIHRoZSBzaW5nbGUgcmVxdWVzdCwgdXNlIERhdGFGcmFtZTo6Y2h1bmtTaXplKCkgbWV0aG9kIGp1c3QgYmVmb3JlIGNhbGxpbmcgRGF0YUZyYW1lOjpsb2FkKCkuCiAqCiAqIEBwYXJhbSBhcnJheXsKICogIGhvc3RzPzogYXJyYXk8c3RyaW5nPiwKICogIGNvbm5lY3Rpb25QYXJhbXM\/OiBhcnJheTxtaXhlZD4sCiAqICByZXRyaWVzPzogaW50LAogKiAgc25pZmZPblN0YXJ0PzogYm9vbCwKICogIHNzbENlcnQ\/OiBhcnJheTxzdHJpbmc+LAogKiAgc3NsS2V5PzogYXJyYXk8c3RyaW5nPiwKICogIHNzbFZlcmlmaWNhdGlvbj86IGJvb2x8c3RyaW5nLAogKiAgZWxhc3RpY01ldGFIZWFkZXI\/OiBib29sLAogKiAgaW5jbHVkZVBvcnRJbkhvc3RIZWFkZXI\/OiBib29sCiAqIH0gJGNvbmZpZwogKiBAcGFyYW0gc3RyaW5nICRpbmRleAogKiBAcGFyYW0gSWRGYWN0b3J5ICRpZF9mYWN0b3J5CiAqIEBwYXJhbSBhcnJheTxtaXhlZD4gJHBhcmFtZXRlcnMgLSBodHRwczovL3d3dy5lbGFzdGljLmNvL2d1aWRlL2VuL2VsYXN0aWNzZWFyY2gvcmVmZXJlbmNlL21hc3Rlci9kb2NzLWJ1bGsuaHRtbCAtIEBkZXByZWNhdGVkIHVzZSB3aXRoUGFyYW1ldGVycyBtZXRob2QgaW5zdGVhZAogKi8="},{"repository_path":"src\/adapter\/etl-adapter-elasticsearch\/src\/Flow\/ETL\/Adapter\/Elasticsearch\/functions.php","start_line_in_file":47,"slug":"entry-id-factory","name":"entry_id_factory","namespace":"Flow\\ETL\\Adapter\\Elasticsearch","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}],"return_type":[{"name":"IdFactory","namespace":"Flow\\ETL\\Adapter\\Elasticsearch","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"ELASTIC_SEARCH","type":"HELPER"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_writing","option":"elasticsearch"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-elasticsearch\/src\/Flow\/ETL\/Adapter\/Elasticsearch\/functions.php","start_line_in_file":53,"slug":"hash-id-factory","name":"hash_id_factory","namespace":"Flow\\ETL\\Adapter\\Elasticsearch","parameters":[{"name":"entry_names","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":"IdFactory","namespace":"Flow\\ETL\\Adapter\\Elasticsearch","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"ELASTIC_SEARCH","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-elasticsearch\/src\/Flow\/ETL\/Adapter\/Elasticsearch\/functions.php","start_line_in_file":79,"slug":"to-es-bulk-update","name":"to_es_bulk_update","namespace":"Flow\\ETL\\Adapter\\Elasticsearch","parameters":[{"name":"config","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":"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},{"name":"id_factory","type":[{"name":"IdFactory","namespace":"Flow\\ETL\\Adapter\\Elasticsearch","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":"ElasticsearchLoader","namespace":"Flow\\ETL\\Adapter\\Elasticsearch\\ElasticsearchPHP","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"ELASTIC_SEARCH","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqICBodHRwczovL3d3dy5lbGFzdGljLmNvL2d1aWRlL2VuL2VsYXN0aWNzZWFyY2gvcmVmZXJlbmNlL21hc3Rlci9kb2NzLWJ1bGsuaHRtbC4KICoKICogSW4gb3JkZXIgdG8gY29udHJvbCB0aGUgc2l6ZSBvZiB0aGUgc2luZ2xlIHJlcXVlc3QsIHVzZSBEYXRhRnJhbWU6OmNodW5rU2l6ZSgpIG1ldGhvZCBqdXN0IGJlZm9yZSBjYWxsaW5nIERhdGFGcmFtZTo6bG9hZCgpLgogKgogKiBAcGFyYW0gYXJyYXl7CiAqICBob3N0cz86IGFycmF5PHN0cmluZz4sCiAqICBjb25uZWN0aW9uUGFyYW1zPzogYXJyYXk8bWl4ZWQ+LAogKiAgcmV0cmllcz86IGludCwKICogIHNuaWZmT25TdGFydD86IGJvb2wsCiAqICBzc2xDZXJ0PzogYXJyYXk8c3RyaW5nPiwKICogIHNzbEtleT86IGFycmF5PHN0cmluZz4sCiAqICBzc2xWZXJpZmljYXRpb24\/OiBib29sfHN0cmluZywKICogIGVsYXN0aWNNZXRhSGVhZGVyPzogYm9vbCwKICogIGluY2x1ZGVQb3J0SW5Ib3N0SGVhZGVyPzogYm9vbAogKiB9ICRjb25maWcKICogQHBhcmFtIHN0cmluZyAkaW5kZXgKICogQHBhcmFtIElkRmFjdG9yeSAkaWRfZmFjdG9yeQogKiBAcGFyYW0gYXJyYXk8bWl4ZWQ+ICRwYXJhbWV0ZXJzIC0gaHR0cHM6Ly93d3cuZWxhc3RpYy5jby9ndWlkZS9lbi9lbGFzdGljc2VhcmNoL3JlZmVyZW5jZS9tYXN0ZXIvZG9jcy1idWxrLmh0bWwgLSBAZGVwcmVjYXRlZCB1c2Ugd2l0aFBhcmFtZXRlcnMgbWV0aG9kIGluc3RlYWQKICov"},{"repository_path":"src\/adapter\/etl-adapter-elasticsearch\/src\/Flow\/ETL\/Adapter\/Elasticsearch\/functions.php","start_line_in_file":95,"slug":"es-hits-to-rows","name":"es_hits_to_rows","namespace":"Flow\\ETL\\Adapter\\Elasticsearch","parameters":[{"name":"source","type":[{"name":"DocumentDataSource","namespace":"Flow\\ETL\\Adapter\\Elasticsearch\\ElasticsearchPHP","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Adapter\\Elasticsearch\\ElasticsearchPHP\\DocumentDataSource::..."}],"return_type":[{"name":"HitsIntoRowsTransformer","namespace":"Flow\\ETL\\Adapter\\Elasticsearch\\ElasticsearchPHP","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"ELASTIC_SEARCH","type":"HELPER"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_writing","option":"elasticsearch"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFRyYW5zZm9ybXMgZWxhc3RpY3NlYXJjaCByZXN1bHRzIGludG8gY2xlYXIgRmxvdyBSb3dzIHVzaW5nIFsnaGl0cyddWydoaXRzJ11beF1bJ19zb3VyY2UnXS4KICoKICogQHJldHVybiBIaXRzSW50b1Jvd3NUcmFuc2Zvcm1lcgogKi8="},{"repository_path":"src\/adapter\/etl-adapter-elasticsearch\/src\/Flow\/ETL\/Adapter\/Elasticsearch\/functions.php","start_line_in_file":124,"slug":"from-es","name":"from_es","namespace":"Flow\\ETL\\Adapter\\Elasticsearch","parameters":[{"name":"config","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":"parameters","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":"pit_params","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":"ElasticsearchExtractor","namespace":"Flow\\ETL\\Adapter\\Elasticsearch\\ElasticsearchPHP","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"ELASTIC_SEARCH","type":"EXTRACTOR"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_reading","option":"elasticsearch"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEV4dHJhY3RvciB3aWxsIGF1dG9tYXRpY2FsbHkgdHJ5IHRvIGl0ZXJhdGUgb3ZlciB3aG9sZSBpbmRleCB1c2luZyBvbmUgb2YgdGhlIHR3byBpdGVyYXRpb24gbWV0aG9kczouCiAqCiAqIC0gZnJvbS9zaXplCiAqIC0gc2VhcmNoX2FmdGVyCiAqCiAqIFNlYXJjaCBhZnRlciBpcyBzZWxlY3RlZCB3aGVuIHlvdSBwcm92aWRlIGRlZmluZSBzb3J0IHBhcmFtZXRlcnMgaW4gcXVlcnksIG90aGVyd2lzZSBpdCB3aWxsIGZhbGxiYWNrIHRvIGZyb20vc2l6ZS4KICoKICogQHBhcmFtIGFycmF5ewogKiAgaG9zdHM\/OiBhcnJheTxzdHJpbmc+LAogKiAgY29ubmVjdGlvblBhcmFtcz86IGFycmF5PG1peGVkPiwKICogIHJldHJpZXM\/OiBpbnQsCiAqICBzbmlmZk9uU3RhcnQ\/OiBib29sLAogKiAgc3NsQ2VydD86IGFycmF5PHN0cmluZz4sCiAqICBzc2xLZXk\/OiBhcnJheTxzdHJpbmc+LAogKiAgc3NsVmVyaWZpY2F0aW9uPzogYm9vbHxzdHJpbmcsCiAqICBlbGFzdGljTWV0YUhlYWRlcj86IGJvb2wsCiAqICBpbmNsdWRlUG9ydEluSG9zdEhlYWRlcj86IGJvb2wKICogfSAkY29uZmlnCiAqIEBwYXJhbSBhcnJheTxtaXhlZD4gJHBhcmFtZXRlcnMgLSBodHRwczovL3d3dy5lbGFzdGljLmNvL2d1aWRlL2VuL2VsYXN0aWNzZWFyY2gvcmVmZXJlbmNlL21hc3Rlci9zZWFyY2gtc2VhcmNoLmh0bWwKICogQHBhcmFtID9hcnJheTxtaXhlZD4gJHBpdF9wYXJhbXMgLSB3aGVuIHVzZWQgZXh0cmFjdG9yIHdpbGwgY3JlYXRlIHBvaW50IGluIHRpbWUgdG8gc3RhYmlsaXplIHNlYXJjaCByZXN1bHRzLiBQb2ludCBpbiB0aW1lIGlzIGF1dG9tYXRpY2FsbHkgY2xvc2VkIHdoZW4gbGFzdCBlbGVtZW50IGlzIGV4dHJhY3RlZC4gaHR0cHM6Ly93d3cuZWxhc3RpYy5jby9ndWlkZS9lbi9lbGFzdGljc2VhcmNoL3JlZmVyZW5jZS9tYXN0ZXIvcG9pbnQtaW4tdGltZS1hcGkuaHRtbCAtIEBkZXByZWNhdGVkIHVzZSB3aXRoUG9pbnRJblRpbWUgbWV0aG9kIGluc3RlYWQKICov"},{"repository_path":"src\/adapter\/etl-adapter-google-sheet\/src\/Flow\/ETL\/Adapter\/GoogleSheet\/functions.php","start_line_in_file":20,"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\\ETL\\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":57,"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\\ETL\\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":15,"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}],"return_type":[{"name":"PsrHttpClientDynamicExtractor","namespace":"Flow\\ETL\\Adapter\\Http","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":29,"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}],"return_type":[{"name":"PsrHttpClientStaticExtractor","namespace":"Flow\\ETL\\Adapter\\Http","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"HTTP","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBpdGVyYWJsZTxSZXF1ZXN0SW50ZXJmYWNlPiAkcmVxdWVzdHMKICov"},{"repository_path":"src\/adapter\/etl-adapter-json\/src\/Flow\/ETL\/Adapter\/JSON\/functions.php","start_line_in_file":20,"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"}],"return_type":[{"name":"JsonExtractor","namespace":"Flow\\ETL\\Adapter\\JSON\\JSONMachine","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"JSON","type":"EXTRACTOR"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_reading","option":"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":45,"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}],"return_type":[{"name":"JsonLinesExtractor","namespace":"Flow\\ETL\\Adapter\\JSON\\JSONMachine","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"JSON","type":"EXTRACTOR"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_reading","option":"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":60,"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"}],"return_type":[{"name":"JsonLoader","namespace":"Flow\\ETL\\Adapter\\JSON","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":80,"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}],"return_type":[{"name":"JsonLinesLoader","namespace":"Flow\\ETL\\Adapter\\JSON","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"JSON","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFVzZWQgdG8gd3JpdGUgdG8gYSBKU09OIGxpbmVzIGh0dHBzOi8vanNvbmxpbmVzLm9yZy8gZm9ybWF0dGVkIGZpbGUuCiAqCiAqIEBwYXJhbSBQYXRofHN0cmluZyAkcGF0aAogKgogKiBAcmV0dXJuIEpzb25MaW5lc0xvYWRlcgogKi8="},{"repository_path":"src\/adapter\/etl-adapter-parquet\/src\/Flow\/ETL\/Adapter\/Parquet\/functions.php","start_line_in_file":28,"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"}],"return_type":[{"name":"ParquetExtractor","namespace":"Flow\\ETL\\Adapter\\Parquet","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PARQUET","type":"EXTRACTOR"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_reading","option":"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":58,"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"}],"return_type":[{"name":"ParquetLoader","namespace":"Flow\\ETL\\Adapter\\Parquet","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PARQUET","type":"LOADER"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_writing","option":"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":86,"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\\ETL\\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":94,"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\\ETL\\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":100,"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\\ETL\\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":106,"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\\ETL\\Attribute","arguments":{"module":"PARQUET","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":15,"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}],"return_type":[{"name":"TextExtractor","namespace":"Flow\\ETL\\Adapter\\Text","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":30,"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'"}],"return_type":[{"name":"Loader","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TEXT","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBQYXRofHN0cmluZyAkcGF0aAogKiBAcGFyYW0gc3RyaW5nICRuZXdfbGluZV9zZXBhcmF0b3IgLSBkZWZhdWx0IFBIUF9FT0wgLSBAZGVwcmVjYXRlZCB1c2Ugd2l0aE5ld0xpbmVTZXBhcmF0b3IgbWV0aG9kIGluc3RlYWQKICoKICogQHJldHVybiBMb2FkZXIKICov"},{"repository_path":"src\/adapter\/etl-adapter-xml\/src\/Flow\/ETL\/Adapter\/XML\/functions.php","start_line_in_file":34,"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":"''"}],"return_type":[{"name":"XMLParserExtractor","namespace":"Flow\\ETL\\Adapter\\XML","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"XML","type":"EXTRACTOR"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_reading","option":"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":50,"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\\DOMDocumentWriter::..."}],"return_type":[{"name":"XMLLoader","namespace":"Flow\\ETL\\Adapter\\XML\\Loader","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":23,"slug":"protocol","name":"protocol","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":"Protocol","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":29,"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\\ETL\\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":35,"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\\ETL\\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":54,"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\\ETL\\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":67,"slug":"path-stdout","name":"path_stdout","namespace":"Flow\\Filesystem\\DSL","parameters":[{"name":"options","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":"Path","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHBhdGggdG8gcGhwIHN0ZG91dCBzdHJlYW0uCiAqCiAqIEBwYXJhbSBudWxsfGFycmF5eydzdHJlYW0nOiAnb3V0cHV0J3wnc3RkZXJyJ3wnc3Rkb3V0J30gJG9wdGlvbnMKICoKICogQHJldHVybiBQYXRoCiAqLw=="},{"repository_path":"src\/lib\/filesystem\/src\/Flow\/Filesystem\/DSL\/functions.php","start_line_in_file":81,"slug":"path-memory","name":"path_memory","namespace":"Flow\\Filesystem\\DSL","parameters":[{"name":"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":"options","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":"Path","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHBhdGggdG8gcGhwIG1lbW9yeSBzdHJlYW0uCiAqCiAqIEBwYXJhbSBzdHJpbmcgJHBhdGggLSBkZWZhdWx0ID0gJycgLSBwYXRoIGlzIHVzZWQgYXMgYW4gaWRlbnRpZmllciBpbiBtZW1vcnkgZmlsZXN5c3RlbSwgc28gd2UgY2FuIHdyaXRlIG11bHRpcGxlIGZpbGVzIHRvIG1lbW9yeSBhdCBvbmNlLCBlYWNoIHBhdGggaXMgYSBuZXcgaGFuZGxlCiAqIEBwYXJhbSBudWxsfGFycmF5eydzdHJlYW0nOiAnbWVtb3J5J3wndGVtcCd9ICRvcHRpb25zIC0gd2hlbiBub3RoaW5nIGlzIHByb3ZpZGVkLCAndGVtcCcgc3RyZWFtIGlzIHVzZWQgYnkgZGVmYXVsdAogKgogKiBAcmV0dXJuIFBhdGgKICov"},{"repository_path":"src\/lib\/filesystem\/src\/Flow\/Filesystem\/DSL\/functions.php","start_line_in_file":92,"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\\ETL\\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":98,"slug":"native-local-filesystem","name":"native_local_filesystem","namespace":"Flow\\Filesystem\\DSL","parameters":[],"return_type":[{"name":"NativeLocalFilesystem","namespace":"Flow\\Filesystem\\Local","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":108,"slug":"stdout-filesystem","name":"stdout_filesystem","namespace":"Flow\\Filesystem\\DSL","parameters":[],"return_type":[{"name":"StdOutFilesystem","namespace":"Flow\\Filesystem\\Local","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":117,"slug":"memory-filesystem","name":"memory_filesystem","namespace":"Flow\\Filesystem\\DSL","parameters":[],"return_type":[{"name":"MemoryFilesystem","namespace":"Flow\\Filesystem\\Local","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":128,"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\\ETL\\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":144,"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\\ETL\\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":155,"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\\ETL\\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":170,"slug":"filesystem-telemetry-options","name":"filesystem_telemetry_options","namespace":"Flow\\Filesystem\\DSL","parameters":[{"name":"traceStreams","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"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"}],"return_type":[{"name":"FilesystemTelemetryOptions","namespace":"Flow\\Filesystem\\Telemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBvcHRpb25zIGZvciBmaWxlc3lzdGVtIHRlbGVtZXRyeS4KICoKICogQHBhcmFtIGJvb2wgJHRyYWNlU3RyZWFtcyBDcmVhdGUgYSBzaW5nbGUgc3BhbiBwZXIgc3RyZWFtIGxpZmVjeWNsZSAoZGVmYXVsdDogT04pCiAqIEBwYXJhbSBib29sICRjb2xsZWN0TWV0cmljcyBDb2xsZWN0IG1ldHJpY3MgZm9yIGJ5dGVzL29wZXJhdGlvbiBjb3VudHMgKGRlZmF1bHQ6IE9OKQogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":56,"slug":"type-structure","name":"type_structure","namespace":"Flow\\Types\\DSL","parameters":[{"name":"elements","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"optional_elements","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"allow_extra","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"StructureType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBhcnJheTxzdHJpbmcsIFR5cGU8VD4+ICRlbGVtZW50cwogKiBAcGFyYW0gYXJyYXk8c3RyaW5nLCBUeXBlPFQ+PiAkb3B0aW9uYWxfZWxlbWVudHMKICoKICogQHJldHVybiBTdHJ1Y3R1cmVUeXBlPFQ+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":73,"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":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqIEB0ZW1wbGF0ZSBUCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBUeXBlPFQ+ICRmaXJzdAogKiBAcGFyYW0gVHlwZTxUPiAkc2Vjb25kCiAqIEBwYXJhbSBUeXBlPFQ+IC4uLiR0eXBlcwogKgogKiBAcmV0dXJuIFR5cGU8VD4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":94,"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":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBUeXBlPFQ+ICRmaXJzdAogKiBAcGFyYW0gVHlwZTxUPiAkc2Vjb25kCiAqIEBwYXJhbSBUeXBlPFQ+IC4uLiR0eXBlcwogKgogKiBAcmV0dXJuIFR5cGU8VD4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":109,"slug":"type-numeric-string","name":"type_numeric_string","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxudW1lcmljLXN0cmluZz4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":122,"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":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBUeXBlPFQ+ICR0eXBlCiAqCiAqIEByZXR1cm4gVHlwZTxUPgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":133,"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\\ETL\\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":144,"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\\ETL\\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":166,"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\\ETL\\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":179,"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\\ETL\\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":192,"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\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBUeXBlPFQ+ICRlbGVtZW50CiAqCiAqIEByZXR1cm4gTGlzdFR5cGU8VD4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":207,"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\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUS2V5IG9mIGFycmF5LWtleQogKiBAdGVtcGxhdGUgVFZhbHVlCiAqCiAqIEBwYXJhbSBUeXBlPFRLZXk+ICRrZXlfdHlwZQogKiBAcGFyYW0gVHlwZTxUVmFsdWU+ICR2YWx1ZV90eXBlCiAqCiAqIEByZXR1cm4gTWFwVHlwZTxUS2V5LCBUVmFsdWU+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":216,"slug":"type-json","name":"type_json","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxKc29uPgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":225,"slug":"type-datetime","name":"type_datetime","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxcRGF0ZVRpbWVJbnRlcmZhY2U+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":234,"slug":"type-date","name":"type_date","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxcRGF0ZVRpbWVJbnRlcmZhY2U+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":243,"slug":"type-time","name":"type_time","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxcRGF0ZUludGVydmFsPgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":252,"slug":"type-time-zone","name":"type_time_zone","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxcRGF0ZVRpbWVab25lPgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":261,"slug":"type-xml","name":"type_xml","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxcRE9NRG9jdW1lbnQ+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":270,"slug":"type-xml-element","name":"type_xml_element","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxcRE9NRWxlbWVudD4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":279,"slug":"type-uuid","name":"type_uuid","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxVdWlkPgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":288,"slug":"type-integer","name":"type_integer","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxpbnQ+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":297,"slug":"type-string","name":"type_string","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxzdHJpbmc+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":306,"slug":"type-float","name":"type_float","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxmbG9hdD4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":315,"slug":"type-boolean","name":"type_boolean","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxib29sPgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":328,"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":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUIG9mIG9iamVjdAogKgogKiBAcGFyYW0gY2xhc3Mtc3RyaW5nPFQ+ICRjbGFzcwogKgogKiBAcmV0dXJuIFR5cGU8VD4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":337,"slug":"type-object","name":"type_object","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxvYmplY3Q+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":346,"slug":"type-scalar","name":"type_scalar","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxib29sfGZsb2F0fGludHxzdHJpbmc+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":355,"slug":"type-resource","name":"type_resource","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxyZXNvdXJjZT4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":364,"slug":"type-array","name":"type_array","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxhcnJheTxtaXhlZD4+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":373,"slug":"type-callable","name":"type_callable","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxjYWxsYWJsZT4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":382,"slug":"type-null","name":"type_null","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxudWxsPgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":391,"slug":"type-mixed","name":"type_mixed","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxtaXhlZD4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":400,"slug":"type-positive-integer","name":"type_positive_integer","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxpbnQ8MCwgbWF4Pj4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":409,"slug":"type-non-empty-string","name":"type_non_empty_string","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxub24tZW1wdHktc3RyaW5nPgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":422,"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":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUIG9mIFVuaXRFbnVtCiAqCiAqIEBwYXJhbSBjbGFzcy1zdHJpbmc8VD4gJGNsYXNzCiAqCiAqIEByZXR1cm4gVHlwZTxUPgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":435,"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\\ETL\\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":444,"slug":"type-html","name":"type_html","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxIVE1MRG9jdW1lbnQ+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":453,"slug":"type-html-element","name":"type_html_element","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxIVE1MRWxlbWVudD4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":465,"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\\ETL\\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":478,"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\\ETL\\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":487,"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\\ETL\\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":500,"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":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUIG9mIG9iamVjdAogKgogKiBAcGFyYW0gbnVsbHxjbGFzcy1zdHJpbmc8VD4gJGNsYXNzCiAqCiAqIEByZXR1cm4gKCRjbGFzcyBpcyBudWxsID8gVHlwZTxjbGFzcy1zdHJpbmc+IDogVHlwZTxjbGFzcy1zdHJpbmc8VD4+KQogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":506,"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\\ETL\\Attribute","arguments":{"module":"TYPES","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":185,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":191,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":201,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFJldHVybnMgYSBmaW5nZXJwcmludCBvZiB0aGUgZ2l2ZW4gU1FMIHF1ZXJ5LgogKiBMaXRlcmFsIHZhbHVlcyBhcmUgbm9ybWFsaXplZCBzbyB0aGV5IHdvbid0IGFmZmVjdCB0aGUgZmluZ2VycHJpbnQuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":212,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIE5vcm1hbGl6ZSBTUUwgcXVlcnkgYnkgcmVwbGFjaW5nIGxpdGVyYWwgdmFsdWVzIGFuZCBuYW1lZCBwYXJhbWV0ZXJzIHdpdGggcG9zaXRpb25hbCBwYXJhbWV0ZXJzLgogKiBXSEVSRSBpZCA9IDppZCB3aWxsIGJlIGNoYW5nZWQgaW50byBXSEVSRSBpZCA9ICQxCiAqIFdIRVJFIGlkID0gMSB3aWxsIGJlIGNoYW5nZWQgaW50byBXSEVSRSBpZCA9ICQxLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":222,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIE5vcm1hbGl6ZSB1dGlsaXR5IFNRTCBzdGF0ZW1lbnRzIChEREwgbGlrZSBDUkVBVEUsIEFMVEVSLCBEUk9QKS4KICogVGhpcyBoYW5kbGVzIERETCBzdGF0ZW1lbnRzIGRpZmZlcmVudGx5IGZyb20gcGdfbm9ybWFsaXplKCkgd2hpY2ggaXMgb3B0aW1pemVkIGZvciBETUwuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":233,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFNwbGl0IHN0cmluZyB3aXRoIG11bHRpcGxlIFNRTCBzdGF0ZW1lbnRzIGludG8gYXJyYXkgb2YgaW5kaXZpZHVhbCBzdGF0ZW1lbnRzLgogKgogKiBAcmV0dXJuIGFycmF5PHN0cmluZz4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":242,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBEZXBhcnNlT3B0aW9ucyBmb3IgY29uZmlndXJpbmcgU1FMIGZvcm1hdHRpbmcuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":256,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENvbnZlcnQgYSBQYXJzZWRRdWVyeSBBU1QgYmFjayB0byBTUUwgc3RyaW5nLgogKgogKiBXaGVuIGNhbGxlZCB3aXRob3V0IG9wdGlvbnMsIHJldHVybnMgdGhlIFNRTCBhcyBhIHNpbXBsZSBzdHJpbmcuCiAqIFdoZW4gY2FsbGVkIHdpdGggRGVwYXJzZU9wdGlvbnMsIGFwcGxpZXMgZm9ybWF0dGluZyAocHJldHR5LXByaW50aW5nLCBpbmRlbnRhdGlvbiwgZXRjLikuCiAqCiAqIEB0aHJvd3MgXFJ1bnRpbWVFeGNlcHRpb24gaWYgZGVwYXJzaW5nIGZhaWxzCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":272,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFBhcnNlIGFuZCBmb3JtYXQgU1FMIHF1ZXJ5IHdpdGggcHJldHR5IHByaW50aW5nLgogKgogKiBUaGlzIGlzIGEgY29udmVuaWVuY2UgZnVuY3Rpb24gdGhhdCBwYXJzZXMgU1FMIGFuZCByZXR1cm5zIGl0IGZvcm1hdHRlZC4KICoKICogQHBhcmFtIHN0cmluZyAkc3FsIFRoZSBTUUwgcXVlcnkgdG8gZm9ybWF0CiAqIEBwYXJhbSBudWxsfERlcGFyc2VPcHRpb25zICRvcHRpb25zIEZvcm1hdHRpbmcgb3B0aW9ucyAoZGVmYXVsdHMgdG8gcHJldHR5LXByaW50IGVuYWJsZWQpCiAqCiAqIEB0aHJvd3MgXFJ1bnRpbWVFeGNlcHRpb24gaWYgcGFyc2luZyBvciBkZXBhcnNpbmcgZmFpbHMKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":282,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEdlbmVyYXRlIGEgc3VtbWFyeSBvZiBwYXJzZWQgcXVlcmllcyBpbiBwcm90b2J1ZiBmb3JtYXQuCiAqIFVzZWZ1bCBmb3IgcXVlcnkgbW9uaXRvcmluZyBhbmQgbG9nZ2luZyB3aXRob3V0IGZ1bGwgQVNUIG92ZXJoZWFkLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":297,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFRyYW5zZm9ybSBhIFNRTCBxdWVyeSBpbnRvIGEgcGFnaW5hdGVkIHF1ZXJ5IHdpdGggTElNSVQgYW5kIE9GRlNFVC4KICoKICogQHBhcmFtIHN0cmluZyAkc3FsIFRoZSBTUUwgcXVlcnkgdG8gcGFnaW5hdGUKICogQHBhcmFtIGludCAkbGltaXQgTWF4aW11bSBudW1iZXIgb2Ygcm93cyB0byByZXR1cm4KICogQHBhcmFtIGludCAkb2Zmc2V0IE51bWJlciBvZiByb3dzIHRvIHNraXAgKHJlcXVpcmVzIE9SREVSIEJZIGluIHF1ZXJ5KQogKgogKiBAcmV0dXJuIHN0cmluZyBUaGUgcGFnaW5hdGVkIFNRTCBxdWVyeQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":314,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFRyYW5zZm9ybSBhIFNRTCBxdWVyeSB0byBsaW1pdCByZXN1bHRzIHRvIGEgc3BlY2lmaWMgbnVtYmVyIG9mIHJvd3MuCiAqCiAqIEBwYXJhbSBzdHJpbmcgJHNxbCBUaGUgU1FMIHF1ZXJ5IHRvIGxpbWl0CiAqIEBwYXJhbSBpbnQgJGxpbWl0IE1heGltdW0gbnVtYmVyIG9mIHJvd3MgdG8gcmV0dXJuCiAqCiAqIEByZXR1cm4gc3RyaW5nIFRoZSBsaW1pdGVkIFNRTCBxdWVyeQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":333,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFRyYW5zZm9ybSBhIFNRTCBxdWVyeSBpbnRvIGEgQ09VTlQgcXVlcnkgZm9yIHBhZ2luYXRpb24uCiAqCiAqIFdyYXBzIHRoZSBxdWVyeSBpbjogU0VMRUNUIENPVU5UKCopIEZST00gKC4uLikgQVMgX2NvdW50X3N1YnEKICogUmVtb3ZlcyBPUkRFUiBCWSBhbmQgTElNSVQvT0ZGU0VUIGZyb20gdGhlIGlubmVyIHF1ZXJ5LgogKgogKiBAcGFyYW0gc3RyaW5nICRzcWwgVGhlIFNRTCBxdWVyeSB0byB0cmFuc2Zvcm0KICoKICogQHJldHVybiBzdHJpbmcgVGhlIENPVU5UIHF1ZXJ5CiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":355,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFRyYW5zZm9ybSBhIFNRTCBxdWVyeSBpbnRvIGEga2V5c2V0IChjdXJzb3ItYmFzZWQpIHBhZ2luYXRlZCBxdWVyeS4KICoKICogTW9yZSBlZmZpY2llbnQgdGhhbiBPRkZTRVQgZm9yIGxhcmdlIGRhdGFzZXRzIC0gdXNlcyBpbmRleGVkIFdIRVJFIGNvbmRpdGlvbnMuCiAqIEF1dG9tYXRpY2FsbHkgZGV0ZWN0cyBleGlzdGluZyBxdWVyeSBwYXJhbWV0ZXJzIGFuZCBhcHBlbmRzIGtleXNldCBwbGFjZWhvbGRlcnMgYXQgdGhlIGVuZC4KICoKICogQHBhcmFtIHN0cmluZyAkc3FsIFRoZSBTUUwgcXVlcnkgdG8gcGFnaW5hdGUgKG11c3QgaGF2ZSBPUkRFUiBCWSkKICogQHBhcmFtIGludCAkbGltaXQgTWF4aW11bSBudW1iZXIgb2Ygcm93cyB0byByZXR1cm4KICogQHBhcmFtIGxpc3Q8S2V5c2V0Q29sdW1uPiAkY29sdW1ucyBDb2x1bW5zIGZvciBrZXlzZXQgcGFnaW5hdGlvbiAobXVzdCBtYXRjaCBPUkRFUiBCWSkKICogQHBhcmFtIG51bGx8bGlzdDxudWxsfGJvb2x8ZmxvYXR8aW50fHN0cmluZz4gJGN1cnNvciBWYWx1ZXMgZnJvbSBsYXN0IHJvdyBvZiBwcmV2aW91cyBwYWdlIChudWxsIGZvciBmaXJzdCBwYWdlKQogKgogKiBAcmV0dXJuIHN0cmluZyBUaGUgcGFnaW5hdGVkIFNRTCBxdWVyeQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":370,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEtleXNldENvbHVtbiBmb3Iga2V5c2V0IHBhZ2luYXRpb24uCiAqCiAqIEBwYXJhbSBzdHJpbmcgJGNvbHVtbiBDb2x1bW4gbmFtZSAoY2FuIGluY2x1ZGUgdGFibGUgYWxpYXMgbGlrZSAidS5pZCIpCiAqIEBwYXJhbSBTb3J0T3JkZXIgJG9yZGVyIFNvcnQgb3JkZXIgKEFTQyBvciBERVNDKQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":379,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEV4dHJhY3QgY29sdW1ucyBmcm9tIGEgcGFyc2VkIFNRTCBxdWVyeS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":388,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEV4dHJhY3QgdGFibGVzIGZyb20gYSBwYXJzZWQgU1FMIHF1ZXJ5LgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":397,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEV4dHJhY3QgZnVuY3Rpb25zIGZyb20gYSBwYXJzZWQgU1FMIHF1ZXJ5LgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":406,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEV4dHJhY3QgT1JERVIgQlkgY2xhdXNlcyBmcm9tIGEgcGFyc2VkIFNRTCBxdWVyeS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":420,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEdldCB0aGUgbWF4aW11bSBuZXN0aW5nIGRlcHRoIG9mIGEgU1FMIHF1ZXJ5LgogKgogKiBFeGFtcGxlOgogKiAtICJTRUxFQ1QgKiBGUk9NIHQiID0+IDEKICogLSAiU0VMRUNUICogRlJPTSAoU0VMRUNUICogRlJPTSB0KSIgPT4gMgogKiAtICJTRUxFQ1QgKiBGUk9NIChTRUxFQ1QgKiBGUk9NIChTRUxFQ1QgKiBGUk9NIHQpKSIgPT4gMwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":437,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFRyYW5zZm9ybSBhIFNRTCBxdWVyeSBpbnRvIGFuIEVYUExBSU4gcXVlcnkuCiAqCiAqIFJldHVybnMgdGhlIG1vZGlmaWVkIFNRTCB3aXRoIEVYUExBSU4gd3JhcHBlZCBhcm91bmQgaXQuCiAqIERlZmF1bHRzIHRvIEVYUExBSU4gQU5BTFlaRSB3aXRoIEpTT04gZm9ybWF0IGZvciBlYXN5IHBhcnNpbmcuCiAqCiAqIEBwYXJhbSBzdHJpbmcgJHNxbCBUaGUgU1FMIHF1ZXJ5IHRvIGV4cGxhaW4KICogQHBhcmFtIG51bGx8RXhwbGFpbkNvbmZpZyAkY29uZmlnIEVYUExBSU4gY29uZmlndXJhdGlvbiAoZGVmYXVsdHMgdG8gZm9yQW5hbHlzaXMoKSkKICoKICogQHJldHVybiBzdHJpbmcgVGhlIEVYUExBSU4gcXVlcnkKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":457,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBFeHBsYWluQ29uZmlnIGZvciBjdXN0b21pemluZyBFWFBMQUlOIG9wdGlvbnMuCiAqCiAqIEBwYXJhbSBib29sICRhbmFseXplIFdoZXRoZXIgdG8gYWN0dWFsbHkgZXhlY3V0ZSB0aGUgcXVlcnkgKEFOQUxZWkUpCiAqIEBwYXJhbSBib29sICR2ZXJib3NlIEluY2x1ZGUgdmVyYm9zZSBvdXRwdXQKICogQHBhcmFtIGJvb2wgJGNvc3RzIEluY2x1ZGUgY29zdCBlc3RpbWF0ZXMgKGRlZmF1bHQgdHJ1ZSkKICogQHBhcmFtIGJvb2wgJGJ1ZmZlcnMgSW5jbHVkZSBidWZmZXIgdXNhZ2Ugc3RhdGlzdGljcyAocmVxdWlyZXMgYW5hbHl6ZSkKICogQHBhcmFtIGJvb2wgJHRpbWluZyBJbmNsdWRlIHRpbWluZyBpbmZvcm1hdGlvbiAocmVxdWlyZXMgYW5hbHl6ZSkKICogQHBhcmFtIEV4cGxhaW5Gb3JtYXQgJGZvcm1hdCBPdXRwdXQgZm9ybWF0IChKU09OIHJlY29tbWVuZGVkIGZvciBwYXJzaW5nKQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":479,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBFeHBsYWluTW9kaWZpZXIgZm9yIHRyYW5zZm9ybWluZyBxdWVyaWVzIGludG8gRVhQTEFJTiBxdWVyaWVzLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":492,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFBhcnNlIEVYUExBSU4gSlNPTiBvdXRwdXQgaW50byBhIFBsYW4gb2JqZWN0LgogKgogKiBAcGFyYW0gc3RyaW5nICRqc29uT3V0cHV0IFRoZSBKU09OIG91dHB1dCBmcm9tIEVYUExBSU4gKEZPUk1BVCBKU09OKQogKgogKiBAcmV0dXJuIFBsYW4gVGhlIHBhcnNlZCBleGVjdXRpb24gcGxhbgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":505,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHBsYW4gYW5hbHl6ZXIgZm9yIGFuYWx5emluZyBFWFBMQUlOIHBsYW5zLgogKgogKiBAcGFyYW0gUGxhbiAkcGxhbiBUaGUgZXhlY3V0aW9uIHBsYW4gdG8gYW5hbHl6ZQogKgogKiBAcmV0dXJuIFBsYW5BbmFseXplciBUaGUgYW5hbHl6ZXIgZm9yIGV4dHJhY3RpbmcgaW5zaWdodHMKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":516,"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}],"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIG5ldyBTRUxFQ1QgcXVlcnkgYnVpbGRlci4KICoKICogQHBhcmFtIEV4cHJlc3Npb24gLi4uJGV4cHJlc3Npb25zIENvbHVtbnMgdG8gc2VsZWN0LiBJZiBlbXB0eSwgcmV0dXJucyBTZWxlY3RTZWxlY3RTdGVwLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":532,"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\\ETL\\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\/functions.php","start_line_in_file":545,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIG5ldyBJTlNFUlQgcXVlcnkgYnVpbGRlci4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":561,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBvcHRpbWl6ZWQgYnVsayBJTlNFUlQgcXVlcnkgZm9yIGhpZ2gtcGVyZm9ybWFuY2UgbXVsdGktcm93IGluc2VydHMuCiAqCiAqIFVubGlrZSBpbnNlcnQoKSB3aGljaCB1c2VzIGltbXV0YWJsZSBidWlsZGVyIHBhdHRlcm5zIChPKG7CsikgZm9yIG4gcm93cyksCiAqIHRoaXMgZnVuY3Rpb24gZ2VuZXJhdGVzIFNRTCBkaXJlY3RseSB1c2luZyBzdHJpbmcgb3BlcmF0aW9ucyAoTyhuKSBjb21wbGV4aXR5KS4KICoKICogQHBhcmFtIHN0cmluZyAkdGFibGUgVGFibGUgbmFtZQogKiBAcGFyYW0gbGlzdDxzdHJpbmc+ICRjb2x1bW5zIENvbHVtbiBuYW1lcwogKiBAcGFyYW0gaW50ICRyb3dDb3VudCBOdW1iZXIgb2Ygcm93cyB0byBpbnNlcnQKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":570,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIG5ldyBVUERBVEUgcXVlcnkgYnVpbGRlci4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":579,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIG5ldyBERUxFVEUgcXVlcnkgYnVpbGRlci4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":591,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIG5ldyBNRVJHRSBxdWVyeSBidWlsZGVyLgogKgogKiBAcGFyYW0gc3RyaW5nICR0YWJsZSBUYXJnZXQgdGFibGUgbmFtZQogKiBAcGFyYW0gbnVsbHxzdHJpbmcgJGFsaWFzIE9wdGlvbmFsIHRhYmxlIGFsaWFzCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":605,"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\\ETL\\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\/functions.php","start_line_in_file":626,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGNvbHVtbiByZWZlcmVuY2UgZXhwcmVzc2lvbi4KICoKICogQ2FuIGJlIHVzZWQgaW4gdHdvIG1vZGVzOgogKiAtIFBhcnNlIG1vZGU6IGNvbCgndXNlcnMuaWQnKSBvciBjb2woJ3NjaGVtYS50YWJsZS5jb2x1bW4nKSAtIHBhcnNlcyBkb3Qtc2VwYXJhdGVkIHN0cmluZwogKiAtIEV4cGxpY2l0IG1vZGU6IGNvbCgnaWQnLCAndXNlcnMnKSBvciBjb2woJ2lkJywgJ3VzZXJzJywgJ3NjaGVtYScpIC0gc2VwYXJhdGUgYXJndW1lbnRzCiAqCiAqIFdoZW4gJHRhYmxlIG9yICRzY2hlbWEgaXMgcHJvdmlkZWQsICRjb2x1bW4gbXVzdCBiZSBhIHBsYWluIGNvbHVtbiBuYW1lIChubyBkb3RzKS4KICoKICogQHBhcmFtIHN0cmluZyAkY29sdW1uIENvbHVtbiBuYW1lLCBvciBkb3Qtc2VwYXJhdGVkIHBhdGggbGlrZSAidGFibGUuY29sdW1uIiBvciAic2NoZW1hLnRhYmxlLmNvbHVtbiIKICogQHBhcmFtIG51bGx8c3RyaW5nICR0YWJsZSBUYWJsZSBuYW1lIChvcHRpb25hbCwgdHJpZ2dlcnMgZXhwbGljaXQgbW9kZSkKICogQHBhcmFtIG51bGx8c3RyaW5nICRzY2hlbWEgU2NoZW1hIG5hbWUgKG9wdGlvbmFsLCByZXF1aXJlcyAkdGFibGUpCiAqCiAqIEB0aHJvd3MgSW52YWxpZEV4cHJlc3Npb25FeGNlcHRpb24gd2hlbiAkc2NoZW1hIGlzIHByb3ZpZGVkIHdpdGhvdXQgJHRhYmxlLCBvciB3aGVuICRjb2x1bW4gY29udGFpbnMgZG90cyBpbiBleHBsaWNpdCBtb2RlCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":655,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFNFTEVDVCAqIGV4cHJlc3Npb24uCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":671,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGxpdGVyYWwgdmFsdWUgZm9yIHVzZSBpbiBxdWVyaWVzLgogKgogKiBBdXRvbWF0aWNhbGx5IGRldGVjdHMgdGhlIHR5cGUgYW5kIGNyZWF0ZXMgdGhlIGFwcHJvcHJpYXRlIGxpdGVyYWw6CiAqIC0gbGl0ZXJhbCgnaGVsbG8nKSBjcmVhdGVzIGEgc3RyaW5nIGxpdGVyYWwKICogLSBsaXRlcmFsKDQyKSBjcmVhdGVzIGFuIGludGVnZXIgbGl0ZXJhbAogKiAtIGxpdGVyYWwoMy4xNCkgY3JlYXRlcyBhIGZsb2F0IGxpdGVyYWwKICogLSBsaXRlcmFsKHRydWUpIGNyZWF0ZXMgYSBib29sZWFuIGxpdGVyYWwKICogLSBsaXRlcmFsKG51bGwpIGNyZWF0ZXMgYSBOVUxMIGxpdGVyYWwKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":686,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHBvc2l0aW9uYWwgcGFyYW1ldGVyICgkMSwgJDIsIGV0Yy4pLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":698,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGZ1bmN0aW9uIGNhbGwgZXhwcmVzc2lvbi4KICoKICogQHBhcmFtIHN0cmluZyAkbmFtZSBGdW5jdGlvbiBuYW1lIChjYW4gaW5jbHVkZSBzY2hlbWEgbGlrZSAicGdfY2F0YWxvZy5ub3ciKQogKiBAcGFyYW0gbGlzdDxFeHByZXNzaW9uPiAkYXJncyBGdW5jdGlvbiBhcmd1bWVudHMKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":711,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBhZ2dyZWdhdGUgZnVuY3Rpb24gY2FsbCAoQ09VTlQsIFNVTSwgQVZHLCBldGMuKS4KICoKICogQHBhcmFtIHN0cmluZyAkbmFtZSBBZ2dyZWdhdGUgZnVuY3Rpb24gbmFtZQogKiBAcGFyYW0gbGlzdDxFeHByZXNzaW9uPiAkYXJncyBGdW5jdGlvbiBhcmd1bWVudHMKICogQHBhcmFtIGJvb2wgJGRpc3RpbmN0IFVzZSBESVNUSU5DVCBtb2RpZmllcgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":720,"slug":"agg-count","name":"agg_count","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","type":[{"name":"Expression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBDT1VOVCgqKSBhZ2dyZWdhdGUuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":733,"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}],"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBTVU0gYWdncmVnYXRlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":742,"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}],"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBBVkcgYWdncmVnYXRlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":751,"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}],"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBNSU4gYWdncmVnYXRlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":760,"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}],"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBNQVggYWdncmVnYXRlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":771,"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}],"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENPQUxFU0NFIGV4cHJlc3Npb24uCiAqCiAqIEBwYXJhbSBFeHByZXNzaW9uIC4uLiRleHByZXNzaW9ucyBFeHByZXNzaW9ucyB0byBjb2FsZXNjZQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":780,"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}],"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}],"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIE5VTExJRiBleHByZXNzaW9uLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":791,"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}],"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEdSRUFURVNUIGV4cHJlc3Npb24uCiAqCiAqIEBwYXJhbSBFeHByZXNzaW9uIC4uLiRleHByZXNzaW9ucyBFeHByZXNzaW9ucyB0byBjb21wYXJlCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":802,"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}],"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIExFQVNUIGV4cHJlc3Npb24uCiAqCiAqIEBwYXJhbSBFeHByZXNzaW9uIC4uLiRleHByZXNzaW9ucyBFeHByZXNzaW9ucyB0byBjb21wYXJlCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":814,"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}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"dataType","type":[{"name":"DataType","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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHR5cGUgY2FzdCBleHByZXNzaW9uLgogKgogKiBAcGFyYW0gRXhwcmVzc2lvbiAkZXhwciBFeHByZXNzaW9uIHRvIGNhc3QKICogQHBhcmFtIERhdGFUeXBlICRkYXRhVHlwZSBUYXJnZXQgZGF0YSB0eXBlICh1c2UgZGF0YV90eXBlXyogZnVuY3Rpb25zKQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":823,"slug":"data-type-integer","name":"data_type_integer","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"DataType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBpbnRlZ2VyIGRhdGEgdHlwZSAoUG9zdGdyZVNRTCBpbnQ0KS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":832,"slug":"data-type-smallint","name":"data_type_smallint","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"DataType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHNtYWxsaW50IGRhdGEgdHlwZSAoUG9zdGdyZVNRTCBpbnQyKS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":841,"slug":"data-type-bigint","name":"data_type_bigint","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"DataType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGJpZ2ludCBkYXRhIHR5cGUgKFBvc3RncmVTUUwgaW50OCkuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":850,"slug":"data-type-boolean","name":"data_type_boolean","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"DataType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGJvb2xlYW4gZGF0YSB0eXBlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":859,"slug":"data-type-text","name":"data_type_text","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"DataType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHRleHQgZGF0YSB0eXBlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":868,"slug":"data-type-varchar","name":"data_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":"DataType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHZhcmNoYXIgZGF0YSB0eXBlIHdpdGggbGVuZ3RoIGNvbnN0cmFpbnQuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":877,"slug":"data-type-char","name":"data_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":"DataType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGNoYXIgZGF0YSB0eXBlIHdpdGggbGVuZ3RoIGNvbnN0cmFpbnQuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":886,"slug":"data-type-numeric","name":"data_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":"DataType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIG51bWVyaWMgZGF0YSB0eXBlIHdpdGggb3B0aW9uYWwgcHJlY2lzaW9uIGFuZCBzY2FsZS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":895,"slug":"data-type-decimal","name":"data_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":"DataType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGRlY2ltYWwgZGF0YSB0eXBlIHdpdGggb3B0aW9uYWwgcHJlY2lzaW9uIGFuZCBzY2FsZS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":904,"slug":"data-type-real","name":"data_type_real","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"DataType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHJlYWwgZGF0YSB0eXBlIChQb3N0Z3JlU1FMIGZsb2F0NCkuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":913,"slug":"data-type-double-precision","name":"data_type_double_precision","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"DataType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGRvdWJsZSBwcmVjaXNpb24gZGF0YSB0eXBlIChQb3N0Z3JlU1FMIGZsb2F0OCkuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":922,"slug":"data-type-date","name":"data_type_date","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"DataType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGRhdGUgZGF0YSB0eXBlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":931,"slug":"data-type-time","name":"data_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":"DataType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHRpbWUgZGF0YSB0eXBlIHdpdGggb3B0aW9uYWwgcHJlY2lzaW9uLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":940,"slug":"data-type-timestamp","name":"data_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":"DataType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHRpbWVzdGFtcCBkYXRhIHR5cGUgd2l0aCBvcHRpb25hbCBwcmVjaXNpb24uCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":949,"slug":"data-type-timestamptz","name":"data_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":"DataType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHRpbWVzdGFtcCB3aXRoIHRpbWUgem9uZSBkYXRhIHR5cGUgd2l0aCBvcHRpb25hbCBwcmVjaXNpb24uCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":958,"slug":"data-type-interval","name":"data_type_interval","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"DataType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBpbnRlcnZhbCBkYXRhIHR5cGUuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":973,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFNRTCBzdGFuZGFyZCBDVVJSRU5UX1RJTUVTVEFNUCBmdW5jdGlvbi4KICoKICogUmV0dXJucyB0aGUgY3VycmVudCBkYXRlIGFuZCB0aW1lIChhdCB0aGUgc3RhcnQgb2YgdGhlIHRyYW5zYWN0aW9uKS4KICogVXNlZnVsIGFzIGEgY29sdW1uIGRlZmF1bHQgdmFsdWUgb3IgaW4gU0VMRUNUIHF1ZXJpZXMuCiAqCiAqIEV4YW1wbGU6IGNvbHVtbignY3JlYXRlZF9hdCcsIGRhdGFfdHlwZV90aW1lc3RhbXAoKSktPmRlZmF1bHQoY3VycmVudF90aW1lc3RhbXAoKSkKICogRXhhbXBsZTogc2VsZWN0KCktPnNlbGVjdChjdXJyZW50X3RpbWVzdGFtcCgpLT5hcygnbm93JykpCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":988,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFNRTCBzdGFuZGFyZCBDVVJSRU5UX0RBVEUgZnVuY3Rpb24uCiAqCiAqIFJldHVybnMgdGhlIGN1cnJlbnQgZGF0ZSAoYXQgdGhlIHN0YXJ0IG9mIHRoZSB0cmFuc2FjdGlvbikuCiAqIFVzZWZ1bCBhcyBhIGNvbHVtbiBkZWZhdWx0IHZhbHVlIG9yIGluIFNFTEVDVCBxdWVyaWVzLgogKgogKiBFeGFtcGxlOiBjb2x1bW4oJ2JpcnRoX2RhdGUnLCBkYXRhX3R5cGVfZGF0ZSgpKS0+ZGVmYXVsdChjdXJyZW50X2RhdGUoKSkKICogRXhhbXBsZTogc2VsZWN0KCktPnNlbGVjdChjdXJyZW50X2RhdGUoKS0+YXMoJ3RvZGF5JykpCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1003,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFNRTCBzdGFuZGFyZCBDVVJSRU5UX1RJTUUgZnVuY3Rpb24uCiAqCiAqIFJldHVybnMgdGhlIGN1cnJlbnQgdGltZSAoYXQgdGhlIHN0YXJ0IG9mIHRoZSB0cmFuc2FjdGlvbikuCiAqIFVzZWZ1bCBhcyBhIGNvbHVtbiBkZWZhdWx0IHZhbHVlIG9yIGluIFNFTEVDVCBxdWVyaWVzLgogKgogKiBFeGFtcGxlOiBjb2x1bW4oJ3N0YXJ0X3RpbWUnLCBkYXRhX3R5cGVfdGltZSgpKS0+ZGVmYXVsdChjdXJyZW50X3RpbWUoKSkKICogRXhhbXBsZTogc2VsZWN0KCktPnNlbGVjdChjdXJyZW50X3RpbWUoKS0+YXMoJ25vd190aW1lJykpCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1012,"slug":"data-type-uuid","name":"data_type_uuid","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"DataType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFVVSUQgZGF0YSB0eXBlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1021,"slug":"data-type-json","name":"data_type_json","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"DataType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEpTT04gZGF0YSB0eXBlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1030,"slug":"data-type-jsonb","name":"data_type_jsonb","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"DataType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEpTT05CIGRhdGEgdHlwZS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1039,"slug":"data-type-bytea","name":"data_type_bytea","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"DataType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGJ5dGVhIGRhdGEgdHlwZS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1048,"slug":"data-type-inet","name":"data_type_inet","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"DataType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBpbmV0IGRhdGEgdHlwZS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1057,"slug":"data-type-cidr","name":"data_type_cidr","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"DataType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGNpZHIgZGF0YSB0eXBlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1066,"slug":"data-type-macaddr","name":"data_type_macaddr","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"DataType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIG1hY2FkZHIgZGF0YSB0eXBlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1075,"slug":"data-type-serial","name":"data_type_serial","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"DataType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHNlcmlhbCBkYXRhIHR5cGUuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1084,"slug":"data-type-smallserial","name":"data_type_smallserial","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"DataType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHNtYWxsc2VyaWFsIGRhdGEgdHlwZS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1093,"slug":"data-type-bigserial","name":"data_type_bigserial","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"DataType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGJpZ3NlcmlhbCBkYXRhIHR5cGUuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1102,"slug":"data-type-array","name":"data_type_array","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"elementType","type":[{"name":"DataType","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":"DataType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBhcnJheSBkYXRhIHR5cGUgZnJvbSBhbiBlbGVtZW50IHR5cGUuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1114,"slug":"data-type-custom","name":"data_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":"DataType","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGN1c3RvbSBkYXRhIHR5cGUuCiAqCiAqIEBwYXJhbSBzdHJpbmcgJHR5cGVOYW1lIFR5cGUgbmFtZQogKiBAcGFyYW0gbnVsbHxzdHJpbmcgJHNjaGVtYSBPcHRpb25hbCBzY2hlbWEgbmFtZQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1127,"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":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":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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENBU0UgZXhwcmVzc2lvbi4KICoKICogQHBhcmFtIG5vbi1lbXB0eS1saXN0PFdoZW5DbGF1c2U+ICR3aGVuQ2xhdXNlcyBXSEVOIGNsYXVzZXMKICogQHBhcmFtIG51bGx8RXhwcmVzc2lvbiAkZWxzZVJlc3VsdCBFTFNFIHJlc3VsdCAob3B0aW9uYWwpCiAqIEBwYXJhbSBudWxsfEV4cHJlc3Npb24gJG9wZXJhbmQgQ0FTRSBvcGVyYW5kIGZvciBzaW1wbGUgQ0FTRSAob3B0aW9uYWwpCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1136,"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}],"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}],"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFdIRU4gY2xhdXNlIGZvciBDQVNFIGV4cHJlc3Npb24uCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1145,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHN1YnF1ZXJ5IGV4cHJlc3Npb24uCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1159,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBhcnJheSBleHByZXNzaW9uLgogKgogKiBAcGFyYW0gbGlzdDxFeHByZXNzaW9uPiAkZWxlbWVudHMgQXJyYXkgZWxlbWVudHMKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1170,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHJvdyBleHByZXNzaW9uLgogKgogKiBAcGFyYW0gbGlzdDxFeHByZXNzaW9uPiAkZWxlbWVudHMgUm93IGVsZW1lbnRzCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1192,"slug":"raw-expr","name":"raw_expr","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":"RawExpression","namespace":"Flow\\PostgreSql\\QueryBuilder\\Expression","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHJhdyBTUUwgZXhwcmVzc2lvbiAodXNlIHdpdGggY2F1dGlvbikuCiAqCiAqIFNFQ1VSSVRZIFdBUk5JTkc6IFRoaXMgZnVuY3Rpb24gYWNjZXB0cyByYXcgU1FMIHdpdGhvdXQgcGFyYW1ldGVyaXphdGlvbi4KICogU1FMIGluamVjdGlvbiBpcyBwb3NzaWJsZSBpZiB1c2VkIHdpdGggdW50cnVzdGVkIHVzZXIgaW5wdXQuCiAqIE9ubHkgdXNlIHdpdGggdHJ1c3RlZCwgdmFsaWRhdGVkIGlucHV0LgogKgogKiBGb3IgdXNlci1wcm92aWRlZCB2YWx1ZXMsIHVzZSBwYXJhbSgpIGluc3RlYWQ6CiAqIGBgYHBocAogKiAvLyBVTlNBRkUgLSBTUUwgaW5qZWN0aW9uIHBvc3NpYmxlOgogKiByYXdfZXhwcigiY3VzdG9tX2Z1bmMoJyIgLiAkdXNlcklucHV0IC4gIicpIikKICoKICogLy8gU0FGRSAtIHVzZSBwYXJhbWV0ZXJzOgogKiBmdW5jKCdjdXN0b21fZnVuYycsIHBhcmFtKDEpKQogKiBgYGAKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1201,"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}],"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}],"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGJpbmFyeSBleHByZXNzaW9uIChsZWZ0IG9wIHJpZ2h0KS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1215,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHdpbmRvdyBmdW5jdGlvbi4KICoKICogQHBhcmFtIHN0cmluZyAkbmFtZSBGdW5jdGlvbiBuYW1lCiAqIEBwYXJhbSBsaXN0PEV4cHJlc3Npb24+ICRhcmdzIEZ1bmN0aW9uIGFyZ3VtZW50cwogKiBAcGFyYW0gbGlzdDxFeHByZXNzaW9uPiAkcGFydGl0aW9uQnkgUEFSVElUSU9OIEJZIGV4cHJlc3Npb25zCiAqIEBwYXJhbSBsaXN0PE9yZGVyQnk+ICRvcmRlckJ5IE9SREVSIEJZIGl0ZW1zCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1228,"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}],"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}],"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBlcXVhbGl0eSBjb21wYXJpc29uIChjb2x1bW4gPSB2YWx1ZSkuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1237,"slug":"neq","name":"neq","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"left","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},{"name":"right","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":"Comparison","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIG5vdC1lcXVhbCBjb21wYXJpc29uIChjb2x1bW4gIT0gdmFsdWUpLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1246,"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}],"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}],"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGxlc3MtdGhhbiBjb21wYXJpc29uIChjb2x1bW4gPCB2YWx1ZSkuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1255,"slug":"lte","name":"lte","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"left","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},{"name":"right","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":"Comparison","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGxlc3MtdGhhbi1vci1lcXVhbCBjb21wYXJpc29uIChjb2x1bW4gPD0gdmFsdWUpLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1264,"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}],"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}],"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGdyZWF0ZXItdGhhbiBjb21wYXJpc29uIChjb2x1bW4gPiB2YWx1ZSkuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1273,"slug":"gte","name":"gte","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"left","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},{"name":"right","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":"Comparison","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGdyZWF0ZXItdGhhbi1vci1lcXVhbCBjb21wYXJpc29uIChjb2x1bW4gPj0gdmFsdWUpLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1282,"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}],"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}],"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}],"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEJFVFdFRU4gY29uZGl0aW9uLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1294,"slug":"is-in","name":"is_in","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"expr","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},{"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBJTiBjb25kaXRpb24uCiAqCiAqIEBwYXJhbSBFeHByZXNzaW9uICRleHByIEV4cHJlc3Npb24gdG8gY2hlY2sKICogQHBhcmFtIGxpc3Q8RXhwcmVzc2lvbj4gJHZhbHVlcyBMaXN0IG9mIHZhbHVlcwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1303,"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}],"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBJUyBOVUxMIGNvbmRpdGlvbi4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1312,"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}],"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}],"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIExJS0UgY29uZGl0aW9uLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1321,"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}],"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}],"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFNJTUlMQVIgVE8gY29uZGl0aW9uLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1330,"slug":"is-distinct-from","name":"is_distinct_from","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"left","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},{"name":"right","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},{"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBJUyBESVNUSU5DVCBGUk9NIGNvbmRpdGlvbi4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1339,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBFWElTVFMgY29uZGl0aW9uLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1351,"slug":"any-sub-select","name":"any_sub_select","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"left","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},{"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":"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":"Any","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBBTlkgY29uZGl0aW9uLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1363,"slug":"all-sub-select","name":"all_sub_select","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"left","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},{"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":"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":"All","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBBTEwgY29uZGl0aW9uLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1389,"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\\ETL\\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\/functions.php","start_line_in_file":1400,"slug":"cond-and","name":"cond_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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENvbWJpbmUgY29uZGl0aW9ucyB3aXRoIEFORC4KICoKICogQHBhcmFtIENvbmRpdGlvbiAuLi4kY29uZGl0aW9ucyBDb25kaXRpb25zIHRvIGNvbWJpbmUKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1411,"slug":"cond-or","name":"cond_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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENvbWJpbmUgY29uZGl0aW9ucyB3aXRoIE9SLgogKgogKiBAcGFyYW0gQ29uZGl0aW9uIC4uLiRjb25kaXRpb25zIENvbmRpdGlvbnMgdG8gY29tYmluZQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1420,"slug":"cond-not","name":"cond_not","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":"NotCondition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIE5lZ2F0ZSBhIGNvbmRpdGlvbiB3aXRoIE5PVC4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1442,"slug":"raw-cond","name":"raw_cond","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":"RawCondition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHJhdyBTUUwgY29uZGl0aW9uICh1c2Ugd2l0aCBjYXV0aW9uKS4KICoKICogU0VDVVJJVFkgV0FSTklORzogVGhpcyBmdW5jdGlvbiBhY2NlcHRzIHJhdyBTUUwgd2l0aG91dCBwYXJhbWV0ZXJpemF0aW9uLgogKiBTUUwgaW5qZWN0aW9uIGlzIHBvc3NpYmxlIGlmIHVzZWQgd2l0aCB1bnRydXN0ZWQgdXNlciBpbnB1dC4KICogT25seSB1c2Ugd2l0aCB0cnVzdGVkLCB2YWxpZGF0ZWQgaW5wdXQuCiAqCiAqIEZvciB1c2VyLXByb3ZpZGVkIHZhbHVlcywgdXNlIHN0YW5kYXJkIGNvbmRpdGlvbiBmdW5jdGlvbnMgd2l0aCBwYXJhbSgpOgogKiBgYGBwaHAKICogLy8gVU5TQUZFIC0gU1FMIGluamVjdGlvbiBwb3NzaWJsZToKICogcmF3X2NvbmQoInN0YXR1cyA9ICciIC4gJHVzZXJJbnB1dCAuICInIikKICoKICogLy8gU0FGRSAtIHVzZSB0eXBlZCBjb25kaXRpb25zOgogKiBlcShjb2woJ3N0YXR1cycpLCBwYXJhbSgxKSkKICogYGBgCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1455,"slug":"cond-true","name":"cond_true","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"RawCondition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFRSVUUgY29uZGl0aW9uIGZvciBXSEVSRSBjbGF1c2VzLgogKgogKiBVc2VmdWwgd2hlbiB5b3UgbmVlZCBhIGNvbmRpdGlvbiB0aGF0IGFsd2F5cyBldmFsdWF0ZXMgdG8gdHJ1ZS4KICoKICogRXhhbXBsZTogc2VsZWN0KGxpdGVyYWwoMSkpLT53aGVyZShjb25kX3RydWUoKSkgLy8gU0VMRUNUIDEgV0hFUkUgdHJ1ZQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1469,"slug":"cond-false","name":"cond_false","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"RawCondition","namespace":"Flow\\PostgreSql\\QueryBuilder\\Condition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEZBTFNFIGNvbmRpdGlvbiBmb3IgV0hFUkUgY2xhdXNlcy4KICoKICogVXNlZnVsIHdoZW4geW91IG5lZWQgYSBjb25kaXRpb24gdGhhdCBhbHdheXMgZXZhbHVhdGVzIHRvIGZhbHNlLAogKiB0eXBpY2FsbHkgZm9yIHRlc3Rpbmcgb3IgdG8gcmV0dXJuIGFuIGVtcHR5IHJlc3VsdCBzZXQuCiAqCiAqIEV4YW1wbGU6IHNlbGVjdChsaXRlcmFsKDEpKS0+d2hlcmUoY29uZF9mYWxzZSgpKSAvLyBTRUxFQ1QgMSBXSEVSRSBmYWxzZQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1481,"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}],"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}],"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEpTT05CIGNvbnRhaW5zIGNvbmRpdGlvbiAoQD4pLgogKgogKiBFeGFtcGxlOiBqc29uX2NvbnRhaW5zKGNvbCgnbWV0YWRhdGEnKSwgbGl0ZXJhbF9qc29uKCd7ImNhdGVnb3J5IjogImVsZWN0cm9uaWNzIn0nKSkKICogUHJvZHVjZXM6IG1ldGFkYXRhIEA+ICd7ImNhdGVnb3J5IjogImVsZWN0cm9uaWNzIn0nCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1493,"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}],"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}],"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEpTT05CIGlzIGNvbnRhaW5lZCBieSBjb25kaXRpb24gKDxAKS4KICoKICogRXhhbXBsZToganNvbl9jb250YWluZWRfYnkoY29sKCdtZXRhZGF0YScpLCBsaXRlcmFsX2pzb24oJ3siY2F0ZWdvcnkiOiAiZWxlY3Ryb25pY3MiLCAicHJpY2UiOiAxMDB9JykpCiAqIFByb2R1Y2VzOiBtZXRhZGF0YSA8QCAneyJjYXRlZ29yeSI6ICJlbGVjdHJvbmljcyIsICJwcmljZSI6IDEwMH0nCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1506,"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}],"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}],"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEpTT04gZmllbGQgYWNjZXNzIGV4cHJlc3Npb24gKC0+KS4KICogUmV0dXJucyBKU09OLgogKgogKiBFeGFtcGxlOiBqc29uX2dldChjb2woJ21ldGFkYXRhJyksIGxpdGVyYWxfc3RyaW5nKCdjYXRlZ29yeScpKQogKiBQcm9kdWNlczogbWV0YWRhdGEgLT4gJ2NhdGVnb3J5JwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1519,"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}],"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}],"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEpTT04gZmllbGQgYWNjZXNzIGV4cHJlc3Npb24gKC0+PikuCiAqIFJldHVybnMgdGV4dC4KICoKICogRXhhbXBsZToganNvbl9nZXRfdGV4dChjb2woJ21ldGFkYXRhJyksIGxpdGVyYWxfc3RyaW5nKCduYW1lJykpCiAqIFByb2R1Y2VzOiBtZXRhZGF0YSAtPj4gJ25hbWUnCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1532,"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}],"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}],"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEpTT04gcGF0aCBhY2Nlc3MgZXhwcmVzc2lvbiAoIz4pLgogKiBSZXR1cm5zIEpTT04uCiAqCiAqIEV4YW1wbGU6IGpzb25fcGF0aChjb2woJ21ldGFkYXRhJyksIGxpdGVyYWxfc3RyaW5nKCd7Y2F0ZWdvcnksbmFtZX0nKSkKICogUHJvZHVjZXM6IG1ldGFkYXRhICM+ICd7Y2F0ZWdvcnksbmFtZX0nCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1545,"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}],"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}],"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\\ETL\\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\/functions.php","start_line_in_file":1557,"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}],"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}],"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEpTT05CIGtleSBleGlzdHMgY29uZGl0aW9uICg\/KS4KICoKICogRXhhbXBsZToganNvbl9leGlzdHMoY29sKCdtZXRhZGF0YScpLCBsaXRlcmFsX3N0cmluZygnY2F0ZWdvcnknKSkKICogUHJvZHVjZXM6IG1ldGFkYXRhID8gJ2NhdGVnb3J5JwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1569,"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}],"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}],"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEpTT05CIGFueSBrZXkgZXhpc3RzIGNvbmRpdGlvbiAoP3wpLgogKgogKiBFeGFtcGxlOiBqc29uX2V4aXN0c19hbnkoY29sKCdtZXRhZGF0YScpLCByYXdfZXhwcigiYXJyYXlbJ2NhdGVnb3J5JywgJ25hbWUnXSIpKQogKiBQcm9kdWNlczogbWV0YWRhdGEgP3wgYXJyYXlbJ2NhdGVnb3J5JywgJ25hbWUnXQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1581,"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}],"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}],"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEpTT05CIGFsbCBrZXlzIGV4aXN0IGNvbmRpdGlvbiAoPyYpLgogKgogKiBFeGFtcGxlOiBqc29uX2V4aXN0c19hbGwoY29sKCdtZXRhZGF0YScpLCByYXdfZXhwcigiYXJyYXlbJ2NhdGVnb3J5JywgJ25hbWUnXSIpKQogKiBQcm9kdWNlczogbWV0YWRhdGEgPyYgYXJyYXlbJ2NhdGVnb3J5JywgJ25hbWUnXQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1593,"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}],"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}],"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBhcnJheSBjb250YWlucyBjb25kaXRpb24gKEA+KS4KICoKICogRXhhbXBsZTogYXJyYXlfY29udGFpbnMoY29sKCd0YWdzJyksIHJhd19leHByKCJBUlJBWVsnc2FsZSddIikpCiAqIFByb2R1Y2VzOiB0YWdzIEA+IEFSUkFZWydzYWxlJ10KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1605,"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}],"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}],"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBhcnJheSBpcyBjb250YWluZWQgYnkgY29uZGl0aW9uICg8QCkuCiAqCiAqIEV4YW1wbGU6IGFycmF5X2NvbnRhaW5lZF9ieShjb2woJ3RhZ3MnKSwgcmF3X2V4cHIoIkFSUkFZWydzYWxlJywgJ2ZlYXR1cmVkJywgJ25ldyddIikpCiAqIFByb2R1Y2VzOiB0YWdzIDxAIEFSUkFZWydzYWxlJywgJ2ZlYXR1cmVkJywgJ25ldyddCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1617,"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}],"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}],"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBhcnJheSBvdmVybGFwIGNvbmRpdGlvbiAoJiYpLgogKgogKiBFeGFtcGxlOiBhcnJheV9vdmVybGFwKGNvbCgndGFncycpLCByYXdfZXhwcigiQVJSQVlbJ3NhbGUnLCAnZmVhdHVyZWQnXSIpKQogKiBQcm9kdWNlczogdGFncyAmJiBBUlJBWVsnc2FsZScsICdmZWF0dXJlZCddCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1631,"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}],"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}],"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBPU0lYIHJlZ2V4IG1hdGNoIGNvbmRpdGlvbiAofikuCiAqIENhc2Utc2Vuc2l0aXZlLgogKgogKiBFeGFtcGxlOiByZWdleF9tYXRjaChjb2woJ2VtYWlsJyksIGxpdGVyYWxfc3RyaW5nKCcuKkBnbWFpbFxcLmNvbScpKQogKgogKiBQcm9kdWNlczogZW1haWwgfiAnLipAZ21haWxcLmNvbScKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1645,"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}],"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}],"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBPU0lYIHJlZ2V4IG1hdGNoIGNvbmRpdGlvbiAofiopLgogKiBDYXNlLWluc2Vuc2l0aXZlLgogKgogKiBFeGFtcGxlOiByZWdleF9pbWF0Y2goY29sKCdlbWFpbCcpLCBsaXRlcmFsX3N0cmluZygnLipAZ21haWxcXC5jb20nKSkKICoKICogUHJvZHVjZXM6IGVtYWlsIH4qICcuKkBnbWFpbFwuY29tJwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1659,"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}],"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}],"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBPU0lYIHJlZ2V4IG5vdCBtYXRjaCBjb25kaXRpb24gKCF+KS4KICogQ2FzZS1zZW5zaXRpdmUuCiAqCiAqIEV4YW1wbGU6IG5vdF9yZWdleF9tYXRjaChjb2woJ2VtYWlsJyksIGxpdGVyYWxfc3RyaW5nKCcuKkBzcGFtXFwuY29tJykpCiAqCiAqIFByb2R1Y2VzOiBlbWFpbCAhfiAnLipAc3BhbVwuY29tJwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1673,"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}],"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}],"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBPU0lYIHJlZ2V4IG5vdCBtYXRjaCBjb25kaXRpb24gKCF+KikuCiAqIENhc2UtaW5zZW5zaXRpdmUuCiAqCiAqIEV4YW1wbGU6IG5vdF9yZWdleF9pbWF0Y2goY29sKCdlbWFpbCcpLCBsaXRlcmFsX3N0cmluZygnLipAc3BhbVxcLmNvbScpKQogKgogKiBQcm9kdWNlczogZW1haWwgIX4qICcuKkBzcGFtXC5jb20nCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1685,"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}],"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}],"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGZ1bGwtdGV4dCBzZWFyY2ggbWF0Y2ggY29uZGl0aW9uIChAQCkuCiAqCiAqIEV4YW1wbGU6IHRleHRfc2VhcmNoX21hdGNoKGNvbCgnZG9jdW1lbnQnKSwgcmF3X2V4cHIoInRvX3RzcXVlcnkoJ2VuZ2xpc2gnLCAnaGVsbG8gJiB3b3JsZCcpIikpCiAqIFByb2R1Y2VzOiBkb2N1bWVudCBAQCB0b190c3F1ZXJ5KCdlbmdsaXNoJywgJ2hlbGxvICYgd29ybGQnKQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1700,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHRhYmxlIHJlZmVyZW5jZS4KICoKICogU3VwcG9ydHMgZG90IG5vdGF0aW9uIGZvciBzY2hlbWEtcXVhbGlmaWVkIG5hbWVzOiAicHVibGljLnVzZXJzIiBvciBleHBsaWNpdCBzY2hlbWEgcGFyYW1ldGVyLgogKiBEb3VibGUtcXVvdGVkIGlkZW50aWZpZXJzIHByZXNlcnZlIGRvdHM6ICcibXkudGFibGUiJyBjcmVhdGVzIGEgc2luZ2xlIGlkZW50aWZpZXIuCiAqCiAqIEBwYXJhbSBzdHJpbmcgJG5hbWUgVGFibGUgbmFtZSAobWF5IGluY2x1ZGUgc2NoZW1hIGFzICJzY2hlbWEudGFibGUiKQogKiBAcGFyYW0gbnVsbHxzdHJpbmcgJHNjaGVtYSBTY2hlbWEgbmFtZSAob3B0aW9uYWwsIG92ZXJyaWRlcyBwYXJzZWQgc2NoZW1hKQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1715,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGRlcml2ZWQgdGFibGUgKHN1YnF1ZXJ5IGluIEZST00gY2xhdXNlKS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1729,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIExBVEVSQUwgc3VicXVlcnkuCiAqCiAqIEBwYXJhbSBUYWJsZVJlZmVyZW5jZSAkcmVmZXJlbmNlIFRoZSBzdWJxdWVyeSBvciB0YWJsZSBmdW5jdGlvbiByZWZlcmVuY2UKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1741,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHRhYmxlIGZ1bmN0aW9uIHJlZmVyZW5jZS4KICoKICogQHBhcmFtIEZ1bmN0aW9uQ2FsbCAkZnVuY3Rpb24gVGhlIHRhYmxlLXZhbHVlZCBmdW5jdGlvbgogKiBAcGFyYW0gYm9vbCAkd2l0aE9yZGluYWxpdHkgV2hldGhlciB0byBhZGQgV0lUSCBPUkRJTkFMSVRZCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1760,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFZBTFVFUyBjbGF1c2UgYXMgYSB0YWJsZSByZWZlcmVuY2UuCiAqCiAqIFVzYWdlOgogKiAgIHNlbGVjdCgpLT5mcm9tKAogKiAgICAgICB2YWx1ZXNfdGFibGUoCiAqICAgICAgICAgICByb3dfZXhwcihbbGl0ZXJhbCgxKSwgbGl0ZXJhbCgnQWxpY2UnKV0pLAogKiAgICAgICAgICAgcm93X2V4cHIoW2xpdGVyYWwoMiksIGxpdGVyYWwoJ0JvYicpXSkKICogICAgICAgKS0+YXMoJ3QnLCBbJ2lkJywgJ25hbWUnXSkKICogICApCiAqCiAqIEdlbmVyYXRlczogU0VMRUNUICogRlJPTSAoVkFMVUVTICgxLCAnQWxpY2UnKSwgKDIsICdCb2InKSkgQVMgdChpZCwgbmFtZSkKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1769,"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}],"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBPUkRFUiBCWSBpdGVtLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1781,"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}],"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBPUkRFUiBCWSBpdGVtIHdpdGggQVNDIGRpcmVjdGlvbi4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1790,"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}],"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBPUkRFUiBCWSBpdGVtIHdpdGggREVTQyBkaXJlY3Rpb24uCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1804,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENURSAoQ29tbW9uIFRhYmxlIEV4cHJlc3Npb24pLgogKgogKiBAcGFyYW0gc3RyaW5nICRuYW1lIENURSBuYW1lCiAqIEBwYXJhbSBTZWxlY3RGaW5hbFN0ZXAgJHF1ZXJ5IENURSBxdWVyeQogKiBAcGFyYW0gYXJyYXk8c3RyaW5nPiAkY29sdW1uTmFtZXMgQ29sdW1uIGFsaWFzZXMgKG9wdGlvbmFsKQogKiBAcGFyYW0gQ1RFTWF0ZXJpYWxpemF0aW9uICRtYXRlcmlhbGl6YXRpb24gTWF0ZXJpYWxpemF0aW9uIGhpbnQKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1826,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHdpbmRvdyBkZWZpbml0aW9uIGZvciBXSU5ET1cgY2xhdXNlLgogKgogKiBAcGFyYW0gc3RyaW5nICRuYW1lIFdpbmRvdyBuYW1lCiAqIEBwYXJhbSBsaXN0PEV4cHJlc3Npb24+ICRwYXJ0aXRpb25CeSBQQVJUSVRJT04gQlkgZXhwcmVzc2lvbnMKICogQHBhcmFtIGxpc3Q8T3JkZXJCeT4gJG9yZGVyQnkgT1JERVIgQlkgaXRlbXMKICogQHBhcmFtIG51bGx8V2luZG93RnJhbWUgJGZyYW1lIFdpbmRvdyBmcmFtZSBzcGVjaWZpY2F0aW9uCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1839,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHdpbmRvdyBmcmFtZSBzcGVjaWZpY2F0aW9uLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1852,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGZyYW1lIGJvdW5kIGZvciBDVVJSRU5UIFJPVy4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1861,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGZyYW1lIGJvdW5kIGZvciBVTkJPVU5ERUQgUFJFQ0VESU5HLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1870,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGZyYW1lIGJvdW5kIGZvciBVTkJPVU5ERUQgRk9MTE9XSU5HLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1879,"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}],"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGZyYW1lIGJvdW5kIGZvciBOIFBSRUNFRElORy4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1888,"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}],"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGZyYW1lIGJvdW5kIGZvciBOIEZPTExPV0lORy4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1901,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGxvY2tpbmcgY2xhdXNlIChGT1IgVVBEQVRFLCBGT1IgU0hBUkUsIGV0Yy4pLgogKgogKiBAcGFyYW0gTG9ja1N0cmVuZ3RoICRzdHJlbmd0aCBMb2NrIHN0cmVuZ3RoCiAqIEBwYXJhbSBsaXN0PHN0cmluZz4gJHRhYmxlcyBUYWJsZXMgdG8gbG9jayAoZW1wdHkgZm9yIGFsbCkKICogQHBhcmFtIExvY2tXYWl0UG9saWN5ICR3YWl0UG9saWN5IFdhaXQgcG9saWN5CiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1915,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEZPUiBVUERBVEUgbG9ja2luZyBjbGF1c2UuCiAqCiAqIEBwYXJhbSBsaXN0PHN0cmluZz4gJHRhYmxlcyBUYWJsZXMgdG8gbG9jayAoZW1wdHkgZm9yIGFsbCkKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1926,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEZPUiBTSEFSRSBsb2NraW5nIGNsYXVzZS4KICoKICogQHBhcmFtIGxpc3Q8c3RyaW5nPiAkdGFibGVzIFRhYmxlcyB0byBsb2NrIChlbXB0eSBmb3IgYWxsKQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1935,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBPTiBDT05GTElDVCBETyBOT1RISU5HIGNsYXVzZS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1947,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBPTiBDT05GTElDVCBETyBVUERBVEUgY2xhdXNlLgogKgogKiBAcGFyYW0gQ29uZmxpY3RUYXJnZXQgJHRhcmdldCBDb25mbGljdCB0YXJnZXQgKGNvbHVtbnMgb3IgY29uc3RyYWludCkKICogQHBhcmFtIGFycmF5PHN0cmluZywgRXhwcmVzc2lvbj4gJHVwZGF0ZXMgQ29sdW1uIHVwZGF0ZXMKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1958,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGNvbmZsaWN0IHRhcmdldCBmb3IgT04gQ09ORkxJQ1QgKGNvbHVtbnMpLgogKgogKiBAcGFyYW0gbGlzdDxzdHJpbmc+ICRjb2x1bW5zIENvbHVtbnMgdGhhdCBkZWZpbmUgdW5pcXVlbmVzcwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1967,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGNvbmZsaWN0IHRhcmdldCBmb3IgT04gQ09ORkxJQ1QgT04gQ09OU1RSQUlOVC4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1978,"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}],"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFJFVFVSTklORyBjbGF1c2UuCiAqCiAqIEBwYXJhbSBFeHByZXNzaW9uIC4uLiRleHByZXNzaW9ucyBFeHByZXNzaW9ucyB0byByZXR1cm4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1987,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFJFVFVSTklORyAqIGNsYXVzZS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1999,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEJFR0lOIHRyYW5zYWN0aW9uIGJ1aWxkZXIuCiAqCiAqIEV4YW1wbGU6IGJlZ2luKCktPmlzb2xhdGlvbkxldmVsKElzb2xhdGlvbkxldmVsOjpTRVJJQUxJWkFCTEUpLT5yZWFkT25seSgpCiAqIFByb2R1Y2VzOiBCRUdJTiBJU09MQVRJT04gTEVWRUwgU0VSSUFMSVpBQkxFIFJFQUQgT05MWQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2011,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENPTU1JVCB0cmFuc2FjdGlvbiBidWlsZGVyLgogKgogKiBFeGFtcGxlOiBjb21taXQoKS0+YW5kQ2hhaW4oKQogKiBQcm9kdWNlczogQ09NTUlUIEFORCBDSEFJTgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2023,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFJPTExCQUNLIHRyYW5zYWN0aW9uIGJ1aWxkZXIuCiAqCiAqIEV4YW1wbGU6IHJvbGxiYWNrKCktPnRvU2F2ZXBvaW50KCdteV9zYXZlcG9pbnQnKQogKiBQcm9kdWNlczogUk9MTEJBQ0sgVE8gU0FWRVBPSU5UIG15X3NhdmVwb2ludAogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2035,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFNBVkVQT0lOVC4KICoKICogRXhhbXBsZTogc2F2ZXBvaW50KCdteV9zYXZlcG9pbnQnKQogKiBQcm9kdWNlczogU0FWRVBPSU5UIG15X3NhdmVwb2ludAogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2047,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFJlbGVhc2UgYSBTQVZFUE9JTlQuCiAqCiAqIEV4YW1wbGU6IHJlbGVhc2Vfc2F2ZXBvaW50KCdteV9zYXZlcG9pbnQnKQogKiBQcm9kdWNlczogUkVMRUFTRSBteV9zYXZlcG9pbnQKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2059,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFNFVCBUUkFOU0FDVElPTiBidWlsZGVyLgogKgogKiBFeGFtcGxlOiBzZXRfdHJhbnNhY3Rpb24oKS0+aXNvbGF0aW9uTGV2ZWwoSXNvbGF0aW9uTGV2ZWw6OlNFUklBTElaQUJMRSktPnJlYWRPbmx5KCkKICogUHJvZHVjZXM6IFNFVCBUUkFOU0FDVElPTiBJU09MQVRJT04gTEVWRUwgU0VSSUFMSVpBQkxFLCBSRUFEIE9OTFkKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2071,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFNFVCBTRVNTSU9OIENIQVJBQ1RFUklTVElDUyBBUyBUUkFOU0FDVElPTiBidWlsZGVyLgogKgogKiBFeGFtcGxlOiBzZXRfc2Vzc2lvbl90cmFuc2FjdGlvbigpLT5pc29sYXRpb25MZXZlbChJc29sYXRpb25MZXZlbDo6U0VSSUFMSVpBQkxFKQogKiBQcm9kdWNlczogU0VUIFNFU1NJT04gQ0hBUkFDVEVSSVNUSUNTIEFTIFRSQU5TQUNUSU9OIElTT0xBVElPTiBMRVZFTCBTRVJJQUxJWkFCTEUKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2083,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFNFVCBUUkFOU0FDVElPTiBTTkFQU0hPVCBidWlsZGVyLgogKgogKiBFeGFtcGxlOiB0cmFuc2FjdGlvbl9zbmFwc2hvdCgnMDAwMDAwMDMtMDAwMDAwMUEtMScpCiAqIFByb2R1Y2VzOiBTRVQgVFJBTlNBQ1RJT04gU05BUFNIT1QgJzAwMDAwMDAzLTAwMDAwMDFBLTEnCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2095,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBSRVBBUkUgVFJBTlNBQ1RJT04gYnVpbGRlci4KICoKICogRXhhbXBsZTogcHJlcGFyZV90cmFuc2FjdGlvbignbXlfdHJhbnNhY3Rpb24nKQogKiBQcm9kdWNlczogUFJFUEFSRSBUUkFOU0FDVElPTiAnbXlfdHJhbnNhY3Rpb24nCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2107,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENPTU1JVCBQUkVQQVJFRCBidWlsZGVyLgogKgogKiBFeGFtcGxlOiBjb21taXRfcHJlcGFyZWQoJ215X3RyYW5zYWN0aW9uJykKICogUHJvZHVjZXM6IENPTU1JVCBQUkVQQVJFRCAnbXlfdHJhbnNhY3Rpb24nCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2119,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFJPTExCQUNLIFBSRVBBUkVEIGJ1aWxkZXIuCiAqCiAqIEV4YW1wbGU6IHJvbGxiYWNrX3ByZXBhcmVkKCdteV90cmFuc2FjdGlvbicpCiAqIFByb2R1Y2VzOiBST0xMQkFDSyBQUkVQQVJFRCAnbXlfdHJhbnNhY3Rpb24nCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2142,"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":"SqlQuery","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}],"return_type":[{"name":"DeclareCursorOptionsStep","namespace":"Flow\\PostgreSql\\QueryBuilder\\Cursor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIERlY2xhcmUgYSBzZXJ2ZXItc2lkZSBjdXJzb3IgZm9yIGEgcXVlcnkuCiAqCiAqIEN1cnNvcnMgbXVzdCBiZSBkZWNsYXJlZCB3aXRoaW4gYSB0cmFuc2FjdGlvbiBhbmQgcHJvdmlkZSBtZW1vcnktZWZmaWNpZW50CiAqIGl0ZXJhdGlvbiBvdmVyIGxhcmdlIHJlc3VsdCBzZXRzIHZpYSBGRVRDSCBjb21tYW5kcy4KICoKICogRXhhbXBsZSB3aXRoIHF1ZXJ5IGJ1aWxkZXI6CiAqICAgZGVjbGFyZV9jdXJzb3IoJ215X2N1cnNvcicsIHNlbGVjdChzdGFyKCkpLT5mcm9tKHRhYmxlKCd1c2VycycpKSktPm5vU2Nyb2xsKCkKICogICBQcm9kdWNlczogREVDTEFSRSBteV9jdXJzb3IgTk8gU0NST0xMIENVUlNPUiBGT1IgU0VMRUNUICogRlJPTSB1c2VycwogKgogKiBFeGFtcGxlIHdpdGggcmF3IFNRTDoKICogICBkZWNsYXJlX2N1cnNvcignbXlfY3Vyc29yJywgJ1NFTEVDVCAqIEZST00gdXNlcnMgV0hFUkUgYWN0aXZlID0gdHJ1ZScpLT53aXRoSG9sZCgpCiAqICAgUHJvZHVjZXM6IERFQ0xBUkUgbXlfY3Vyc29yIE5PIFNDUk9MTCBDVVJTT1IgV0lUSCBIT0xEIEZPUiBTRUxFQ1QgKiBGUk9NIHVzZXJzIFdIRVJFIGFjdGl2ZSA9IHRydWUKICoKICogQHBhcmFtIHN0cmluZyAkY3Vyc29yTmFtZSBVbmlxdWUgY3Vyc29yIG5hbWUKICogQHBhcmFtIFNlbGVjdEZpbmFsU3RlcHxTcWxRdWVyeXxzdHJpbmcgJHF1ZXJ5IFF1ZXJ5IHRvIGl0ZXJhdGUgb3ZlcgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2163,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEZldGNoIHJvd3MgZnJvbSBhIGN1cnNvci4KICoKICogRXhhbXBsZTogZmV0Y2goJ215X2N1cnNvcicpLT5mb3J3YXJkKDEwMCkKICogUHJvZHVjZXM6IEZFVENIIEZPUldBUkQgMTAwIG15X2N1cnNvcgogKgogKiBFeGFtcGxlOiBmZXRjaCgnbXlfY3Vyc29yJyktPmFsbCgpCiAqIFByb2R1Y2VzOiBGRVRDSCBBTEwgbXlfY3Vyc29yCiAqCiAqIEBwYXJhbSBzdHJpbmcgJGN1cnNvck5hbWUgQ3Vyc29yIHRvIGZldGNoIGZyb20KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2180,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENsb3NlIGEgY3Vyc29yLgogKgogKiBFeGFtcGxlOiBjbG9zZV9jdXJzb3IoJ215X2N1cnNvcicpCiAqIFByb2R1Y2VzOiBDTE9TRSBteV9jdXJzb3IKICoKICogRXhhbXBsZTogY2xvc2VfY3Vyc29yKCkgLSBjbG9zZXMgYWxsIGN1cnNvcnMKICogUHJvZHVjZXM6IENMT1NFIEFMTAogKgogKiBAcGFyYW0gbnVsbHxzdHJpbmcgJGN1cnNvck5hbWUgQ3Vyc29yIHRvIGNsb3NlLCBvciBudWxsIHRvIGNsb3NlIGFsbAogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2196,"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":"DataType","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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGNvbHVtbiBkZWZpbml0aW9uIGZvciBDUkVBVEUgVEFCTEUuCiAqCiAqIEBwYXJhbSBzdHJpbmcgJG5hbWUgQ29sdW1uIG5hbWUKICogQHBhcmFtIERhdGFUeXBlICR0eXBlIENvbHVtbiBkYXRhIHR5cGUKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2207,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBSSU1BUlkgS0VZIGNvbnN0cmFpbnQuCiAqCiAqIEBwYXJhbSBzdHJpbmcgLi4uJGNvbHVtbnMgQ29sdW1ucyB0aGF0IGZvcm0gdGhlIHByaW1hcnkga2V5CiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2218,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFVOSVFVRSBjb25zdHJhaW50LgogKgogKiBAcGFyYW0gc3RyaW5nIC4uLiRjb2x1bW5zIENvbHVtbnMgdGhhdCBtdXN0IGJlIHVuaXF1ZSB0b2dldGhlcgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2231,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEZPUkVJR04gS0VZIGNvbnN0cmFpbnQuCiAqCiAqIEBwYXJhbSBsaXN0PHN0cmluZz4gJGNvbHVtbnMgTG9jYWwgY29sdW1ucwogKiBAcGFyYW0gc3RyaW5nICRyZWZlcmVuY2VUYWJsZSBSZWZlcmVuY2VkIHRhYmxlCiAqIEBwYXJhbSBsaXN0PHN0cmluZz4gJHJlZmVyZW5jZUNvbHVtbnMgUmVmZXJlbmNlZCBjb2x1bW5zIChkZWZhdWx0cyB0byBzYW1lIGFzICRjb2x1bW5zIGlmIGVtcHR5KQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2242,"slug":"check-constraint","name":"check_constraint","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}],"return_type":[{"name":"CheckConstraint","namespace":"Flow\\PostgreSql\\QueryBuilder\\Schema\\Constraint","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENIRUNLIGNvbnN0cmFpbnQuCiAqCiAqIEBwYXJhbSBzdHJpbmcgJGV4cHJlc3Npb24gU1FMIGV4cHJlc3Npb24gdGhhdCBtdXN0IGV2YWx1YXRlIHRvIHRydWUKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2273,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGZhY3RvcnkgZm9yIGJ1aWxkaW5nIENSRUFURSBzdGF0ZW1lbnRzLgogKgogKiBQcm92aWRlcyBhIHVuaWZpZWQgZW50cnkgcG9pbnQgZm9yIGFsbCBDUkVBVEUgb3BlcmF0aW9uczoKICogLSBjcmVhdGUoKS0+dGFibGUoKSAtIENSRUFURSBUQUJMRQogKiAtIGNyZWF0ZSgpLT50YWJsZUFzKCkgLSBDUkVBVEUgVEFCTEUgQVMKICogLSBjcmVhdGUoKS0+aW5kZXgoKSAtIENSRUFURSBJTkRFWAogKiAtIGNyZWF0ZSgpLT52aWV3KCkgLSBDUkVBVEUgVklFVwogKiAtIGNyZWF0ZSgpLT5tYXRlcmlhbGl6ZWRWaWV3KCkgLSBDUkVBVEUgTUFURVJJQUxJWkVEIFZJRVcKICogLSBjcmVhdGUoKS0+c2VxdWVuY2UoKSAtIENSRUFURSBTRVFVRU5DRQogKiAtIGNyZWF0ZSgpLT5zY2hlbWEoKSAtIENSRUFURSBTQ0hFTUEKICogLSBjcmVhdGUoKS0+cm9sZSgpIC0gQ1JFQVRFIFJPTEUKICogLSBjcmVhdGUoKS0+ZnVuY3Rpb24oKSAtIENSRUFURSBGVU5DVElPTgogKiAtIGNyZWF0ZSgpLT5wcm9jZWR1cmUoKSAtIENSRUFURSBQUk9DRURVUkUKICogLSBjcmVhdGUoKS0+dHJpZ2dlcigpIC0gQ1JFQVRFIFRSSUdHRVIKICogLSBjcmVhdGUoKS0+cnVsZSgpIC0gQ1JFQVRFIFJVTEUKICogLSBjcmVhdGUoKS0+ZXh0ZW5zaW9uKCkgLSBDUkVBVEUgRVhURU5TSU9OCiAqIC0gY3JlYXRlKCktPmNvbXBvc2l0ZVR5cGUoKSAtIENSRUFURSBUWVBFIChjb21wb3NpdGUpCiAqIC0gY3JlYXRlKCktPmVudW1UeXBlKCkgLSBDUkVBVEUgVFlQRSAoZW51bSkKICogLSBjcmVhdGUoKS0+cmFuZ2VUeXBlKCkgLSBDUkVBVEUgVFlQRSAocmFuZ2UpCiAqIC0gY3JlYXRlKCktPmRvbWFpbigpIC0gQ1JFQVRFIERPTUFJTgogKgogKiBFeGFtcGxlOiBjcmVhdGUoKS0+dGFibGUoJ3VzZXJzJyktPmNvbHVtbnMoY29sX2RlZignaWQnLCBkYXRhX3R5cGVfc2VyaWFsKCkpKQogKiBFeGFtcGxlOiBjcmVhdGUoKS0+aW5kZXgoJ2lkeF9lbWFpbCcpLT5vbigndXNlcnMnKS0+Y29sdW1ucygnZW1haWwnKQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2302,"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\\ETL\\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\/functions.php","start_line_in_file":2336,"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\\ETL\\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+YWRkQ29sdW1uKGNvbF9kZWYoJ2VtYWlsJywgZGF0YV90eXBlX3RleHQoKSkpCiAqIEV4YW1wbGU6IGFsdGVyKCktPnNlcXVlbmNlKCd1c2VyX2lkX3NlcScpLT5yZXN0YXJ0KDEwMDApCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2347,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFRSVU5DQVRFIFRBQkxFIGJ1aWxkZXIuCiAqCiAqIEBwYXJhbSBzdHJpbmcgLi4uJHRhYmxlcyBUYWJsZSBuYW1lcyB0byB0cnVuY2F0ZQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2365,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFJFRlJFU0ggTUFURVJJQUxJWkVEIFZJRVcgYnVpbGRlci4KICoKICogRXhhbXBsZTogcmVmcmVzaF9tYXRlcmlhbGl6ZWRfdmlldygndXNlcl9zdGF0cycpCiAqIFByb2R1Y2VzOiBSRUZSRVNIIE1BVEVSSUFMSVpFRCBWSUVXIHVzZXJfc3RhdHMKICoKICogRXhhbXBsZTogcmVmcmVzaF9tYXRlcmlhbGl6ZWRfdmlldygndXNlcl9zdGF0cycpLT5jb25jdXJyZW50bHkoKS0+d2l0aERhdGEoKQogKiBQcm9kdWNlczogUkVGUkVTSCBNQVRFUklBTElaRUQgVklFVyBDT05DVVJSRU5UTFkgdXNlcl9zdGF0cyBXSVRIIERBVEEKICoKICogQHBhcmFtIHN0cmluZyAkbmFtZSBWaWV3IG5hbWUgKG1heSBpbmNsdWRlIHNjaGVtYSBhcyAic2NoZW1hLnZpZXciKQogKiBAcGFyYW0gbnVsbHxzdHJpbmcgJHNjaGVtYSBTY2hlbWEgbmFtZSAob3B0aW9uYWwsIG92ZXJyaWRlcyBwYXJzZWQgc2NoZW1hKQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2374,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEdldCBhIENBU0NBREUgcmVmZXJlbnRpYWwgYWN0aW9uLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2383,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEdldCBhIFJFU1RSSUNUIHJlZmVyZW50aWFsIGFjdGlvbi4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2392,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEdldCBhIFNFVCBOVUxMIHJlZmVyZW50aWFsIGFjdGlvbi4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2401,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEdldCBhIFNFVCBERUZBVUxUIHJlZmVyZW50aWFsIGFjdGlvbi4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2410,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEdldCBhIE5PIEFDVElPTiByZWZlcmVudGlhbCBhY3Rpb24uCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2425,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFN0YXJ0IGJ1aWxkaW5nIGEgUkVJTkRFWCBJTkRFWCBzdGF0ZW1lbnQuCiAqCiAqIFVzZSBjaGFpbmFibGUgbWV0aG9kczogLT5jb25jdXJyZW50bHkoKSwgLT52ZXJib3NlKCksIC0+dGFibGVzcGFjZSgpCiAqCiAqIEV4YW1wbGU6IHJlaW5kZXhfaW5kZXgoJ2lkeF91c2Vyc19lbWFpbCcpLT5jb25jdXJyZW50bHkoKQogKgogKiBAcGFyYW0gc3RyaW5nICRuYW1lIFRoZSBpbmRleCBuYW1lIChtYXkgaW5jbHVkZSBzY2hlbWE6IHNjaGVtYS5pbmRleCkKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2440,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFN0YXJ0IGJ1aWxkaW5nIGEgUkVJTkRFWCBUQUJMRSBzdGF0ZW1lbnQuCiAqCiAqIFVzZSBjaGFpbmFibGUgbWV0aG9kczogLT5jb25jdXJyZW50bHkoKSwgLT52ZXJib3NlKCksIC0+dGFibGVzcGFjZSgpCiAqCiAqIEV4YW1wbGU6IHJlaW5kZXhfdGFibGUoJ3VzZXJzJyktPmNvbmN1cnJlbnRseSgpCiAqCiAqIEBwYXJhbSBzdHJpbmcgJG5hbWUgVGhlIHRhYmxlIG5hbWUgKG1heSBpbmNsdWRlIHNjaGVtYTogc2NoZW1hLnRhYmxlKQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2455,"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\\ETL\\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\/functions.php","start_line_in_file":2470,"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\\ETL\\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\/functions.php","start_line_in_file":2485,"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\\ETL\\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\/functions.php","start_line_in_file":2500,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBpbmRleCBjb2x1bW4gc3BlY2lmaWNhdGlvbiBmcm9tIGFuIGV4cHJlc3Npb24uCiAqCiAqIFVzZSBjaGFpbmFibGUgbWV0aG9kczogLT5hc2MoKSwgLT5kZXNjKCksIC0+bnVsbHNGaXJzdCgpLCAtPm51bGxzTGFzdCgpLCAtPm9wY2xhc3MoKSwgLT5jb2xsYXRlKCkKICoKICogRXhhbXBsZTogaW5kZXhfZXhwcihmbl9jYWxsKCdsb3dlcicsIGNvbCgnZW1haWwnKSkpLT5kZXNjKCkKICoKICogQHBhcmFtIEV4cHJlc3Npb24gJGV4cHJlc3Npb24gVGhlIGV4cHJlc3Npb24gdG8gaW5kZXgKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2509,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEdldCB0aGUgQlRSRUUgaW5kZXggbWV0aG9kLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2518,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEdldCB0aGUgSEFTSCBpbmRleCBtZXRob2QuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2527,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEdldCB0aGUgR0lTVCBpbmRleCBtZXRob2QuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2536,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEdldCB0aGUgU1BHSVNUIGluZGV4IG1ldGhvZC4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2545,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEdldCB0aGUgR0lOIGluZGV4IG1ldGhvZC4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2554,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEdldCB0aGUgQlJJTiBpbmRleCBtZXRob2QuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2566,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFZBQ1VVTSBidWlsZGVyLgogKgogKiBFeGFtcGxlOiB2YWN1dW0oKS0+dGFibGUoJ3VzZXJzJykKICogUHJvZHVjZXM6IFZBQ1VVTSB1c2VycwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2578,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBBTkFMWVpFIGJ1aWxkZXIuCiAqCiAqIEV4YW1wbGU6IGFuYWx5emUoKS0+dGFibGUoJ3VzZXJzJykKICogUHJvZHVjZXM6IEFOQUxZWkUgdXNlcnMKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2592,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBFWFBMQUlOIGJ1aWxkZXIgZm9yIGEgcXVlcnkuCiAqCiAqIEV4YW1wbGU6IGV4cGxhaW4oc2VsZWN0KCktPmZyb20oJ3VzZXJzJykpCiAqIFByb2R1Y2VzOiBFWFBMQUlOIFNFTEVDVCAqIEZST00gdXNlcnMKICoKICogQHBhcmFtIERlbGV0ZUJ1aWxkZXJ8SW5zZXJ0QnVpbGRlcnxTZWxlY3RGaW5hbFN0ZXB8VXBkYXRlQnVpbGRlciAkcXVlcnkgUXVlcnkgdG8gZXhwbGFpbgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2604,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIExPQ0sgVEFCTEUgYnVpbGRlci4KICoKICogRXhhbXBsZTogbG9ja190YWJsZSgndXNlcnMnLCAnb3JkZXJzJyktPmFjY2Vzc0V4Y2x1c2l2ZSgpCiAqIFByb2R1Y2VzOiBMT0NLIFRBQkxFIHVzZXJzLCBvcmRlcnMgSU4gQUNDRVNTIEVYQ0xVU0lWRSBNT0RFCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2619,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENPTU1FTlQgT04gYnVpbGRlci4KICoKICogRXhhbXBsZTogY29tbWVudChDb21tZW50VGFyZ2V0OjpUQUJMRSwgJ3VzZXJzJyktPmlzKCdVc2VyIGFjY291bnRzIHRhYmxlJykKICogUHJvZHVjZXM6IENPTU1FTlQgT04gVEFCTEUgdXNlcnMgSVMgJ1VzZXIgYWNjb3VudHMgdGFibGUnCiAqCiAqIEBwYXJhbSBDb21tZW50VGFyZ2V0ICR0YXJnZXQgVGFyZ2V0IHR5cGUgKFRBQkxFLCBDT0xVTU4sIElOREVYLCBldGMuKQogKiBAcGFyYW0gc3RyaW5nICRuYW1lIFRhcmdldCBuYW1lICh1c2UgJ3RhYmxlLmNvbHVtbicgZm9yIENPTFVNTiB0YXJnZXRzKQogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2631,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENMVVNURVIgYnVpbGRlci4KICoKICogRXhhbXBsZTogY2x1c3RlcigpLT50YWJsZSgndXNlcnMnKS0+dXNpbmcoJ2lkeF91c2Vyc19wa2V5JykKICogUHJvZHVjZXM6IENMVVNURVIgdXNlcnMgVVNJTkcgaWR4X3VzZXJzX3BrZXkKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2645,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIERJU0NBUkQgYnVpbGRlci4KICoKICogRXhhbXBsZTogZGlzY2FyZChEaXNjYXJkVHlwZTo6QUxMKQogKiBQcm9kdWNlczogRElTQ0FSRCBBTEwKICoKICogQHBhcmFtIERpc2NhcmRUeXBlICR0eXBlIFR5cGUgb2YgcmVzb3VyY2VzIHRvIGRpc2NhcmQgKEFMTCwgUExBTlMsIFNFUVVFTkNFUywgVEVNUCkKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2664,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEdSQU5UIHByaXZpbGVnZXMgYnVpbGRlci4KICoKICogRXhhbXBsZTogZ3JhbnQoVGFibGVQcml2aWxlZ2U6OlNFTEVDVCktPm9uVGFibGUoJ3VzZXJzJyktPnRvKCdhcHBfdXNlcicpCiAqIFByb2R1Y2VzOiBHUkFOVCBTRUxFQ1QgT04gdXNlcnMgVE8gYXBwX3VzZXIKICoKICogRXhhbXBsZTogZ3JhbnQoVGFibGVQcml2aWxlZ2U6OkFMTCktPm9uQWxsVGFibGVzSW5TY2hlbWEoJ3B1YmxpYycpLT50bygnYWRtaW4nKQogKiBQcm9kdWNlczogR1JBTlQgQUxMIE9OIEFMTCBUQUJMRVMgSU4gU0NIRU1BIHB1YmxpYyBUTyBhZG1pbgogKgogKiBAcGFyYW0gc3RyaW5nfFRhYmxlUHJpdmlsZWdlIC4uLiRwcml2aWxlZ2VzIFRoZSBwcml2aWxlZ2VzIHRvIGdyYW50CiAqCiAqIEByZXR1cm4gR3JhbnRPblN0ZXAgQnVpbGRlciBmb3IgZ3JhbnQgb3B0aW9ucwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2683,"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\\ETL\\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\/functions.php","start_line_in_file":2702,"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\\ETL\\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\/functions.php","start_line_in_file":2721,"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\\ETL\\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\/functions.php","start_line_in_file":2737,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFNFVCBST0xFIGJ1aWxkZXIuCiAqCiAqIEV4YW1wbGU6IHNldF9yb2xlKCdhZG1pbicpCiAqIFByb2R1Y2VzOiBTRVQgUk9MRSBhZG1pbgogKgogKiBAcGFyYW0gc3RyaW5nICRyb2xlIFRoZSByb2xlIHRvIHNldAogKgogKiBAcmV0dXJuIFNldFJvbGVGaW5hbFN0ZXAgQnVpbGRlciBmb3Igc2V0IHJvbGUKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2751,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFJFU0VUIFJPTEUgYnVpbGRlci4KICoKICogRXhhbXBsZTogcmVzZXRfcm9sZSgpCiAqIFByb2R1Y2VzOiBSRVNFVCBST0xFCiAqCiAqIEByZXR1cm4gUmVzZXRSb2xlRmluYWxTdGVwIEJ1aWxkZXIgZm9yIHJlc2V0IHJvbGUKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2767,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFJFQVNTSUdOIE9XTkVEIGJ1aWxkZXIuCiAqCiAqIEV4YW1wbGU6IHJlYXNzaWduX293bmVkKCdvbGRfcm9sZScpLT50bygnbmV3X3JvbGUnKQogKiBQcm9kdWNlczogUkVBU1NJR04gT1dORUQgQlkgb2xkX3JvbGUgVE8gbmV3X3JvbGUKICoKICogQHBhcmFtIHN0cmluZyAuLi4kcm9sZXMgVGhlIHJvbGVzIHdob3NlIG93bmVkIG9iamVjdHMgc2hvdWxkIGJlIHJlYXNzaWduZWQKICoKICogQHJldHVybiBSZWFzc2lnbk93bmVkVG9TdGVwIEJ1aWxkZXIgZm9yIHJlYXNzaWduIG93bmVkIG9wdGlvbnMKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2786,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIERST1AgT1dORUQgYnVpbGRlci4KICoKICogRXhhbXBsZTogZHJvcF9vd25lZCgncm9sZTEnKQogKiBQcm9kdWNlczogRFJPUCBPV05FRCBCWSByb2xlMQogKgogKiBFeGFtcGxlOiBkcm9wX293bmVkKCdyb2xlMScsICdyb2xlMicpLT5jYXNjYWRlKCkKICogUHJvZHVjZXM6IERST1AgT1dORUQgQlkgcm9sZTEsIHJvbGUyIENBU0NBREUKICoKICogQHBhcmFtIHN0cmluZyAuLi4kcm9sZXMgVGhlIHJvbGVzIHdob3NlIG93bmVkIG9iamVjdHMgc2hvdWxkIGJlIGRyb3BwZWQKICoKICogQHJldHVybiBEcm9wT3duZWRGaW5hbFN0ZXAgQnVpbGRlciBmb3IgZHJvcCBvd25lZCBvcHRpb25zCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2804,"slug":"func-arg","name":"func_arg","namespace":"Flow\\PostgreSql\\DSL","parameters":[{"name":"type","type":[{"name":"DataType","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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZXMgYSBuZXcgZnVuY3Rpb24gYXJndW1lbnQgZm9yIHVzZSBpbiBmdW5jdGlvbi9wcm9jZWR1cmUgZGVmaW5pdGlvbnMuCiAqCiAqIEV4YW1wbGU6IGZ1bmNfYXJnKGRhdGFfdHlwZV9pbnRlZ2VyKCkpCiAqIEV4YW1wbGU6IGZ1bmNfYXJnKGRhdGFfdHlwZV90ZXh0KCkpLT5uYW1lZCgndXNlcm5hbWUnKQogKiBFeGFtcGxlOiBmdW5jX2FyZyhkYXRhX3R5cGVfaW50ZWdlcigpKS0+bmFtZWQoJ2NvdW50JyktPmRlZmF1bHQoJzAnKQogKiBFeGFtcGxlOiBmdW5jX2FyZyhkYXRhX3R5cGVfdGV4dCgpKS0+b3V0KCkKICoKICogQHBhcmFtIERhdGFUeXBlICR0eXBlIFRoZSBQb3N0Z3JlU1FMIGRhdGEgdHlwZSBmb3IgdGhlIGFyZ3VtZW50CiAqCiAqIEByZXR1cm4gRnVuY3Rpb25Bcmd1bWVudCBCdWlsZGVyIGZvciBmdW5jdGlvbiBhcmd1bWVudCBvcHRpb25zCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2823,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZXMgYSBDQUxMIHN0YXRlbWVudCBidWlsZGVyIGZvciBpbnZva2luZyBhIHByb2NlZHVyZS4KICoKICogRXhhbXBsZTogY2FsbCgndXBkYXRlX3N0YXRzJyktPndpdGgoMTIzKQogKiBQcm9kdWNlczogQ0FMTCB1cGRhdGVfc3RhdHMoMTIzKQogKgogKiBFeGFtcGxlOiBjYWxsKCdwcm9jZXNzX2RhdGEnKS0+d2l0aCgndGVzdCcsIDQyLCB0cnVlKQogKiBQcm9kdWNlczogQ0FMTCBwcm9jZXNzX2RhdGEoJ3Rlc3QnLCA0MiwgdHJ1ZSkKICoKICogQHBhcmFtIHN0cmluZyAkcHJvY2VkdXJlIFRoZSBuYW1lIG9mIHRoZSBwcm9jZWR1cmUgdG8gY2FsbAogKgogKiBAcmV0dXJuIENhbGxGaW5hbFN0ZXAgQnVpbGRlciBmb3IgY2FsbCBzdGF0ZW1lbnQgb3B0aW9ucwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2842,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZXMgYSBETyBzdGF0ZW1lbnQgYnVpbGRlciBmb3IgZXhlY3V0aW5nIGFuIGFub255bW91cyBjb2RlIGJsb2NrLgogKgogKiBFeGFtcGxlOiBkb19ibG9jaygnQkVHSU4gUkFJU0UgTk9USUNFICQkSGVsbG8gV29ybGQkJDsgRU5EOycpCiAqIFByb2R1Y2VzOiBETyAkJCBCRUdJTiBSQUlTRSBOT1RJQ0UgJCRIZWxsbyBXb3JsZCQkOyBFTkQ7ICQkIExBTkdVQUdFIHBscGdzcWwKICoKICogRXhhbXBsZTogZG9fYmxvY2soJ1NFTEVDVCAxJyktPmxhbmd1YWdlKCdzcWwnKQogKiBQcm9kdWNlczogRE8gJCQgU0VMRUNUIDEgJCQgTEFOR1VBR0Ugc3FsCiAqCiAqIEBwYXJhbSBzdHJpbmcgJGNvZGUgVGhlIGFub255bW91cyBjb2RlIGJsb2NrIHRvIGV4ZWN1dGUKICoKICogQHJldHVybiBEb0ZpbmFsU3RlcCBCdWlsZGVyIGZvciBETyBzdGF0ZW1lbnQgb3B0aW9ucwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2862,"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":"DataType","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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZXMgYSB0eXBlIGF0dHJpYnV0ZSBmb3IgY29tcG9zaXRlIHR5cGVzLgogKgogKiBFeGFtcGxlOiB0eXBlX2F0dHIoJ25hbWUnLCBkYXRhX3R5cGVfdGV4dCgpKQogKiBQcm9kdWNlczogbmFtZSB0ZXh0CiAqCiAqIEV4YW1wbGU6IHR5cGVfYXR0cignZGVzY3JpcHRpb24nLCBkYXRhX3R5cGVfdGV4dCgpKS0+Y29sbGF0ZSgnZW5fVVMnKQogKiBQcm9kdWNlczogZGVzY3JpcHRpb24gdGV4dCBDT0xMQVRFICJlbl9VUyIKICoKICogQHBhcmFtIHN0cmluZyAkbmFtZSBUaGUgYXR0cmlidXRlIG5hbWUKICogQHBhcmFtIERhdGFUeXBlICR0eXBlIFRoZSBhdHRyaWJ1dGUgdHlwZQogKgogKiBAcmV0dXJuIFR5cGVBdHRyaWJ1dGUgVHlwZSBhdHRyaWJ1dGUgdmFsdWUgb2JqZWN0CiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2879,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBjb25uZWN0aW9uIHBhcmFtZXRlcnMgZnJvbSBhIGNvbm5lY3Rpb24gc3RyaW5nLgogKgogKiBBY2NlcHRzIGxpYnBxLXN0eWxlIGNvbm5lY3Rpb24gc3RyaW5nczoKICogLSBLZXktdmFsdWUgZm9ybWF0OiAiaG9zdD1sb2NhbGhvc3QgcG9ydD01NDMyIGRibmFtZT1teWRiIHVzZXI9bXl1c2VyIHBhc3N3b3JkPXNlY3JldCIKICogLSBVUkkgZm9ybWF0OiAicG9zdGdyZXNxbDovL3VzZXI6cGFzc3dvcmRAbG9jYWxob3N0OjU0MzIvZGJuYW1lIgogKgogKiBAZXhhbXBsZQogKiAkcGFyYW1zID0gcGdzcWxfY29ubmVjdGlvbignaG9zdD1sb2NhbGhvc3QgZGJuYW1lPW15ZGInKTsKICogJHBhcmFtcyA9IHBnc3FsX2Nvbm5lY3Rpb24oJ3Bvc3RncmVzcWw6Ly91c2VyOnBhc3NAbG9jYWxob3N0L215ZGInKTsKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2901,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBjb25uZWN0aW9uIHBhcmFtZXRlcnMgZnJvbSBhIERTTiBzdHJpbmcuCiAqCiAqIFBhcnNlcyBzdGFuZGFyZCBQb3N0Z3JlU1FMIERTTiBmb3JtYXQgY29tbW9ubHkgdXNlZCBpbiBlbnZpcm9ubWVudCB2YXJpYWJsZXMKICogKGUuZy4sIERBVEFCQVNFX1VSTCkuIFN1cHBvcnRzIHBvc3RncmVzOi8vLCBwb3N0Z3Jlc3FsOi8vLCBhbmQgcGdzcWw6Ly8gc2NoZW1lcy4KICoKICogQHBhcmFtIHN0cmluZyAkZHNuIERTTiBzdHJpbmcgaW4gZm9ybWF0OiBwb3N0Z3JlczovL3VzZXI6cGFzc3dvcmRAaG9zdDpwb3J0L2RhdGFiYXNlP29wdGlvbnMKICoKICogQHRocm93cyBDbGllbnRcRHNuUGFyc2VyRXhjZXB0aW9uIElmIHRoZSBEU04gY2Fubm90IGJlIHBhcnNlZAogKgogKiBAZXhhbXBsZQogKiAkcGFyYW1zID0gcGdzcWxfY29ubmVjdGlvbl9kc24oJ3Bvc3RncmVzOi8vbXl1c2VyOnNlY3JldEBsb2NhbGhvc3Q6NTQzMi9teWRiJyk7CiAqICRwYXJhbXMgPSBwZ3NxbF9jb25uZWN0aW9uX2RzbigncG9zdGdyZXNxbDovL3VzZXI6cGFzc0BkYi5leGFtcGxlLmNvbS9hcHA\/c3NsbW9kZT1yZXF1aXJlJyk7CiAqICRwYXJhbXMgPSBwZ3NxbF9jb25uZWN0aW9uX2RzbigncGdzcWw6Ly91c2VyOnBhc3NAbG9jYWxob3N0L215ZGInKTsgLy8gU3ltZm9ueS9Eb2N0cmluZSBmb3JtYXQKICogJHBhcmFtcyA9IHBnc3FsX2Nvbm5lY3Rpb25fZHNuKGdldGVudignREFUQUJBU0VfVVJMJykpOwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2928,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBjb25uZWN0aW9uIHBhcmFtZXRlcnMgZnJvbSBpbmRpdmlkdWFsIHZhbHVlcy4KICoKICogQWxsb3dzIHNwZWNpZnlpbmcgY29ubmVjdGlvbiBwYXJhbWV0ZXJzIGluZGl2aWR1YWxseSBmb3IgYmV0dGVyIHR5cGUgc2FmZXR5CiAqIGFuZCBJREUgc3VwcG9ydC4KICoKICogQHBhcmFtIHN0cmluZyAkZGF0YWJhc2UgRGF0YWJhc2UgbmFtZSAocmVxdWlyZWQpCiAqIEBwYXJhbSBzdHJpbmcgJGhvc3QgSG9zdG5hbWUgKGRlZmF1bHQ6IGxvY2FsaG9zdCkKICogQHBhcmFtIGludCAkcG9ydCBQb3J0IG51bWJlciAoZGVmYXVsdDogNTQzMikKICogQHBhcmFtIG51bGx8c3RyaW5nICR1c2VyIFVzZXJuYW1lIChvcHRpb25hbCkKICogQHBhcmFtIG51bGx8c3RyaW5nICRwYXNzd29yZCBQYXNzd29yZCAob3B0aW9uYWwpCiAqIEBwYXJhbSBhcnJheTxzdHJpbmcsIHN0cmluZz4gJG9wdGlvbnMgQWRkaXRpb25hbCBsaWJwcSBvcHRpb25zCiAqCiAqIEBleGFtcGxlCiAqICRwYXJhbXMgPSBwZ3NxbF9jb25uZWN0aW9uX3BhcmFtcygKICogICAgIGRhdGFiYXNlOiAnbXlkYicsCiAqICAgICBob3N0OiAnbG9jYWxob3N0JywKICogICAgIHVzZXI6ICdteXVzZXInLAogKiAgICAgcGFzc3dvcmQ6ICdzZWNyZXQnLAogKiApOwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2969,"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":"mapper","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":"Client","namespace":"Flow\\PostgreSql\\Client","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBvc3RncmVTUUwgY2xpZW50IHVzaW5nIGV4dC1wZ3NxbC4KICoKICogVGhlIGNsaWVudCBjb25uZWN0cyBpbW1lZGlhdGVseSBhbmQgaXMgcmVhZHkgdG8gZXhlY3V0ZSBxdWVyaWVzLgogKiBGb3Igb2JqZWN0IG1hcHBpbmcsIHByb3ZpZGUgYSBSb3dNYXBwZXIgKHVzZSBwZ3NxbF9tYXBwZXIoKSBmb3IgdGhlIGRlZmF1bHQpLgogKgogKiBAcGFyYW0gQ2xpZW50XENvbm5lY3Rpb25QYXJhbWV0ZXJzICRwYXJhbXMgQ29ubmVjdGlvbiBwYXJhbWV0ZXJzCiAqIEBwYXJhbSBudWxsfFZhbHVlQ29udmVydGVycyAkdmFsdWVDb252ZXJ0ZXJzIEN1c3RvbSB0eXBlIGNvbnZlcnRlcnMgKG9wdGlvbmFsKQogKiBAcGFyYW0gbnVsbHxDbGllbnRcUm93TWFwcGVyICRtYXBwZXIgUm93IG1hcHBlciBmb3Igb2JqZWN0IGh5ZHJhdGlvbiAob3B0aW9uYWwpCiAqCiAqIEB0aHJvd3MgQ29ubmVjdGlvbkV4Y2VwdGlvbiBJZiBjb25uZWN0aW9uIGZhaWxzCiAqCiAqIEBleGFtcGxlCiAqIC8vIEJhc2ljIGNsaWVudAogKiAkY2xpZW50ID0gcGdzcWxfY2xpZW50KHBnc3FsX2Nvbm5lY3Rpb24oJ2hvc3Q9bG9jYWxob3N0IGRibmFtZT1teWRiJykpOwogKgogKiAvLyBXaXRoIG9iamVjdCBtYXBwaW5nCiAqICRjbGllbnQgPSBwZ3NxbF9jbGllbnQoCiAqICAgICBwZ3NxbF9jb25uZWN0aW9uKCdob3N0PWxvY2FsaG9zdCBkYm5hbWU9bXlkYicpLAogKiAgICAgbWFwcGVyOiBwZ3NxbF9tYXBwZXIoKSwKICogKTsKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3005,"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":"traceTransactions","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSB0ZWxlbWV0cnkgb3B0aW9ucyBmb3IgUG9zdGdyZVNRTCBjbGllbnQgaW5zdHJ1bWVudGF0aW9uLgogKgogKiBDb250cm9scyB3aGljaCB0ZWxlbWV0cnkgc2lnbmFscyAodHJhY2VzLCBtZXRyaWNzLCBsb2dzKSBhcmUgZW5hYmxlZAogKiBhbmQgaG93IHF1ZXJ5IGluZm9ybWF0aW9uIGlzIGNhcHR1cmVkLgogKgogKiBAcGFyYW0gYm9vbCAkdHJhY2VRdWVyaWVzIENyZWF0ZSBzcGFucyBmb3IgcXVlcnkgZXhlY3V0aW9uIChkZWZhdWx0OiB0cnVlKQogKiBAcGFyYW0gYm9vbCAkdHJhY2VUcmFuc2FjdGlvbnMgQ3JlYXRlIHNwYW5zIGZvciB0cmFuc2FjdGlvbnMgKGRlZmF1bHQ6IHRydWUpCiAqIEBwYXJhbSBib29sICRjb2xsZWN0TWV0cmljcyBDb2xsZWN0IGR1cmF0aW9uIGFuZCByb3cgY291bnQgbWV0cmljcyAoZGVmYXVsdDogdHJ1ZSkKICogQHBhcmFtIGJvb2wgJGxvZ1F1ZXJpZXMgTG9nIGV4ZWN1dGVkIHF1ZXJpZXMgKGRlZmF1bHQ6IGZhbHNlKQogKiBAcGFyYW0gbnVsbHxpbnQgJG1heFF1ZXJ5TGVuZ3RoIE1heGltdW0gcXVlcnkgdGV4dCBsZW5ndGggaW4gdGVsZW1ldHJ5IChkZWZhdWx0OiAxMDAwLCBudWxsID0gdW5saW1pdGVkKQogKiBAcGFyYW0gYm9vbCAkaW5jbHVkZVBhcmFtZXRlcnMgSW5jbHVkZSBxdWVyeSBwYXJhbWV0ZXJzIGluIHRlbGVtZXRyeSAoZGVmYXVsdDogZmFsc2UsIHNlY3VyaXR5IGNvbnNpZGVyYXRpb24pCiAqCiAqIEBleGFtcGxlCiAqIC8vIERlZmF1bHQgb3B0aW9ucyAodHJhY2VzIGFuZCBtZXRyaWNzIGVuYWJsZWQpCiAqICRvcHRpb25zID0gcG9zdGdyZXNxbF90ZWxlbWV0cnlfb3B0aW9ucygpOwogKgogKiAvLyBFbmFibGUgcXVlcnkgbG9nZ2luZwogKiAkb3B0aW9ucyA9IHBvc3RncmVzcWxfdGVsZW1ldHJ5X29wdGlvbnMobG9nUXVlcmllczogdHJ1ZSk7CiAqCiAqIC8vIERpc2FibGUgYWxsIGJ1dCBtZXRyaWNzCiAqICRvcHRpb25zID0gcG9zdGdyZXNxbF90ZWxlbWV0cnlfb3B0aW9ucygKICogICAgIHRyYWNlUXVlcmllczogZmFsc2UsCiAqICAgICB0cmFjZVRyYW5zYWN0aW9uczogZmFsc2UsCiAqICAgICBjb2xsZWN0TWV0cmljczogdHJ1ZSwKICogKTsKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3043,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSB0ZWxlbWV0cnkgY29uZmlndXJhdGlvbiBmb3IgUG9zdGdyZVNRTCBjbGllbnQuCiAqCiAqIEJ1bmRsZXMgdGVsZW1ldHJ5IGluc3RhbmNlLCBjbG9jaywgYW5kIG9wdGlvbnMgbmVlZGVkIHRvIGluc3RydW1lbnQgYSBQb3N0Z3JlU1FMIGNsaWVudC4KICoKICogQHBhcmFtIFRlbGVtZXRyeSAkdGVsZW1ldHJ5IFRoZSB0ZWxlbWV0cnkgaW5zdGFuY2UKICogQHBhcmFtIENsb2NrSW50ZXJmYWNlICRjbG9jayBDbG9jayBmb3IgdGltZXN0YW1wcwogKiBAcGFyYW0gbnVsbHxQb3N0Z3JlU3FsVGVsZW1ldHJ5T3B0aW9ucyAkb3B0aW9ucyBUZWxlbWV0cnkgb3B0aW9ucyAoZGVmYXVsdDogYWxsIGVuYWJsZWQpCiAqCiAqIEBleGFtcGxlCiAqICRjb25maWcgPSBwb3N0Z3Jlc3FsX3RlbGVtZXRyeV9jb25maWcoCiAqICAgICB0ZWxlbWV0cnkocmVzb3VyY2UoWydzZXJ2aWNlLm5hbWUnID0+ICdteS1hcHAnXSkpLAogKiAgICAgbmV3IFN5c3RlbUNsb2NrKCksCiAqICk7CiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3089,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFdyYXAgYSBQb3N0Z3JlU1FMIGNsaWVudCB3aXRoIHRlbGVtZXRyeSBpbnN0cnVtZW50YXRpb24uCiAqCiAqIFJldHVybnMgYSBkZWNvcmF0b3IgdGhhdCBhZGRzIHNwYW5zLCBtZXRyaWNzLCBhbmQgbG9ncyB0byBhbGwKICogcXVlcnkgYW5kIHRyYW5zYWN0aW9uIG9wZXJhdGlvbnMgZm9sbG93aW5nIE9wZW5UZWxlbWV0cnkgY29udmVudGlvbnMuCiAqCiAqIEBwYXJhbSBDbGllbnRcQ2xpZW50ICRjbGllbnQgVGhlIFBvc3RncmVTUUwgY2xpZW50IHRvIGluc3RydW1lbnQKICogQHBhcmFtIFBvc3RncmVTcWxUZWxlbWV0cnlDb25maWcgJHRlbGVtZXRyeUNvbmZpZyBUZWxlbWV0cnkgY29uZmlndXJhdGlvbgogKgogKiBAZXhhbXBsZQogKiAkY2xpZW50ID0gcGdzcWxfY2xpZW50KHBnc3FsX2Nvbm5lY3Rpb24oJ2hvc3Q9bG9jYWxob3N0IGRibmFtZT1teWRiJykpOwogKgogKiAkdHJhY2VhYmxlQ2xpZW50ID0gdHJhY2VhYmxlX3Bvc3RncmVzcWxfY2xpZW50KAogKiAgICAgJGNsaWVudCwKICogICAgIHBvc3RncmVzcWxfdGVsZW1ldHJ5X2NvbmZpZygKICogICAgICAgICB0ZWxlbWV0cnkocmVzb3VyY2UoWydzZXJ2aWNlLm5hbWUnID0+ICdteS1hcHAnXSkpLAogKiAgICAgICAgIG5ldyBTeXN0ZW1DbG9jaygpLAogKiAgICAgICAgIHBvc3RncmVzcWxfdGVsZW1ldHJ5X29wdGlvbnMoCiAqICAgICAgICAgICAgIHRyYWNlUXVlcmllczogdHJ1ZSwKICogICAgICAgICAgICAgdHJhY2VUcmFuc2FjdGlvbnM6IHRydWUsCiAqICAgICAgICAgICAgIGNvbGxlY3RNZXRyaWNzOiB0cnVlLAogKiAgICAgICAgICAgICBsb2dRdWVyaWVzOiB0cnVlLAogKiAgICAgICAgICAgICBtYXhRdWVyeUxlbmd0aDogNTAwLAogKiAgICAgICAgICksCiAqICAgICApLAogKiApOwogKgogKiAvLyBBbGwgb3BlcmF0aW9ucyBub3cgdHJhY2VkCiAqICR0cmFjZWFibGVDbGllbnQtPnRyYW5zYWN0aW9uKGZ1bmN0aW9uIChDbGllbnQgJGNsaWVudCkgewogKiAgICAgJHVzZXIgPSAkY2xpZW50LT5mZXRjaE9uZSgnU0VMRUNUICogRlJPTSB1c2VycyBXSEVSRSBpZCA9ICQxJywgWzEyM10pOwogKiAgICAgJGNsaWVudC0+ZXhlY3V0ZSgnVVBEQVRFIHVzZXJzIFNFVCBsYXN0X2xvZ2luID0gTk9XKCkgV0hFUkUgaWQgPSAkMScsIFsxMjNdKTsKICogfSk7CiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3124,"slug":"pgsql-mapper","name":"pgsql_mapper","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"ConstructorMapper","namespace":"Flow\\PostgreSql\\Client\\RowMapper","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGRlZmF1bHQgY29uc3RydWN0b3ItYmFzZWQgcm93IG1hcHBlci4KICoKICogTWFwcyBkYXRhYmFzZSByb3dzIGRpcmVjdGx5IHRvIGNvbnN0cnVjdG9yIHBhcmFtZXRlcnMuCiAqIENvbHVtbiBuYW1lcyBtdXN0IG1hdGNoIHBhcmFtZXRlciBuYW1lcyBleGFjdGx5ICgxOjEpLgogKiBVc2UgU1FMIGFsaWFzZXMgaWYgY29sdW1uIG5hbWVzIGRpZmZlciBmcm9tIHBhcmFtZXRlciBuYW1lcy4KICoKICogQGV4YW1wbGUKICogLy8gRFRPIHdoZXJlIGNvbHVtbiBuYW1lcyBtYXRjaCBwYXJhbWV0ZXIgbmFtZXMKICogcmVhZG9ubHkgY2xhc3MgVXNlciB7CiAqICAgICBwdWJsaWMgZnVuY3Rpb24gX19jb25zdHJ1Y3QoCiAqICAgICAgICAgcHVibGljIGludCAkaWQsCiAqICAgICAgICAgcHVibGljIHN0cmluZyAkbmFtZSwKICogICAgICAgICBwdWJsaWMgc3RyaW5nICRlbWFpbCwKICogICAgICkge30KICogfQogKgogKiAvLyBVc2FnZQogKiAkY2xpZW50ID0gcGdzcWxfY2xpZW50KHBnc3FsX2Nvbm5lY3Rpb24oJy4uLicpLCBtYXBwZXI6IHBnc3FsX21hcHBlcigpKTsKICoKICogLy8gRm9yIHNuYWtlX2Nhc2UgY29sdW1ucywgdXNlIFNRTCBhbGlhc2VzCiAqICR1c2VyID0gJGNsaWVudC0+ZmV0Y2hJbnRvKAogKiAgICAgVXNlcjo6Y2xhc3MsCiAqICAgICAnU0VMRUNUIGlkLCB1c2VyX25hbWUgQVMgbmFtZSwgdXNlcl9lbWFpbCBBUyBlbWFpbCBGUk9NIHVzZXJzIFdIRVJFIGlkID0gJDEnLAogKiAgICAgWzFdCiAqICk7CiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3153,"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":"PostgreSqlType","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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFdyYXAgYSB2YWx1ZSB3aXRoIGV4cGxpY2l0IFBvc3RncmVTUUwgdHlwZSBpbmZvcm1hdGlvbiBmb3IgcGFyYW1ldGVyIGJpbmRpbmcuCiAqCiAqIFVzZSB3aGVuIGF1dG8tZGV0ZWN0aW9uIGlzbid0IHN1ZmZpY2llbnQgb3Igd2hlbiB5b3UgbmVlZCB0byBzcGVjaWZ5CiAqIHRoZSBleGFjdCBQb3N0Z3JlU1FMIHR5cGUgKHNpbmNlIG9uZSBQSFAgdHlwZSBjYW4gbWFwIHRvIG11bHRpcGxlIFBvc3RncmVTUUwgdHlwZXMpOgogKiAtIGludCBjb3VsZCBiZSBJTlQyLCBJTlQ0LCBvciBJTlQ4CiAqIC0gc3RyaW5nIGNvdWxkIGJlIFRFWFQsIFZBUkNIQVIsIG9yIENIQVIKICogLSBhcnJheSBtdXN0IGFsd2F5cyB1c2UgdHlwZWQoKSBzaW5jZSBhdXRvLWRldGVjdGlvbiBjYW5ub3QgZGV0ZXJtaW5lIGVsZW1lbnQgdHlwZQogKiAtIERhdGVUaW1lSW50ZXJmYWNlIGNvdWxkIGJlIFRJTUVTVEFNUCBvciBUSU1FU1RBTVBUWgogKiAtIEpzb24gY291bGQgYmUgSlNPTiBvciBKU09OQgogKgogKiBAcGFyYW0gbWl4ZWQgJHZhbHVlIFRoZSB2YWx1ZSB0byBiaW5kCiAqIEBwYXJhbSBQb3N0Z3JlU3FsVHlwZSAkdGFyZ2V0VHlwZSBUaGUgUG9zdGdyZVNRTCB0eXBlIHRvIGNvbnZlcnQgdGhlIHZhbHVlIHRvCiAqCiAqIEBleGFtcGxlCiAqICRjbGllbnQtPmZldGNoKAogKiAgICAgJ1NFTEVDVCAqIEZST00gdXNlcnMgV0hFUkUgaWQgPSAkMSBBTkQgdGFncyA9ICQyJywKICogICAgIFsKICogICAgICAgICB0eXBlZCgnNTUwZTg0MDAtZTI5Yi00MWQ0LWE3MTYtNDQ2NjU1NDQwMDAwJywgUG9zdGdyZVNxbFR5cGU6OlVVSUQpLAogKiAgICAgICAgIHR5cGVkKFsndGFnMScsICd0YWcyJ10sIFBvc3RncmVTcWxUeXBlOjpURVhUX0FSUkFZKSwKICogICAgIF0KICogKTsKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3161,"slug":"pgsql-type-text","name":"pgsql_type_text","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3167,"slug":"pgsql-type-varchar","name":"pgsql_type_varchar","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3173,"slug":"pgsql-type-char","name":"pgsql_type_char","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3179,"slug":"pgsql-type-bpchar","name":"pgsql_type_bpchar","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3185,"slug":"pgsql-type-int2","name":"pgsql_type_int2","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3191,"slug":"pgsql-type-smallint","name":"pgsql_type_smallint","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3197,"slug":"pgsql-type-int4","name":"pgsql_type_int4","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3203,"slug":"pgsql-type-integer","name":"pgsql_type_integer","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3209,"slug":"pgsql-type-int8","name":"pgsql_type_int8","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3215,"slug":"pgsql-type-bigint","name":"pgsql_type_bigint","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3221,"slug":"pgsql-type-float4","name":"pgsql_type_float4","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3227,"slug":"pgsql-type-real","name":"pgsql_type_real","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3233,"slug":"pgsql-type-float8","name":"pgsql_type_float8","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3239,"slug":"pgsql-type-double","name":"pgsql_type_double","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3245,"slug":"pgsql-type-numeric","name":"pgsql_type_numeric","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3251,"slug":"pgsql-type-money","name":"pgsql_type_money","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3257,"slug":"pgsql-type-bool","name":"pgsql_type_bool","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3263,"slug":"pgsql-type-boolean","name":"pgsql_type_boolean","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3269,"slug":"pgsql-type-bytea","name":"pgsql_type_bytea","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3275,"slug":"pgsql-type-bit","name":"pgsql_type_bit","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3281,"slug":"pgsql-type-varbit","name":"pgsql_type_varbit","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3287,"slug":"pgsql-type-date","name":"pgsql_type_date","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3293,"slug":"pgsql-type-time","name":"pgsql_type_time","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3299,"slug":"pgsql-type-timetz","name":"pgsql_type_timetz","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3305,"slug":"pgsql-type-timestamp","name":"pgsql_type_timestamp","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3311,"slug":"pgsql-type-timestamptz","name":"pgsql_type_timestamptz","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3317,"slug":"pgsql-type-interval","name":"pgsql_type_interval","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3323,"slug":"pgsql-type-json","name":"pgsql_type_json","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3329,"slug":"pgsql-type-jsonb","name":"pgsql_type_jsonb","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3335,"slug":"pgsql-type-uuid","name":"pgsql_type_uuid","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3341,"slug":"pgsql-type-inet","name":"pgsql_type_inet","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3347,"slug":"pgsql-type-cidr","name":"pgsql_type_cidr","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3353,"slug":"pgsql-type-macaddr","name":"pgsql_type_macaddr","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3359,"slug":"pgsql-type-macaddr8","name":"pgsql_type_macaddr8","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3365,"slug":"pgsql-type-xml","name":"pgsql_type_xml","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3371,"slug":"pgsql-type-oid","name":"pgsql_type_oid","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3377,"slug":"pgsql-type-text-array","name":"pgsql_type_text_array","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3383,"slug":"pgsql-type-varchar-array","name":"pgsql_type_varchar_array","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3389,"slug":"pgsql-type-int2-array","name":"pgsql_type_int2_array","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3395,"slug":"pgsql-type-int4-array","name":"pgsql_type_int4_array","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3401,"slug":"pgsql-type-int8-array","name":"pgsql_type_int8_array","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3407,"slug":"pgsql-type-float4-array","name":"pgsql_type_float4_array","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3413,"slug":"pgsql-type-float8-array","name":"pgsql_type_float8_array","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3419,"slug":"pgsql-type-bool-array","name":"pgsql_type_bool_array","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3425,"slug":"pgsql-type-uuid-array","name":"pgsql_type_uuid_array","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3431,"slug":"pgsql-type-json-array","name":"pgsql_type_json_array","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":3437,"slug":"pgsql-type-jsonb-array","name":"pgsql_type_jsonb_array","namespace":"Flow\\PostgreSql\\DSL","parameters":[],"return_type":[{"name":"PostgreSqlType","namespace":"Flow\\PostgreSql\\Client\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":39,"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\\ETL\\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":59,"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\\ETL\\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":74,"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\\ETL\\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":89,"slug":"context","name":"context","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"traceId","type":[{"name":"TraceId","namespace":"Flow\\Telemetry\\Context","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":"Context","namespace":"Flow\\Telemetry\\Context","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENvbnRleHQuCiAqCiAqIElmIG5vIFRyYWNlSWQgaXMgcHJvdmlkZWQsIGdlbmVyYXRlcyBhIG5ldyBvbmUuCiAqIElmIG5vIEJhZ2dhZ2UgaXMgcHJvdmlkZWQsIGNyZWF0ZXMgYW4gZW1wdHkgb25lLgogKgogKiBAcGFyYW0gbnVsbHxUcmFjZUlkICR0cmFjZUlkIE9wdGlvbmFsIFRyYWNlSWQgdG8gdXNlCiAqIEBwYXJhbSBudWxsfEJhZ2dhZ2UgJGJhZ2dhZ2UgT3B0aW9uYWwgQmFnZ2FnZSB0byB1c2UKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":106,"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\\ETL\\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":117,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFJlc291cmNlLgogKgogKiBAcGFyYW0gYXJyYXk8c3RyaW5nLCBhcnJheTxib29sfGZsb2F0fGludHxzdHJpbmc+fGJvb2x8ZmxvYXR8aW50fHN0cmluZz58QXR0cmlidXRlcyAkYXR0cmlidXRlcyBSZXNvdXJjZSBhdHRyaWJ1dGVzCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":130,"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\\ETL\\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":143,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFNwYW5FdmVudCAoR2VuZXJpY0V2ZW50KSB3aXRoIGFuIGV4cGxpY2l0IHRpbWVzdGFtcC4KICoKICogQHBhcmFtIHN0cmluZyAkbmFtZSBFdmVudCBuYW1lCiAqIEBwYXJhbSBcRGF0ZVRpbWVJbW11dGFibGUgJHRpbWVzdGFtcCBFdmVudCB0aW1lc3RhbXAKICogQHBhcmFtIGFycmF5PHN0cmluZywgYXJyYXk8Ym9vbHxmbG9hdHxpbnR8c3RyaW5nPnxib29sfGZsb2F0fGludHxzdHJpbmc+fEF0dHJpYnV0ZXMgJGF0dHJpYnV0ZXMgRXZlbnQgYXR0cmlidXRlcwogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":155,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFNwYW5MaW5rLgogKgogKiBAcGFyYW0gU3BhbkNvbnRleHQgJGNvbnRleHQgVGhlIGxpbmtlZCBzcGFuIGNvbnRleHQKICogQHBhcmFtIGFycmF5PHN0cmluZywgYXJyYXk8Ym9vbHxmbG9hdHxpbnR8c3RyaW5nPnxib29sfGZsb2F0fGludHxzdHJpbmc+fEF0dHJpYnV0ZXMgJGF0dHJpYnV0ZXMgTGluayBhdHRyaWJ1dGVzCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":174,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBTcGFuTGltaXRzIGNvbmZpZ3VyYXRpb24uCiAqCiAqIFNwYW5MaW1pdHMgY29udHJvbHMgdGhlIG1heGltdW0gYW1vdW50IG9mIGRhdGEgYSBzcGFuIGNhbiBjb2xsZWN0LAogKiBwcmV2ZW50aW5nIHVuYm91bmRlZCBtZW1vcnkgZ3Jvd3RoIGFuZCBlbnN1cmluZyByZWFzb25hYmxlIHNwYW4gc2l6ZXMuCiAqCiAqIEBwYXJhbSBpbnQgJGF0dHJpYnV0ZUNvdW50TGltaXQgTWF4aW11bSBudW1iZXIgb2YgYXR0cmlidXRlcyBwZXIgc3BhbgogKiBAcGFyYW0gaW50ICRldmVudENvdW50TGltaXQgTWF4aW11bSBudW1iZXIgb2YgZXZlbnRzIHBlciBzcGFuCiAqIEBwYXJhbSBpbnQgJGxpbmtDb3VudExpbWl0IE1heGltdW0gbnVtYmVyIG9mIGxpbmtzIHBlciBzcGFuCiAqIEBwYXJhbSBpbnQgJGF0dHJpYnV0ZVBlckV2ZW50Q291bnRMaW1pdCBNYXhpbXVtIG51bWJlciBvZiBhdHRyaWJ1dGVzIHBlciBldmVudAogKiBAcGFyYW0gaW50ICRhdHRyaWJ1dGVQZXJMaW5rQ291bnRMaW1pdCBNYXhpbXVtIG51bWJlciBvZiBhdHRyaWJ1dGVzIHBlciBsaW5rCiAqIEBwYXJhbSBudWxsfGludCAkYXR0cmlidXRlVmFsdWVMZW5ndGhMaW1pdCBNYXhpbXVtIGxlbmd0aCBmb3Igc3RyaW5nIGF0dHJpYnV0ZSB2YWx1ZXMgKG51bGwgPSB1bmxpbWl0ZWQpCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":202,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBMb2dSZWNvcmRMaW1pdHMgY29uZmlndXJhdGlvbi4KICoKICogTG9nUmVjb3JkTGltaXRzIGNvbnRyb2xzIHRoZSBtYXhpbXVtIGFtb3VudCBvZiBkYXRhIGEgbG9nIHJlY29yZCBjYW4gY29sbGVjdCwKICogcHJldmVudGluZyB1bmJvdW5kZWQgbWVtb3J5IGdyb3d0aCBhbmQgZW5zdXJpbmcgcmVhc29uYWJsZSBsb2cgcmVjb3JkIHNpemVzLgogKgogKiBAcGFyYW0gaW50ICRhdHRyaWJ1dGVDb3VudExpbWl0IE1heGltdW0gbnVtYmVyIG9mIGF0dHJpYnV0ZXMgcGVyIGxvZyByZWNvcmQKICogQHBhcmFtIG51bGx8aW50ICRhdHRyaWJ1dGVWYWx1ZUxlbmd0aExpbWl0IE1heGltdW0gbGVuZ3RoIGZvciBzdHJpbmcgYXR0cmlidXRlIHZhbHVlcyAobnVsbCA9IHVubGltaXRlZCkKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":227,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBNZXRyaWNMaW1pdHMgY29uZmlndXJhdGlvbi4KICoKICogTWV0cmljTGltaXRzIGNvbnRyb2xzIHRoZSBtYXhpbXVtIGNhcmRpbmFsaXR5ICh1bmlxdWUgYXR0cmlidXRlIGNvbWJpbmF0aW9ucykKICogcGVyIG1ldHJpYyBpbnN0cnVtZW50LCBwcmV2ZW50aW5nIG1lbW9yeSBleGhhdXN0aW9uIGZyb20gaGlnaC1jYXJkaW5hbGl0eSBhdHRyaWJ1dGVzLgogKgogKiBXaGVuIHRoZSBjYXJkaW5hbGl0eSBsaW1pdCBpcyBleGNlZWRlZCwgbmV3IGF0dHJpYnV0ZSBjb21iaW5hdGlvbnMgYXJlIGFnZ3JlZ2F0ZWQKICogaW50byBhbiBvdmVyZmxvdyBkYXRhIHBvaW50IHdpdGggYG90ZWwubWV0cmljLm92ZXJmbG93OiB0cnVlYCBhdHRyaWJ1dGUuCiAqCiAqIE5vdGU6IFVubGlrZSBzcGFucyBhbmQgbG9ncywgbWV0cmljcyBhcmUgRVhFTVBUIGZyb20gYXR0cmlidXRlIGNvdW50IGFuZCB2YWx1ZQogKiBsZW5ndGggbGltaXRzIHBlciB0aGUgT3BlblRlbGVtZXRyeSBzcGVjaWZpY2F0aW9uLiBPbmx5IGNhcmRpbmFsaXR5IGlzIGxpbWl0ZWQuCiAqCiAqIEBwYXJhbSBpbnQgJGNhcmRpbmFsaXR5TGltaXQgTWF4aW11bSBudW1iZXIgb2YgdW5pcXVlIGF0dHJpYnV0ZSBjb21iaW5hdGlvbnMgcGVyIGluc3RydW1lbnQKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":242,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFZvaWRTcGFuUHJvY2Vzc29yLgogKgogKiBOby1vcCBzcGFuIHByb2Nlc3NvciB0aGF0IGRpc2NhcmRzIGFsbCBkYXRhLgogKiBVc2UgdGhpcyB3aGVuIHRyYWNpbmcgaXMgZGlzYWJsZWQgdG8gbWluaW1pemUgb3ZlcmhlYWQuCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":254,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFZvaWRNZXRyaWNQcm9jZXNzb3IuCiAqCiAqIE5vLW9wIG1ldHJpYyBwcm9jZXNzb3IgdGhhdCBkaXNjYXJkcyBhbGwgZGF0YS4KICogVXNlIHRoaXMgd2hlbiBtZXRyaWNzIGNvbGxlY3Rpb24gaXMgZGlzYWJsZWQgdG8gbWluaW1pemUgb3ZlcmhlYWQuCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":266,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFZvaWRMb2dQcm9jZXNzb3IuCiAqCiAqIE5vLW9wIGxvZyBwcm9jZXNzb3IgdGhhdCBkaXNjYXJkcyBhbGwgZGF0YS4KICogVXNlIHRoaXMgd2hlbiBsb2dnaW5nIGlzIGRpc2FibGVkIHRvIG1pbmltaXplIG92ZXJoZWFkLgogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":278,"slug":"void-span-exporter","name":"void_span_exporter","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"VoidSpanExporter","namespace":"Flow\\Telemetry\\Provider\\Void","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFZvaWRTcGFuRXhwb3J0ZXIuCiAqCiAqIE5vLW9wIHNwYW4gZXhwb3J0ZXIgdGhhdCBkaXNjYXJkcyBhbGwgZGF0YS4KICogVXNlIHRoaXMgd2hlbiB0ZWxlbWV0cnkgZXhwb3J0IGlzIGRpc2FibGVkIHRvIG1pbmltaXplIG92ZXJoZWFkLgogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":290,"slug":"void-metric-exporter","name":"void_metric_exporter","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"VoidMetricExporter","namespace":"Flow\\Telemetry\\Provider\\Void","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFZvaWRNZXRyaWNFeHBvcnRlci4KICoKICogTm8tb3AgbWV0cmljIGV4cG9ydGVyIHRoYXQgZGlzY2FyZHMgYWxsIGRhdGEuCiAqIFVzZSB0aGlzIHdoZW4gdGVsZW1ldHJ5IGV4cG9ydCBpcyBkaXNhYmxlZCB0byBtaW5pbWl6ZSBvdmVyaGVhZC4KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":302,"slug":"void-log-exporter","name":"void_log_exporter","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"VoidLogExporter","namespace":"Flow\\Telemetry\\Provider\\Void","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFZvaWRMb2dFeHBvcnRlci4KICoKICogTm8tb3AgbG9nIGV4cG9ydGVyIHRoYXQgZGlzY2FyZHMgYWxsIGRhdGEuCiAqIFVzZSB0aGlzIHdoZW4gdGVsZW1ldHJ5IGV4cG9ydCBpcyBkaXNhYmxlZCB0byBtaW5pbWl6ZSBvdmVyaGVhZC4KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":315,"slug":"memory-span-exporter","name":"memory_span_exporter","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"MemorySpanExporter","namespace":"Flow\\Telemetry\\Provider\\Memory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIE1lbW9yeVNwYW5FeHBvcnRlci4KICoKICogU3BhbiBleHBvcnRlciB0aGF0IHN0b3JlcyBkYXRhIGluIG1lbW9yeS4KICogUHJvdmlkZXMgZGlyZWN0IGdldHRlciBhY2Nlc3MgdG8gZXhwb3J0ZWQgc3BhbnMuCiAqIFVzZWZ1bCBmb3IgdGVzdGluZyBhbmQgaW5zcGVjdGlvbiB3aXRob3V0IHNlcmlhbGl6YXRpb24uCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":328,"slug":"memory-metric-exporter","name":"memory_metric_exporter","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"MemoryMetricExporter","namespace":"Flow\\Telemetry\\Provider\\Memory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIE1lbW9yeU1ldHJpY0V4cG9ydGVyLgogKgogKiBNZXRyaWMgZXhwb3J0ZXIgdGhhdCBzdG9yZXMgZGF0YSBpbiBtZW1vcnkuCiAqIFByb3ZpZGVzIGRpcmVjdCBnZXR0ZXIgYWNjZXNzIHRvIGV4cG9ydGVkIG1ldHJpY3MuCiAqIFVzZWZ1bCBmb3IgdGVzdGluZyBhbmQgaW5zcGVjdGlvbiB3aXRob3V0IHNlcmlhbGl6YXRpb24uCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":341,"slug":"memory-log-exporter","name":"memory_log_exporter","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"MemoryLogExporter","namespace":"Flow\\Telemetry\\Provider\\Memory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIE1lbW9yeUxvZ0V4cG9ydGVyLgogKgogKiBMb2cgZXhwb3J0ZXIgdGhhdCBzdG9yZXMgZGF0YSBpbiBtZW1vcnkuCiAqIFByb3ZpZGVzIGRpcmVjdCBnZXR0ZXIgYWNjZXNzIHRvIGV4cG9ydGVkIGxvZyBlbnRyaWVzLgogKiBVc2VmdWwgZm9yIHRlc3RpbmcgYW5kIGluc3BlY3Rpb24gd2l0aG91dCBzZXJpYWxpemF0aW9uLgogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":355,"slug":"memory-span-processor","name":"memory_span_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"exporter","type":[{"name":"SpanExporter","namespace":"Flow\\Telemetry\\Tracer","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"MemorySpanProcessor","namespace":"Flow\\Telemetry\\Provider\\Memory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIE1lbW9yeVNwYW5Qcm9jZXNzb3IuCiAqCiAqIFNwYW4gcHJvY2Vzc29yIHRoYXQgc3RvcmVzIHNwYW5zIGluIG1lbW9yeSBhbmQgZXhwb3J0cyB2aWEgY29uZmlndXJlZCBleHBvcnRlci4KICogVXNlZnVsIGZvciB0ZXN0aW5nLgogKgogKiBAcGFyYW0gU3BhbkV4cG9ydGVyICRleHBvcnRlciBUaGUgZXhwb3J0ZXIgdG8gc2VuZCBzcGFucyB0bwogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":369,"slug":"memory-metric-processor","name":"memory_metric_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"exporter","type":[{"name":"MetricExporter","namespace":"Flow\\Telemetry\\Meter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"MemoryMetricProcessor","namespace":"Flow\\Telemetry\\Provider\\Memory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIE1lbW9yeU1ldHJpY1Byb2Nlc3Nvci4KICoKICogTWV0cmljIHByb2Nlc3NvciB0aGF0IHN0b3JlcyBtZXRyaWNzIGluIG1lbW9yeSBhbmQgZXhwb3J0cyB2aWEgY29uZmlndXJlZCBleHBvcnRlci4KICogVXNlZnVsIGZvciB0ZXN0aW5nLgogKgogKiBAcGFyYW0gTWV0cmljRXhwb3J0ZXIgJGV4cG9ydGVyIFRoZSBleHBvcnRlciB0byBzZW5kIG1ldHJpY3MgdG8KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":383,"slug":"memory-log-processor","name":"memory_log_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"exporter","type":[{"name":"LogExporter","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":"MemoryLogProcessor","namespace":"Flow\\Telemetry\\Provider\\Memory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIE1lbW9yeUxvZ1Byb2Nlc3Nvci4KICoKICogTG9nIHByb2Nlc3NvciB0aGF0IHN0b3JlcyBsb2cgcmVjb3JkcyBpbiBtZW1vcnkgYW5kIGV4cG9ydHMgdmlhIGNvbmZpZ3VyZWQgZXhwb3J0ZXIuCiAqIFVzZWZ1bCBmb3IgdGVzdGluZy4KICoKICogQHBhcmFtIExvZ0V4cG9ydGVyICRleHBvcnRlciBUaGUgZXhwb3J0ZXIgdG8gc2VuZCBsb2dzIHRvCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":402,"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\\AlwaysOnSampler::..."},{"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::..."}],"return_type":[{"name":"TracerProvider","namespace":"Flow\\Telemetry\\Tracer","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFRyYWNlclByb3ZpZGVyLgogKgogKiBDcmVhdGVzIGEgcHJvdmlkZXIgdGhhdCB1c2VzIGEgU3BhblByb2Nlc3NvciBmb3IgcHJvY2Vzc2luZyBzcGFucy4KICogRm9yIHZvaWQvZGlzYWJsZWQgdHJhY2luZywgcGFzcyB2b2lkX3Byb2Nlc3NvcigpLgogKiBGb3IgbWVtb3J5LWJhc2VkIHRlc3RpbmcsIHBhc3MgbWVtb3J5X3Byb2Nlc3NvcigpIHdpdGggZXhwb3J0ZXJzLgogKgogKiBAcGFyYW0gU3BhblByb2Nlc3NvciAkcHJvY2Vzc29yIFRoZSBwcm9jZXNzb3IgZm9yIHNwYW5zCiAqIEBwYXJhbSBDbG9ja0ludGVyZmFjZSAkY2xvY2sgVGhlIGNsb2NrIGZvciB0aW1lc3RhbXBzCiAqIEBwYXJhbSBDb250ZXh0U3RvcmFnZSAkY29udGV4dFN0b3JhZ2UgU3RvcmFnZSBmb3IgY29udGV4dCBwcm9wYWdhdGlvbgogKiBAcGFyYW0gU2FtcGxlciAkc2FtcGxlciBTYW1wbGluZyBzdHJhdGVneSBmb3Igc3BhbnMKICogQHBhcmFtIFNwYW5MaW1pdHMgJGxpbWl0cyBMaW1pdHMgZm9yIHNwYW4gYXR0cmlidXRlcywgZXZlbnRzLCBhbmQgbGlua3MKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":431,"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::..."}],"return_type":[{"name":"LoggerProvider","namespace":"Flow\\Telemetry\\Logger","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIExvZ2dlclByb3ZpZGVyLgogKgogKiBDcmVhdGVzIGEgcHJvdmlkZXIgdGhhdCB1c2VzIGEgTG9nUHJvY2Vzc29yIGZvciBwcm9jZXNzaW5nIGxvZ3MuCiAqIEZvciB2b2lkL2Rpc2FibGVkIGxvZ2dpbmcsIHBhc3Mgdm9pZF9wcm9jZXNzb3IoKS4KICogRm9yIG1lbW9yeS1iYXNlZCB0ZXN0aW5nLCBwYXNzIG1lbW9yeV9wcm9jZXNzb3IoKSB3aXRoIGV4cG9ydGVycy4KICoKICogQHBhcmFtIExvZ1Byb2Nlc3NvciAkcHJvY2Vzc29yIFRoZSBwcm9jZXNzb3IgZm9yIGxvZ3MKICogQHBhcmFtIENsb2NrSW50ZXJmYWNlICRjbG9jayBUaGUgY2xvY2sgZm9yIHRpbWVzdGFtcHMKICogQHBhcmFtIENvbnRleHRTdG9yYWdlICRjb250ZXh0U3RvcmFnZSBTdG9yYWdlIGZvciBzcGFuIGNvcnJlbGF0aW9uCiAqIEBwYXJhbSBMb2dSZWNvcmRMaW1pdHMgJGxpbWl0cyBMaW1pdHMgZm9yIGxvZyByZWNvcmQgYXR0cmlidXRlcwogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":459,"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::..."}],"return_type":[{"name":"MeterProvider","namespace":"Flow\\Telemetry\\Meter","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIE1ldGVyUHJvdmlkZXIuCiAqCiAqIENyZWF0ZXMgYSBwcm92aWRlciB0aGF0IHVzZXMgYSBNZXRyaWNQcm9jZXNzb3IgZm9yIHByb2Nlc3NpbmcgbWV0cmljcy4KICogRm9yIHZvaWQvZGlzYWJsZWQgbWV0cmljcywgcGFzcyB2b2lkX3Byb2Nlc3NvcigpLgogKiBGb3IgbWVtb3J5LWJhc2VkIHRlc3RpbmcsIHBhc3MgbWVtb3J5X3Byb2Nlc3NvcigpIHdpdGggZXhwb3J0ZXJzLgogKgogKiBAcGFyYW0gTWV0cmljUHJvY2Vzc29yICRwcm9jZXNzb3IgVGhlIHByb2Nlc3NvciBmb3IgbWV0cmljcwogKiBAcGFyYW0gQ2xvY2tJbnRlcmZhY2UgJGNsb2NrIFRoZSBjbG9jayBmb3IgdGltZXN0YW1wcwogKiBAcGFyYW0gQWdncmVnYXRpb25UZW1wb3JhbGl0eSAkdGVtcG9yYWxpdHkgQWdncmVnYXRpb24gdGVtcG9yYWxpdHkgZm9yIG1ldHJpY3MKICogQHBhcmFtIEV4ZW1wbGFyRmlsdGVyICRleGVtcGxhckZpbHRlciBGaWx0ZXIgZm9yIGV4ZW1wbGFyIHNhbXBsaW5nIChkZWZhdWx0OiBUcmFjZUJhc2VkRXhlbXBsYXJGaWx0ZXIpCiAqIEBwYXJhbSBNZXRyaWNMaW1pdHMgJGxpbWl0cyBDYXJkaW5hbGl0eSBsaW1pdHMgZm9yIG1ldHJpYyBpbnN0cnVtZW50cwogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":486,"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"}],"return_type":[{"name":"Telemetry","namespace":"Flow\\Telemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIG5ldyBUZWxlbWV0cnkgaW5zdGFuY2Ugd2l0aCB0aGUgZ2l2ZW4gcHJvdmlkZXJzLgogKgogKiBJZiBwcm92aWRlcnMgYXJlIG5vdCBzcGVjaWZpZWQsIHZvaWQgcHJvdmlkZXJzIChuby1vcCkgYXJlIHVzZWQuCiAqCiAqIEBwYXJhbSByZXNvdXJjZSAkcmVzb3VyY2UgVGhlIHJlc291cmNlIGRlc2NyaWJpbmcgdGhlIGVudGl0eSBwcm9kdWNpbmcgdGVsZW1ldHJ5CiAqIEBwYXJhbSBudWxsfFRyYWNlclByb3ZpZGVyICR0cmFjZXJQcm92aWRlciBUaGUgdHJhY2VyIHByb3ZpZGVyIChudWxsIGZvciB2b2lkL2Rpc2FibGVkKQogKiBAcGFyYW0gbnVsbHxNZXRlclByb3ZpZGVyICRtZXRlclByb3ZpZGVyIFRoZSBtZXRlciBwcm92aWRlciAobnVsbCBmb3Igdm9pZC9kaXNhYmxlZCkKICogQHBhcmFtIG51bGx8TG9nZ2VyUHJvdmlkZXIgJGxvZ2dlclByb3ZpZGVyIFRoZSBsb2dnZXIgcHJvdmlkZXIgKG51bGwgZm9yIHZvaWQvZGlzYWJsZWQpCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":511,"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\\ETL\\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":530,"slug":"batching-span-processor","name":"batching_span_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"exporter","type":[{"name":"SpanExporter","namespace":"Flow\\Telemetry\\Tracer","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"}],"return_type":[{"name":"BatchingSpanProcessor","namespace":"Flow\\Telemetry\\Tracer\\Processor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEJhdGNoaW5nU3BhblByb2Nlc3Nvci4KICoKICogQ29sbGVjdHMgc3BhbnMgaW4gbWVtb3J5IGFuZCBleHBvcnRzIHRoZW0gaW4gYmF0Y2hlcyBmb3IgZWZmaWNpZW5jeS4KICogU3BhbnMgYXJlIGV4cG9ydGVkIHdoZW4gYmF0Y2ggc2l6ZSBpcyByZWFjaGVkLCBmbHVzaCgpIGlzIGNhbGxlZCwgb3Igc2h1dGRvd24oKS4KICoKICogQHBhcmFtIFNwYW5FeHBvcnRlciAkZXhwb3J0ZXIgVGhlIGV4cG9ydGVyIHRvIHNlbmQgc3BhbnMgdG8KICogQHBhcmFtIGludCAkYmF0Y2hTaXplIE51bWJlciBvZiBzcGFucyB0byBjb2xsZWN0IGJlZm9yZSBleHBvcnRpbmcgKGRlZmF1bHQgNTEyKQogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":544,"slug":"pass-through-span-processor","name":"pass_through_span_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"exporter","type":[{"name":"SpanExporter","namespace":"Flow\\Telemetry\\Tracer","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"PassThroughSpanProcessor","namespace":"Flow\\Telemetry\\Tracer\\Processor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBhc3NUaHJvdWdoU3BhblByb2Nlc3Nvci4KICoKICogRXhwb3J0cyBlYWNoIHNwYW4gaW1tZWRpYXRlbHkgd2hlbiBpdCBlbmRzLgogKiBVc2VmdWwgZm9yIGRlYnVnZ2luZyB3aGVyZSBpbW1lZGlhdGUgdmlzaWJpbGl0eSBpcyBtb3JlIGltcG9ydGFudCB0aGFuIHBlcmZvcm1hbmNlLgogKgogKiBAcGFyYW0gU3BhbkV4cG9ydGVyICRleHBvcnRlciBUaGUgZXhwb3J0ZXIgdG8gc2VuZCBzcGFucyB0bwogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":559,"slug":"batching-metric-processor","name":"batching_metric_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"exporter","type":[{"name":"MetricExporter","namespace":"Flow\\Telemetry\\Meter","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"}],"return_type":[{"name":"BatchingMetricProcessor","namespace":"Flow\\Telemetry\\Meter\\Processor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEJhdGNoaW5nTWV0cmljUHJvY2Vzc29yLgogKgogKiBDb2xsZWN0cyBtZXRyaWNzIGluIG1lbW9yeSBhbmQgZXhwb3J0cyB0aGVtIGluIGJhdGNoZXMgZm9yIGVmZmljaWVuY3kuCiAqIE1ldHJpY3MgYXJlIGV4cG9ydGVkIHdoZW4gYmF0Y2ggc2l6ZSBpcyByZWFjaGVkLCBmbHVzaCgpIGlzIGNhbGxlZCwgb3Igc2h1dGRvd24oKS4KICoKICogQHBhcmFtIE1ldHJpY0V4cG9ydGVyICRleHBvcnRlciBUaGUgZXhwb3J0ZXIgdG8gc2VuZCBtZXRyaWNzIHRvCiAqIEBwYXJhbSBpbnQgJGJhdGNoU2l6ZSBOdW1iZXIgb2YgbWV0cmljcyB0byBjb2xsZWN0IGJlZm9yZSBleHBvcnRpbmcgKGRlZmF1bHQgNTEyKQogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":573,"slug":"pass-through-metric-processor","name":"pass_through_metric_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"exporter","type":[{"name":"MetricExporter","namespace":"Flow\\Telemetry\\Meter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"PassThroughMetricProcessor","namespace":"Flow\\Telemetry\\Meter\\Processor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBhc3NUaHJvdWdoTWV0cmljUHJvY2Vzc29yLgogKgogKiBFeHBvcnRzIGVhY2ggbWV0cmljIGltbWVkaWF0ZWx5IHdoZW4gcHJvY2Vzc2VkLgogKiBVc2VmdWwgZm9yIGRlYnVnZ2luZyB3aGVyZSBpbW1lZGlhdGUgdmlzaWJpbGl0eSBpcyBtb3JlIGltcG9ydGFudCB0aGFuIHBlcmZvcm1hbmNlLgogKgogKiBAcGFyYW0gTWV0cmljRXhwb3J0ZXIgJGV4cG9ydGVyIFRoZSBleHBvcnRlciB0byBzZW5kIG1ldHJpY3MgdG8KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":588,"slug":"batching-log-processor","name":"batching_log_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"exporter","type":[{"name":"LogExporter","namespace":"Flow\\Telemetry\\Logger","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"}],"return_type":[{"name":"BatchingLogProcessor","namespace":"Flow\\Telemetry\\Logger\\Processor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEJhdGNoaW5nTG9nUHJvY2Vzc29yLgogKgogKiBDb2xsZWN0cyBsb2cgcmVjb3JkcyBpbiBtZW1vcnkgYW5kIGV4cG9ydHMgdGhlbSBpbiBiYXRjaGVzIGZvciBlZmZpY2llbmN5LgogKiBMb2dzIGFyZSBleHBvcnRlZCB3aGVuIGJhdGNoIHNpemUgaXMgcmVhY2hlZCwgZmx1c2goKSBpcyBjYWxsZWQsIG9yIHNodXRkb3duKCkuCiAqCiAqIEBwYXJhbSBMb2dFeHBvcnRlciAkZXhwb3J0ZXIgVGhlIGV4cG9ydGVyIHRvIHNlbmQgbG9ncyB0bwogKiBAcGFyYW0gaW50ICRiYXRjaFNpemUgTnVtYmVyIG9mIGxvZ3MgdG8gY29sbGVjdCBiZWZvcmUgZXhwb3J0aW5nIChkZWZhdWx0IDUxMikKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":602,"slug":"pass-through-log-processor","name":"pass_through_log_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"exporter","type":[{"name":"LogExporter","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":"PassThroughLogProcessor","namespace":"Flow\\Telemetry\\Logger\\Processor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBhc3NUaHJvdWdoTG9nUHJvY2Vzc29yLgogKgogKiBFeHBvcnRzIGVhY2ggbG9nIHJlY29yZCBpbW1lZGlhdGVseSB3aGVuIHByb2Nlc3NlZC4KICogVXNlZnVsIGZvciBkZWJ1Z2dpbmcgd2hlcmUgaW1tZWRpYXRlIHZpc2liaWxpdHkgaXMgbW9yZSBpbXBvcnRhbnQgdGhhbiBwZXJmb3JtYW5jZS4KICoKICogQHBhcmFtIExvZ0V4cG9ydGVyICRleHBvcnRlciBUaGUgZXhwb3J0ZXIgdG8gc2VuZCBsb2dzIHRvCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":617,"slug":"severity-filtering-log-processor","name":"severity_filtering_log_processor","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":"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":"SeverityFilteringLogProcessor","namespace":"Flow\\Telemetry\\Logger\\Processor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFNldmVyaXR5RmlsdGVyaW5nTG9nUHJvY2Vzc29yLgogKgogKiBGaWx0ZXJzIGxvZyBlbnRyaWVzIGJhc2VkIG9uIG1pbmltdW0gc2V2ZXJpdHkgbGV2ZWwuIE9ubHkgZW50cmllcyBhdCBvciBhYm92ZQogKiB0aGUgY29uZmlndXJlZCB0aHJlc2hvbGQgYXJlIHBhc3NlZCB0byB0aGUgd3JhcHBlZCBwcm9jZXNzb3IuCiAqCiAqIEBwYXJhbSBMb2dQcm9jZXNzb3IgJHByb2Nlc3NvciBUaGUgcHJvY2Vzc29yIHRvIHdyYXAKICogQHBhcmFtIFNldmVyaXR5ICRtaW5pbXVtU2V2ZXJpdHkgTWluaW11bSBzZXZlcml0eSBsZXZlbCAoZGVmYXVsdDogSU5GTykKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":634,"slug":"console-span-exporter","name":"console_span_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":"options","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":"ConsoleSpanExporter","namespace":"Flow\\Telemetry\\Provider\\Console","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENvbnNvbGVTcGFuRXhwb3J0ZXIuCiAqCiAqIE91dHB1dHMgc3BhbnMgdG8gdGhlIGNvbnNvbGUgd2l0aCBBU0NJSSB0YWJsZSBmb3JtYXR0aW5nLgogKiBVc2VmdWwgZm9yIGRlYnVnZ2luZyBhbmQgZGV2ZWxvcG1lbnQuCiAqCiAqIEBwYXJhbSBib29sICRjb2xvcnMgV2hldGhlciB0byB1c2UgQU5TSSBjb2xvcnMgKGRlZmF1bHQ6IHRydWUpCiAqIEBwYXJhbSBDb25zb2xlU3Bhbk9wdGlvbnMgJG9wdGlvbnMgRGlzcGxheSBvcHRpb25zIGZvciB0aGUgZXhwb3J0ZXIKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":649,"slug":"console-metric-exporter","name":"console_metric_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":"options","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::..."}],"return_type":[{"name":"ConsoleMetricExporter","namespace":"Flow\\Telemetry\\Provider\\Console","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENvbnNvbGVNZXRyaWNFeHBvcnRlci4KICoKICogT3V0cHV0cyBtZXRyaWNzIHRvIHRoZSBjb25zb2xlIHdpdGggQVNDSUkgdGFibGUgZm9ybWF0dGluZy4KICogVXNlZnVsIGZvciBkZWJ1Z2dpbmcgYW5kIGRldmVsb3BtZW50LgogKgogKiBAcGFyYW0gYm9vbCAkY29sb3JzIFdoZXRoZXIgdG8gdXNlIEFOU0kgY29sb3JzIChkZWZhdWx0OiB0cnVlKQogKiBAcGFyYW0gQ29uc29sZU1ldHJpY09wdGlvbnMgJG9wdGlvbnMgRGlzcGxheSBvcHRpb25zIGZvciB0aGUgZXhwb3J0ZXIKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":665,"slug":"console-log-exporter","name":"console_log_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":"maxBodyLength","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":"options","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::..."}],"return_type":[{"name":"ConsoleLogExporter","namespace":"Flow\\Telemetry\\Provider\\Console","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENvbnNvbGVMb2dFeHBvcnRlci4KICoKICogT3V0cHV0cyBsb2cgcmVjb3JkcyB0byB0aGUgY29uc29sZSB3aXRoIHNldmVyaXR5LWJhc2VkIGNvbG9yaW5nLgogKiBVc2VmdWwgZm9yIGRlYnVnZ2luZyBhbmQgZGV2ZWxvcG1lbnQuCiAqCiAqIEBwYXJhbSBib29sICRjb2xvcnMgV2hldGhlciB0byB1c2UgQU5TSSBjb2xvcnMgKGRlZmF1bHQ6IHRydWUpCiAqIEBwYXJhbSBudWxsfGludCAkbWF4Qm9keUxlbmd0aCBNYXhpbXVtIGxlbmd0aCBmb3IgYm9keSthdHRyaWJ1dGVzIGNvbHVtbiAobnVsbCA9IG5vIGxpbWl0LCBkZWZhdWx0OiAxMDApCiAqIEBwYXJhbSBDb25zb2xlTG9nT3B0aW9ucyAkb3B0aW9ucyBEaXNwbGF5IG9wdGlvbnMgZm9yIHRoZSBleHBvcnRlcgogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":674,"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\\ETL\\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":683,"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\\ETL\\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":692,"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\\ETL\\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":701,"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\\ETL\\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":710,"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\\ETL\\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":719,"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\\ETL\\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":731,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBBbHdheXNPbkV4ZW1wbGFyRmlsdGVyLgogKgogKiBSZWNvcmRzIGV4ZW1wbGFycyB3aGVuZXZlciBhIHNwYW4gY29udGV4dCBpcyBwcmVzZW50LgogKiBVc2UgdGhpcyBmaWx0ZXIgZm9yIGRlYnVnZ2luZyBvciB3aGVuIGNvbXBsZXRlIHRyYWNlIGNvbnRleHQgaXMgaW1wb3J0YW50LgogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":743,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBBbHdheXNPZmZFeGVtcGxhckZpbHRlci4KICoKICogTmV2ZXIgcmVjb3JkcyBleGVtcGxhcnMuIFVzZSB0aGlzIGZpbHRlciB0byBkaXNhYmxlIGV4ZW1wbGFyIGNvbGxlY3Rpb24KICogZW50aXJlbHkgZm9yIHBlcmZvcm1hbmNlIG9wdGltaXphdGlvbi4KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":755,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFRyYWNlQmFzZWRFeGVtcGxhckZpbHRlci4KICoKICogUmVjb3JkcyBleGVtcGxhcnMgb25seSB3aGVuIHRoZSBzcGFuIGlzIHNhbXBsZWQgKGhhcyBTQU1QTEVEIHRyYWNlIGZsYWcpLgogKiBUaGlzIGlzIHRoZSBkZWZhdWx0IGZpbHRlciwgYmFsYW5jaW5nIGV4ZW1wbGFyIGNvbGxlY3Rpb24gd2l0aCBwZXJmb3JtYW5jZS4KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":770,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFByb3BhZ2F0aW9uQ29udGV4dC4KICoKICogVmFsdWUgb2JqZWN0IGNvbnRhaW5pbmcgYm90aCB0cmFjZSBjb250ZXh0IChTcGFuQ29udGV4dCkgYW5kIGFwcGxpY2F0aW9uCiAqIGRhdGEgKEJhZ2dhZ2UpIHRoYXQgY2FuIGJlIHByb3BhZ2F0ZWQgYWNyb3NzIHByb2Nlc3MgYm91bmRhcmllcy4KICoKICogQHBhcmFtIG51bGx8U3BhbkNvbnRleHQgJHNwYW5Db250ZXh0IE9wdGlvbmFsIHNwYW4gY29udGV4dAogKiBAcGFyYW0gbnVsbHxCYWdnYWdlICRiYWdnYWdlIE9wdGlvbmFsIGJhZ2dhZ2UKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":783,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBBcnJheUNhcnJpZXIuCiAqCiAqIENhcnJpZXIgYmFja2VkIGJ5IGFuIGFzc29jaWF0aXZlIGFycmF5IHdpdGggY2FzZS1pbnNlbnNpdGl2ZSBrZXkgbG9va3VwLgogKgogKiBAcGFyYW0gYXJyYXk8c3RyaW5nLCBzdHJpbmc+ICRkYXRhIEluaXRpYWwgY2FycmllciBkYXRhCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":795,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFN1cGVyZ2xvYmFsQ2Fycmllci4KICoKICogUmVhZC1vbmx5IGNhcnJpZXIgdGhhdCBleHRyYWN0cyBjb250ZXh0IGZyb20gUEhQIHN1cGVyZ2xvYmFscwogKiAoJF9TRVJWRVIsICRfR0VULCAkX1BPU1QsICRfQ09PS0lFKS4KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":807,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFczQ1RyYWNlQ29udGV4dCBwcm9wYWdhdG9yLgogKgogKiBJbXBsZW1lbnRzIFczQyBUcmFjZSBDb250ZXh0IHNwZWNpZmljYXRpb24gZm9yIHByb3BhZ2F0aW5nIHRyYWNlIGNvbnRleHQKICogdXNpbmcgdHJhY2VwYXJlbnQgYW5kIHRyYWNlc3RhdGUgaGVhZGVycy4KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":819,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFczQ0JhZ2dhZ2UgcHJvcGFnYXRvci4KICoKICogSW1wbGVtZW50cyBXM0MgQmFnZ2FnZSBzcGVjaWZpY2F0aW9uIGZvciBwcm9wYWdhdGluZyBhcHBsaWNhdGlvbi1zcGVjaWZpYwogKiBrZXktdmFsdWUgcGFpcnMgdXNpbmcgdGhlIGJhZ2dhZ2UgaGVhZGVyLgogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":833,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENvbXBvc2l0ZVByb3BhZ2F0b3IuCiAqCiAqIENvbWJpbmVzIG11bHRpcGxlIHByb3BhZ2F0b3JzIGludG8gb25lLiBPbiBleHRyYWN0LCBhbGwgcHJvcGFnYXRvcnMgYXJlCiAqIGludm9rZWQgYW5kIHRoZWlyIGNvbnRleHRzIGFyZSBtZXJnZWQuIE9uIGluamVjdCwgYWxsIHByb3BhZ2F0b3JzIGFyZSBpbnZva2VkLgogKgogKiBAcGFyYW0gUHJvcGFnYXRvciAuLi4kcHJvcGFnYXRvcnMgVGhlIHByb3BhZ2F0b3JzIHRvIGNvbWJpbmUKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":848,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENoYWluRGV0ZWN0b3IuCiAqCiAqIENvbWJpbmVzIG11bHRpcGxlIHJlc291cmNlIGRldGVjdG9ycyBpbnRvIGEgY2hhaW4uIERldGVjdG9ycyBhcmUgZXhlY3V0ZWQKICogaW4gb3JkZXIgYW5kIHRoZWlyIHJlc3VsdHMgYXJlIG1lcmdlZC4gTGF0ZXIgZGV0ZWN0b3JzIHRha2UgcHJlY2VkZW5jZQogKiBvdmVyIGVhcmxpZXIgb25lcyB3aGVuIHRoZXJlIGFyZSBjb25mbGljdGluZyBhdHRyaWJ1dGUga2V5cy4KICoKICogQHBhcmFtIFJlc291cmNlRGV0ZWN0b3IgLi4uJGRldGVjdG9ycyBUaGUgZGV0ZWN0b3JzIHRvIGNoYWluCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":860,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBPc0RldGVjdG9yLgogKgogKiBEZXRlY3RzIG9wZXJhdGluZyBzeXN0ZW0gaW5mb3JtYXRpb24gaW5jbHVkaW5nIG9zLnR5cGUsIG9zLm5hbWUsIG9zLnZlcnNpb24sCiAqIGFuZCBvcy5kZXNjcmlwdGlvbiB1c2luZyBQSFAncyBwaHBfdW5hbWUoKSBmdW5jdGlvbi4KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":872,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEhvc3REZXRlY3Rvci4KICoKICogRGV0ZWN0cyBob3N0IGluZm9ybWF0aW9uIGluY2x1ZGluZyBob3N0Lm5hbWUsIGhvc3QuYXJjaCwgYW5kIGhvc3QuaWQKICogKGZyb20gL2V0Yy9tYWNoaW5lLWlkIG9uIExpbnV4IG9yIElPUGxhdGZvcm1VVUlEIG9uIG1hY09TKS4KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":885,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFByb2Nlc3NEZXRlY3Rvci4KICoKICogRGV0ZWN0cyBwcm9jZXNzIGluZm9ybWF0aW9uIGluY2x1ZGluZyBwcm9jZXNzLnBpZCwgcHJvY2Vzcy5leGVjdXRhYmxlLnBhdGgsCiAqIHByb2Nlc3MucnVudGltZS5uYW1lIChQSFApLCBwcm9jZXNzLnJ1bnRpbWUudmVyc2lvbiwgcHJvY2Vzcy5jb21tYW5kLAogKiBhbmQgcHJvY2Vzcy5vd25lciAob24gUE9TSVggc3lzdGVtcykuCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":898,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBFbnZpcm9ubWVudERldGVjdG9yLgogKgogKiBEZXRlY3RzIHJlc291cmNlIGF0dHJpYnV0ZXMgZnJvbSBPcGVuVGVsZW1ldHJ5IHN0YW5kYXJkIGVudmlyb25tZW50IHZhcmlhYmxlczoKICogLSBPVEVMX1NFUlZJQ0VfTkFNRTogU2V0cyBzZXJ2aWNlLm5hbWUgYXR0cmlidXRlCiAqIC0gT1RFTF9SRVNPVVJDRV9BVFRSSUJVVEVTOiBTZXRzIGFkZGl0aW9uYWwgYXR0cmlidXRlcyBpbiBrZXk9dmFsdWUsa2V5Mj12YWx1ZTIgZm9ybWF0CiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":910,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENvbXBvc2VyRGV0ZWN0b3IuCiAqCiAqIERldGVjdHMgc2VydmljZS5uYW1lIGFuZCBzZXJ2aWNlLnZlcnNpb24gZnJvbSBDb21wb3NlcidzIEluc3RhbGxlZFZlcnNpb25zCiAqIHVzaW5nIHRoZSByb290IHBhY2thZ2UgaW5mb3JtYXRpb24uCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":924,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIE1hbnVhbERldGVjdG9yLgogKgogKiBSZXR1cm5zIG1hbnVhbGx5IHNwZWNpZmllZCByZXNvdXJjZSBhdHRyaWJ1dGVzLiBVc2UgdGhpcyB3aGVuIHlvdSBuZWVkCiAqIHRvIHNldCBhdHRyaWJ1dGVzIGV4cGxpY2l0bHkgcmF0aGVyIHRoYW4gZGV0ZWN0aW5nIHRoZW0gYXV0b21hdGljYWxseS4KICoKICogQHBhcmFtIGFycmF5PHN0cmluZywgYXJyYXk8Ym9vbHxmbG9hdHxpbnR8c3RyaW5nPnxib29sfGZsb2F0fGludHxzdHJpbmc+ICRhdHRyaWJ1dGVzIFJlc291cmNlIGF0dHJpYnV0ZXMKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":939,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENhY2hpbmdEZXRlY3Rvci4KICoKICogV3JhcHMgYW5vdGhlciBkZXRlY3RvciBhbmQgY2FjaGVzIGl0cyByZXN1bHRzIHRvIGEgZmlsZS4gT24gc3Vic2VxdWVudAogKiBjYWxscywgcmV0dXJucyB0aGUgY2FjaGVkIHJlc291cmNlIGluc3RlYWQgb2YgcnVubmluZyBkZXRlY3Rpb24gYWdhaW4uCiAqCiAqIEBwYXJhbSBSZXNvdXJjZURldGVjdG9yICRkZXRlY3RvciBUaGUgZGV0ZWN0b3IgdG8gd3JhcAogKiBAcGFyYW0gbnVsbHxzdHJpbmcgJGNhY2hlUGF0aCBDYWNoZSBmaWxlIHBhdGggKGRlZmF1bHQ6IHN5c19nZXRfdGVtcF9kaXIoKS9mbG93X3RlbGVtZXRyeV9yZXNvdXJjZS5jYWNoZSkKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":959,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHJlc291cmNlIGRldGVjdG9yIGNoYWluLgogKgogKiBXaGVuIG5vIGRldGVjdG9ycyBhcmUgcHJvdmlkZWQsIHVzZXMgdGhlIGRlZmF1bHQgZGV0ZWN0b3IgY2hhaW46CiAqIDEuIE9zRGV0ZWN0b3IgLSBPcGVyYXRpbmcgc3lzdGVtIGluZm9ybWF0aW9uCiAqIDIuIEhvc3REZXRlY3RvciAtIEhvc3QgaW5mb3JtYXRpb24KICogMy4gUHJvY2Vzc0RldGVjdG9yIC0gUHJvY2VzcyBpbmZvcm1hdGlvbgogKiA0LiBDb21wb3NlckRldGVjdG9yIC0gU2VydmljZSBpbmZvcm1hdGlvbiBmcm9tIENvbXBvc2VyCiAqIDUuIEVudmlyb25tZW50RGV0ZWN0b3IgLSBFbnZpcm9ubWVudCB2YXJpYWJsZSBvdmVycmlkZXMgKGhpZ2hlc3QgcHJlY2VkZW5jZSkKICoKICogV2hlbiBkZXRlY3RvcnMgYXJlIHByb3ZpZGVkLCB1c2VzIG9ubHkgdGhvc2UgZGV0ZWN0b3JzLgogKgogKiBAcGFyYW0gYXJyYXk8UmVzb3VyY2VEZXRlY3Rvcj4gJGRldGVjdG9ycyBPcHRpb25hbCBjdXN0b20gZGV0ZWN0b3JzIChlbXB0eSA9IHVzZSBkZWZhdWx0cykKICov"},{"repository_path":"src\/lib\/azure-sdk\/src\/Flow\/Azure\/SDK\/DSL\/functions.php","start_line_in_file":18,"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\\ETL\\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":24,"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\\ETL\\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":30,"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\\ETL\\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":36,"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\\ETL\\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":42,"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\\ETL\\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","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\\ETL\\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":12,"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\\ETL\\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":18,"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::..."}],"return_type":[{"name":"AzureBlobFilesystem","namespace":"Flow\\Filesystem\\Bridge\\Azure","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":15,"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\\ETL\\Attribute","arguments":{"module":"S3_FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxzdHJpbmcsIG1peGVkPiAkY29uZmlndXJhdGlvbiAtIGZvciBkZXRhaWxzIHBsZWFzZSBzZWUgaHR0cHM6Ly9hc3luYy1hd3MuY29tL2NsaWVudHMvczMuaHRtbAogKi8="},{"repository_path":"src\/bridge\/filesystem\/async-aws\/src\/Flow\/Filesystem\/Bridge\/AsyncAWS\/DSL\/functions.php","start_line_in_file":22,"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::..."}],"return_type":[{"name":"AsyncAWSS3Filesystem","namespace":"Flow\\Filesystem\\Bridge\\AsyncAWS","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"S3_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":32,"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\\ETL\\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":65,"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\\ETL\\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":99,"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\\ETL\\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":144,"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"}],"return_type":[{"name":"TelemetryHandler","namespace":"Flow\\Bridge\\Monolog\\Telemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":12,"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\\ETL\\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":18,"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\\ETL\\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":12,"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\\ETL\\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":18,"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\\ETL\\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":13,"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\\ETL\\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":36,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEpTT04gc2VyaWFsaXplciBmb3IgT1RMUC4KICoKICogUmV0dXJucyBhIEpzb25TZXJpYWxpemVyIHRoYXQgY29udmVydHMgdGVsZW1ldHJ5IGRhdGEgdG8gT1RMUCBKU09OIHdpcmUgZm9ybWF0LgogKiBVc2UgdGhpcyB3aXRoIEh0dHBUcmFuc3BvcnQgZm9yIEpTT04gb3ZlciBIVFRQLgogKgogKiBFeGFtcGxlIHVzYWdlOgogKiBgYGBwaHAKICogJHNlcmlhbGl6ZXIgPSBvdGxwX2pzb25fc2VyaWFsaXplcigpOwogKiAkdHJhbnNwb3J0ID0gb3RscF9odHRwX3RyYW5zcG9ydCgkY2xpZW50LCAkcmVxRmFjdG9yeSwgJHN0cmVhbUZhY3RvcnksICRlbmRwb2ludCwgJHNlcmlhbGl6ZXIpOwogKiBgYGAKICov"},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":58,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFByb3RvYnVmIHNlcmlhbGl6ZXIgZm9yIE9UTFAuCiAqCiAqIFJldHVybnMgYSBQcm90b2J1ZlNlcmlhbGl6ZXIgdGhhdCBjb252ZXJ0cyB0ZWxlbWV0cnkgZGF0YSB0byBPVExQIFByb3RvYnVmIGJpbmFyeSBmb3JtYXQuCiAqIFVzZSB0aGlzIHdpdGggSHR0cFRyYW5zcG9ydCBmb3IgUHJvdG9idWYgb3ZlciBIVFRQLCBvciB3aXRoIEdycGNUcmFuc3BvcnQuCiAqCiAqIFJlcXVpcmVzOgogKiAtIGdvb2dsZS9wcm90b2J1ZiBwYWNrYWdlCiAqIC0gb3Blbi10ZWxlbWV0cnkvZ2VuLW90bHAtcHJvdG9idWYgcGFja2FnZQogKgogKiBFeGFtcGxlIHVzYWdlOgogKiBgYGBwaHAKICogJHNlcmlhbGl6ZXIgPSBvdGxwX3Byb3RvYnVmX3NlcmlhbGl6ZXIoKTsKICogJHRyYW5zcG9ydCA9IG90bHBfaHR0cF90cmFuc3BvcnQoJGNsaWVudCwgJHJlcUZhY3RvcnksICRzdHJlYW1GYWN0b3J5LCAkZW5kcG9pbnQsICRzZXJpYWxpemVyKTsKICogYGBgCiAqLw=="},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":98,"slug":"otlp-http-transport","name":"otlp_http_transport","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\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":"requestFactory","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":"streamFactory","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},{"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":"Serializer","namespace":"Flow\\Telemetry\\Serializer","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":"[]"}],"return_type":[{"name":"HttpTransport","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Transport","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBIVFRQIHRyYW5zcG9ydCBmb3IgT1RMUCBlbmRwb2ludHMuCiAqCiAqIENyZWF0ZXMgYW4gSHR0cFRyYW5zcG9ydCBjb25maWd1cmVkIHRvIHNlbmQgdGVsZW1ldHJ5IGRhdGEgdG8gYW4gT1RMUC1jb21wYXRpYmxlCiAqIGVuZHBvaW50IHVzaW5nIFBTUi0xOCBIVFRQIGNsaWVudC4gU3VwcG9ydHMgYm90aCBKU09OIGFuZCBQcm90b2J1ZiBmb3JtYXRzLgogKgogKiBFeGFtcGxlIHVzYWdlOgogKiBgYGBwaHAKICogLy8gSlNPTiBvdmVyIEhUVFAKICogJHRyYW5zcG9ydCA9IG90bHBfaHR0cF90cmFuc3BvcnQoCiAqICAgICBjbGllbnQ6ICRjbGllbnQsCiAqICAgICByZXF1ZXN0RmFjdG9yeTogJHBzcjE3RmFjdG9yeSwKICogICAgIHN0cmVhbUZhY3Rvcnk6ICRwc3IxN0ZhY3RvcnksCiAqICAgICBlbmRwb2ludDogJ2h0dHA6Ly9sb2NhbGhvc3Q6NDMxOCcsCiAqICAgICBzZXJpYWxpemVyOiBvdGxwX2pzb25fc2VyaWFsaXplcigpLAogKiApOwogKgogKiAvLyBQcm90b2J1ZiBvdmVyIEhUVFAKICogJHRyYW5zcG9ydCA9IG90bHBfaHR0cF90cmFuc3BvcnQoCiAqICAgICBjbGllbnQ6ICRjbGllbnQsCiAqICAgICByZXF1ZXN0RmFjdG9yeTogJHBzcjE3RmFjdG9yeSwKICogICAgIHN0cmVhbUZhY3Rvcnk6ICRwc3IxN0ZhY3RvcnksCiAqICAgICBlbmRwb2ludDogJ2h0dHA6Ly9sb2NhbGhvc3Q6NDMxOCcsCiAqICAgICBzZXJpYWxpemVyOiBvdGxwX3Byb3RvYnVmX3NlcmlhbGl6ZXIoKSwKICogKTsKICogYGBgCiAqCiAqIEBwYXJhbSBDbGllbnRJbnRlcmZhY2UgJGNsaWVudCBQU1ItMTggSFRUUCBjbGllbnQKICogQHBhcmFtIFJlcXVlc3RGYWN0b3J5SW50ZXJmYWNlICRyZXF1ZXN0RmFjdG9yeSBQU1ItMTcgcmVxdWVzdCBmYWN0b3J5CiAqIEBwYXJhbSBTdHJlYW1GYWN0b3J5SW50ZXJmYWNlICRzdHJlYW1GYWN0b3J5IFBTUi0xNyBzdHJlYW0gZmFjdG9yeQogKiBAcGFyYW0gc3RyaW5nICRlbmRwb2ludCBPVExQIGVuZHBvaW50IFVSTCAoZS5nLiwgJ2h0dHA6Ly9sb2NhbGhvc3Q6NDMxOCcpCiAqIEBwYXJhbSBTZXJpYWxpemVyICRzZXJpYWxpemVyIFNlcmlhbGl6ZXIgZm9yIGVuY29kaW5nIHRlbGVtZXRyeSBkYXRhIChKU09OIG9yIFByb3RvYnVmKQogKiBAcGFyYW0gYXJyYXk8c3RyaW5nLCBzdHJpbmc+ICRoZWFkZXJzIEFkZGl0aW9uYWwgaGVhZGVycyB0byBpbmNsdWRlIGluIHJlcXVlc3RzCiAqLw=="},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":134,"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":"serializer","type":[{"name":"ProtobufSerializer","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Serializer","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"}],"return_type":[{"name":"GrpcTransport","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Transport","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGdSUEMgdHJhbnNwb3J0IGZvciBPVExQIGVuZHBvaW50cy4KICoKICogQ3JlYXRlcyBhIEdycGNUcmFuc3BvcnQgY29uZmlndXJlZCB0byBzZW5kIHRlbGVtZXRyeSBkYXRhIHRvIGFuIE9UTFAtY29tcGF0aWJsZQogKiBlbmRwb2ludCB1c2luZyBnUlBDIHByb3RvY29sIHdpdGggUHJvdG9idWYgc2VyaWFsaXphdGlvbi4KICoKICogUmVxdWlyZXM6CiAqIC0gZXh0LWdycGMgUEhQIGV4dGVuc2lvbgogKiAtIGdvb2dsZS9wcm90b2J1ZiBwYWNrYWdlCiAqIC0gb3Blbi10ZWxlbWV0cnkvZ2VuLW90bHAtcHJvdG9idWYgcGFja2FnZQogKgogKiBFeGFtcGxlIHVzYWdlOgogKiBgYGBwaHAKICogJHRyYW5zcG9ydCA9IG90bHBfZ3JwY190cmFuc3BvcnQoCiAqICAgICBlbmRwb2ludDogJ2xvY2FsaG9zdDo0MzE3JywKICogICAgIHNlcmlhbGl6ZXI6IG90bHBfcHJvdG9idWZfc2VyaWFsaXplcigpLAogKiApOwogKiBgYGAKICoKICogQHBhcmFtIHN0cmluZyAkZW5kcG9pbnQgZ1JQQyBlbmRwb2ludCAoZS5nLiwgJ2xvY2FsaG9zdDo0MzE3JykKICogQHBhcmFtIFByb3RvYnVmU2VyaWFsaXplciAkc2VyaWFsaXplciBQcm90b2J1ZiBzZXJpYWxpemVyIGZvciBlbmNvZGluZyB0ZWxlbWV0cnkgZGF0YQogKiBAcGFyYW0gYXJyYXk8c3RyaW5nLCBzdHJpbmc+ICRoZWFkZXJzIEFkZGl0aW9uYWwgaGVhZGVycyAobWV0YWRhdGEpIHRvIGluY2x1ZGUgaW4gcmVxdWVzdHMKICogQHBhcmFtIGJvb2wgJGluc2VjdXJlIFdoZXRoZXIgdG8gdXNlIGluc2VjdXJlIGNoYW5uZWwgY3JlZGVudGlhbHMgKGRlZmF1bHQgdHJ1ZSBmb3IgbG9jYWwgZGV2KQogKi8="},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":162,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBjdXJsIHRyYW5zcG9ydCBvcHRpb25zIGZvciBPVExQLgogKgogKiBSZXR1cm5zIGEgQ3VybFRyYW5zcG9ydE9wdGlvbnMgYnVpbGRlciBmb3IgY29uZmlndXJpbmcgY3VybCB0cmFuc3BvcnQgc2V0dGluZ3MKICogdXNpbmcgYSBmbHVlbnQgaW50ZXJmYWNlLgogKgogKiBFeGFtcGxlIHVzYWdlOgogKiBgYGBwaHAKICogJG9wdGlvbnMgPSBvdGxwX2N1cmxfb3B0aW9ucygpCiAqICAgICAtPndpdGhUaW1lb3V0KDYwKQogKiAgICAgLT53aXRoQ29ubmVjdFRpbWVvdXQoMTUpCiAqICAgICAtPndpdGhIZWFkZXIoJ0F1dGhvcml6YXRpb24nLCAnQmVhcmVyIHRva2VuJykKICogICAgIC0+d2l0aENvbXByZXNzaW9uKCkKICogICAgIC0+d2l0aFNzbFZlcmlmaWNhdGlvbih2ZXJpZnlQZWVyOiB0cnVlKTsKICoKICogJHRyYW5zcG9ydCA9IG90bHBfY3VybF90cmFuc3BvcnQoJGVuZHBvaW50LCAkc2VyaWFsaXplciwgJG9wdGlvbnMpOwogKiBgYGAKICov"},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":201,"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":"Serializer","namespace":"Flow\\Telemetry\\Serializer","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"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::..."}],"return_type":[{"name":"CurlTransport","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Transport","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBhc3luYyBjdXJsIHRyYW5zcG9ydCBmb3IgT1RMUCBlbmRwb2ludHMuCiAqCiAqIENyZWF0ZXMgYSBDdXJsVHJhbnNwb3J0IHRoYXQgdXNlcyBjdXJsX211bHRpIGZvciBub24tYmxvY2tpbmcgSS9PLgogKiBVbmxpa2UgSHR0cFRyYW5zcG9ydCAoUFNSLTE4KSwgdGhpcyB0cmFuc3BvcnQgcXVldWVzIHJlcXVlc3RzIGFuZCBleGVjdXRlcwogKiB0aGVtIGFzeW5jaHJvbm91c2x5LiBDb21wbGV0ZWQgcmVxdWVzdHMgYXJlIHByb2Nlc3NlZCBvbiBzdWJzZXF1ZW50IHNlbmQoKQogKiBjYWxscyBvciBvbiBzaHV0ZG93bigpLgogKgogKiBSZXF1aXJlczogZXh0LWN1cmwgUEhQIGV4dGVuc2lvbgogKgogKiBFeGFtcGxlIHVzYWdlOgogKiBgYGBwaHAKICogLy8gSlNPTiBvdmVyIEhUVFAgKGFzeW5jKSB3aXRoIGRlZmF1bHQgb3B0aW9ucwogKiAkdHJhbnNwb3J0ID0gb3RscF9jdXJsX3RyYW5zcG9ydCgKICogICAgIGVuZHBvaW50OiAnaHR0cDovL2xvY2FsaG9zdDo0MzE4JywKICogICAgIHNlcmlhbGl6ZXI6IG90bHBfanNvbl9zZXJpYWxpemVyKCksCiAqICk7CiAqCiAqIC8vIFByb3RvYnVmIG92ZXIgSFRUUCAoYXN5bmMpIHdpdGggY3VzdG9tIG9wdGlvbnMKICogJHRyYW5zcG9ydCA9IG90bHBfY3VybF90cmFuc3BvcnQoCiAqICAgICBlbmRwb2ludDogJ2h0dHA6Ly9sb2NhbGhvc3Q6NDMxOCcsCiAqICAgICBzZXJpYWxpemVyOiBvdGxwX3Byb3RvYnVmX3NlcmlhbGl6ZXIoKSwKICogICAgIG9wdGlvbnM6IG90bHBfY3VybF9vcHRpb25zKCkKICogICAgICAgICAtPndpdGhUaW1lb3V0KDYwKQogKiAgICAgICAgIC0+d2l0aEhlYWRlcignQXV0aG9yaXphdGlvbicsICdCZWFyZXIgdG9rZW4nKQogKiAgICAgICAgIC0+d2l0aENvbXByZXNzaW9uKCksCiAqICk7CiAqIGBgYAogKgogKiBAcGFyYW0gc3RyaW5nICRlbmRwb2ludCBPVExQIGVuZHBvaW50IFVSTCAoZS5nLiwgJ2h0dHA6Ly9sb2NhbGhvc3Q6NDMxOCcpCiAqIEBwYXJhbSBTZXJpYWxpemVyICRzZXJpYWxpemVyIFNlcmlhbGl6ZXIgZm9yIGVuY29kaW5nIHRlbGVtZXRyeSBkYXRhIChKU09OIG9yIFByb3RvYnVmKQogKiBAcGFyYW0gQ3VybFRyYW5zcG9ydE9wdGlvbnMgJG9wdGlvbnMgVHJhbnNwb3J0IGNvbmZpZ3VyYXRpb24gb3B0aW9ucwogKi8="},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":221,"slug":"otlp-span-exporter","name":"otlp_span_exporter","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\DSL","parameters":[{"name":"transport","type":[{"name":"Transport","namespace":"Flow\\Telemetry\\Transport","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"OTLPSpanExporter","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Exporter","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBPVExQIHNwYW4gZXhwb3J0ZXIuCiAqCiAqIEV4YW1wbGUgdXNhZ2U6CiAqIGBgYHBocAogKiAkZXhwb3J0ZXIgPSBvdGxwX3NwYW5fZXhwb3J0ZXIoJHRyYW5zcG9ydCk7CiAqICRwcm9jZXNzb3IgPSBiYXRjaGluZ19zcGFuX3Byb2Nlc3NvcigkZXhwb3J0ZXIpOwogKiBgYGAKICoKICogQHBhcmFtIFRyYW5zcG9ydCAkdHJhbnNwb3J0IFRoZSB0cmFuc3BvcnQgZm9yIHNlbmRpbmcgc3BhbiBkYXRhCiAqLw=="},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":238,"slug":"otlp-metric-exporter","name":"otlp_metric_exporter","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\DSL","parameters":[{"name":"transport","type":[{"name":"Transport","namespace":"Flow\\Telemetry\\Transport","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"OTLPMetricExporter","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Exporter","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBPVExQIG1ldHJpYyBleHBvcnRlci4KICoKICogRXhhbXBsZSB1c2FnZToKICogYGBgcGhwCiAqICRleHBvcnRlciA9IG90bHBfbWV0cmljX2V4cG9ydGVyKCR0cmFuc3BvcnQpOwogKiAkcHJvY2Vzc29yID0gYmF0Y2hpbmdfbWV0cmljX3Byb2Nlc3NvcigkZXhwb3J0ZXIpOwogKiBgYGAKICoKICogQHBhcmFtIFRyYW5zcG9ydCAkdHJhbnNwb3J0IFRoZSB0cmFuc3BvcnQgZm9yIHNlbmRpbmcgbWV0cmljIGRhdGEKICov"},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":255,"slug":"otlp-log-exporter","name":"otlp_log_exporter","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\DSL","parameters":[{"name":"transport","type":[{"name":"Transport","namespace":"Flow\\Telemetry\\Transport","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"OTLPLogExporter","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Exporter","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBPVExQIGxvZyBleHBvcnRlci4KICoKICogRXhhbXBsZSB1c2FnZToKICogYGBgcGhwCiAqICRleHBvcnRlciA9IG90bHBfbG9nX2V4cG9ydGVyKCR0cmFuc3BvcnQpOwogKiAkcHJvY2Vzc29yID0gYmF0Y2hpbmdfbG9nX3Byb2Nlc3NvcigkZXhwb3J0ZXIpOwogKiBgYGAKICoKICogQHBhcmFtIFRyYW5zcG9ydCAkdHJhbnNwb3J0IFRoZSB0cmFuc3BvcnQgZm9yIHNlbmRpbmcgbG9nIGRhdGEKICov"},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":276,"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\\AlwaysOnSampler::..."},{"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHRyYWNlciBwcm92aWRlciBjb25maWd1cmVkIGZvciBPVExQIGV4cG9ydC4KICoKICogRXhhbXBsZSB1c2FnZToKICogYGBgcGhwCiAqICRwcm9jZXNzb3IgPSBiYXRjaGluZ19zcGFuX3Byb2Nlc3NvcihvdGxwX3NwYW5fZXhwb3J0ZXIoJHRyYW5zcG9ydCkpOwogKiAkcHJvdmlkZXIgPSBvdGxwX3RyYWNlcl9wcm92aWRlcigkcHJvY2Vzc29yLCAkY2xvY2spOwogKiAkdHJhY2VyID0gJHByb3ZpZGVyLT50cmFjZXIoJHJlc291cmNlLCAnbXktc2VydmljZScsICcxLjAuMCcpOwogKiBgYGAKICoKICogQHBhcmFtIFNwYW5Qcm9jZXNzb3IgJHByb2Nlc3NvciBUaGUgcHJvY2Vzc29yIGZvciBoYW5kbGluZyBzcGFucwogKiBAcGFyYW0gQ2xvY2tJbnRlcmZhY2UgJGNsb2NrIFRoZSBjbG9jayBmb3IgdGltZXN0YW1wcwogKiBAcGFyYW0gU2FtcGxlciAkc2FtcGxlciBUaGUgc2FtcGxlciBmb3IgZGVjaWRpbmcgd2hldGhlciB0byByZWNvcmQgc3BhbnMKICogQHBhcmFtIENvbnRleHRTdG9yYWdlICRjb250ZXh0U3RvcmFnZSBUaGUgY29udGV4dCBzdG9yYWdlIGZvciBwcm9wYWdhdGluZyB0cmFjZSBjb250ZXh0CiAqLw=="},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":300,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIG1ldGVyIHByb3ZpZGVyIGNvbmZpZ3VyZWQgZm9yIE9UTFAgZXhwb3J0LgogKgogKiBFeGFtcGxlIHVzYWdlOgogKiBgYGBwaHAKICogJHByb2Nlc3NvciA9IGJhdGNoaW5nX21ldHJpY19wcm9jZXNzb3Iob3RscF9tZXRyaWNfZXhwb3J0ZXIoJHRyYW5zcG9ydCkpOwogKiAkcHJvdmlkZXIgPSBvdGxwX21ldGVyX3Byb3ZpZGVyKCRwcm9jZXNzb3IsICRjbG9jayk7CiAqICRtZXRlciA9ICRwcm92aWRlci0+bWV0ZXIoJHJlc291cmNlLCAnbXktc2VydmljZScsICcxLjAuMCcpOwogKiBgYGAKICoKICogQHBhcmFtIE1ldHJpY1Byb2Nlc3NvciAkcHJvY2Vzc29yIFRoZSBwcm9jZXNzb3IgZm9yIGhhbmRsaW5nIG1ldHJpY3MKICogQHBhcmFtIENsb2NrSW50ZXJmYWNlICRjbG9jayBUaGUgY2xvY2sgZm9yIHRpbWVzdGFtcHMKICogQHBhcmFtIEFnZ3JlZ2F0aW9uVGVtcG9yYWxpdHkgJHRlbXBvcmFsaXR5IFRoZSBhZ2dyZWdhdGlvbiB0ZW1wb3JhbGl0eSBmb3IgbWV0cmljcwogKi8="},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":323,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGxvZ2dlciBwcm92aWRlciBjb25maWd1cmVkIGZvciBPVExQIGV4cG9ydC4KICoKICogRXhhbXBsZSB1c2FnZToKICogYGBgcGhwCiAqICRwcm9jZXNzb3IgPSBiYXRjaGluZ19sb2dfcHJvY2Vzc29yKG90bHBfbG9nX2V4cG9ydGVyKCR0cmFuc3BvcnQpKTsKICogJHByb3ZpZGVyID0gb3RscF9sb2dnZXJfcHJvdmlkZXIoJHByb2Nlc3NvciwgJGNsb2NrKTsKICogJGxvZ2dlciA9ICRwcm92aWRlci0+bG9nZ2VyKCRyZXNvdXJjZSwgJ215LXNlcnZpY2UnLCAnMS4wLjAnKTsKICogYGBgCiAqCiAqIEBwYXJhbSBMb2dQcm9jZXNzb3IgJHByb2Nlc3NvciBUaGUgcHJvY2Vzc29yIGZvciBoYW5kbGluZyBsb2cgcmVjb3JkcwogKiBAcGFyYW0gQ2xvY2tJbnRlcmZhY2UgJGNsb2NrIFRoZSBjbG9jayBmb3IgdGltZXN0YW1wcwogKiBAcGFyYW0gQ29udGV4dFN0b3JhZ2UgJGNvbnRleHRTdG9yYWdlIFRoZSBjb250ZXh0IHN0b3JhZ2UgZm9yIHByb3BhZ2F0aW5nIGNvbnRleHQKICov"}] \ No newline at end of file +[{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":218,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_reading","option":"data_frame"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_writing","option":"overwrite"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEFsaWFzIGZvciBkYXRhX2ZyYW1lKCkgOiBGbG93LgogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":226,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_reading","option":"data_frame"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_writing","option":"overwrite"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":232,"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"},{"name":"filesystem","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":"TelemetryOptions","namespace":"Flow\\ETL\\Config\\Telemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":251,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"EXTRACTOR"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_reading","option":"data_frame"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_writing","option":"overwrite"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":258,"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}],"return_type":[{"name":"PathPartitionsExtractor","namespace":"Flow\\ETL\\Extractor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"EXTRACTOR"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\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":270,"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"}],"return_type":[{"name":"ArrayExtractor","namespace":"Flow\\ETL\\Extractor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"EXTRACTOR"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_reading","option":"array"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_reading","option":"data_frame"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBpdGVyYWJsZTxhcnJheTxtaXhlZD4+ICRhcnJheQogKiBAcGFyYW0gbnVsbHxTY2hlbWEgJHNjaGVtYSAtIEBkZXByZWNhdGVkIHVzZSB3aXRoU2NoZW1hKCkgbWV0aG9kIGluc3RlYWQKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":287,"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"}],"return_type":[{"name":"CacheExtractor","namespace":"Flow\\ETL\\Extractor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":303,"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\\ETL\\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":309,"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\\ETL\\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":315,"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}],"return_type":[{"name":"FilesExtractor","namespace":"Flow\\ETL\\Extractor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":321,"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\\Serializer\\NativePHPSerializer::..."}],"return_type":[{"name":"FilesystemCache","namespace":"Flow\\ETL\\Cache\\Implementation","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":330,"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\\ETL\\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":343,"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\\ETL\\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":349,"slug":"from-pipeline","name":"from_pipeline","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"pipeline","type":[{"name":"Pipeline","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":"PipelineExtractor","namespace":"Flow\\ETL\\Extractor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":355,"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\\ETL\\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":361,"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\\ETL\\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":370,"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\\ETL\\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-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\\ETL\\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":"to-callable","name":"to_callable","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"callable","type":[{"name":"callable","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"CallbackLoader","namespace":"Flow\\ETL\\Loader","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":394,"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\\ETL\\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":408,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"LOADER"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_writing","option":"array"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENvbnZlcnQgcm93cyB0byBhbiBhcnJheSBhbmQgc3RvcmUgdGhlbSBpbiBwYXNzZWQgYXJyYXkgdmFyaWFibGUuCiAqCiAqIEBwYXJhbSBhcnJheTxhcnJheS1rZXksIG1peGVkPiAkYXJyYXkKICoKICogQHBhcmFtLW91dCBhcnJheTxhcnJheTxtaXhlZD4+ICRhcnJheQogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":415,"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\\ETL\\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":421,"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\\ETL\\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":427,"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\\ETL\\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":433,"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\\ETL\\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":439,"slug":"to-transformation","name":"to_transformation","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"transformer","type":[{"name":"Transformer","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false},{"name":"Transformation","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"loader","type":[{"name":"Loader","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"TransformerLoader","namespace":"Flow\\ETL\\Loader","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":445,"slug":"to-branch","name":"to_branch","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"condition","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"loader","type":[{"name":"Loader","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"BranchingLoader","namespace":"Flow\\ETL\\Loader","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":451,"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\\ETL\\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":461,"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\\ETL\\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":470,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"TRANSFORMER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxzdHJpbmcsIHN0cmluZz4gJHJlbmFtZXMgTWFwIG9mIG9sZF9uYW1lID0+IG5ld19uYW1lCiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":479,"slug":"bool-entry","name":"bool_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":"value","type":[{"name":"bool","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gRW50cnk8P2Jvb2w+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":488,"slug":"boolean-entry","name":"boolean_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":"value","type":[{"name":"bool","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gRW50cnk8P2Jvb2w+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":497,"slug":"datetime-entry","name":"datetime_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":"value","type":[{"name":"DateTimeInterface","namespace":"","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":false,"is_nullable":true,"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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gRW50cnk8P1xEYXRlVGltZUludGVyZmFjZT4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":506,"slug":"time-entry","name":"time_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":"value","type":[{"name":"DateInterval","namespace":"","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":false,"is_nullable":true,"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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gRW50cnk8P1xEYXRlSW50ZXJ2YWw+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":515,"slug":"date-entry","name":"date_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":"value","type":[{"name":"DateTimeInterface","namespace":"","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":false,"is_nullable":true,"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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gRW50cnk8P1xEYXRlVGltZUludGVyZmFjZT4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":524,"slug":"int-entry","name":"int_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":"value","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gRW50cnk8P2ludD4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":533,"slug":"integer-entry","name":"integer_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":"value","type":[{"name":"int","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gRW50cnk8P2ludD4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":542,"slug":"enum-entry","name":"enum_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":"enum","type":[{"name":"UnitEnum","namespace":"","is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gRW50cnk8P1xVbml0RW51bT4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":551,"slug":"float-entry","name":"float_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":"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":"null","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gRW50cnk8P2Zsb2F0PgogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":562,"slug":"json-entry","name":"json_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":"data","type":[{"name":"Json","namespace":"Flow\\Types\\Value","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},{"name":"null","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBudWxsfGFycmF5PGFycmF5LWtleSwgbWl4ZWQ+fEpzb258c3RyaW5nICRkYXRhCiAqCiAqIEByZXR1cm4gRW50cnk8P0pzb24+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":575,"slug":"json-object-entry","name":"json_object_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":"data","type":[{"name":"Json","namespace":"Flow\\Types\\Value","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},{"name":"null","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBudWxsfGFycmF5PGFycmF5LWtleSwgbWl4ZWQ+fEpzb258c3RyaW5nICRkYXRhCiAqCiAqIEB0aHJvd3MgSW52YWxpZEFyZ3VtZW50RXhjZXB0aW9uCiAqCiAqIEByZXR1cm4gRW50cnk8P0pzb24+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":592,"slug":"str-entry","name":"str_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":"value","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gRW50cnk8P3N0cmluZz4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":610,"slug":"null-entry","name":"null_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":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFRoaXMgZnVuY3Rpb25zIGlzIGFuIGFsaWFzIGZvciBjcmVhdGluZyBzdHJpbmcgZW50cnkgZnJvbSBudWxsLgogKiBUaGUgbWFpbiBkaWZmZXJlbmNlIGJldHdlZW4gdXNpbmcgdGhpcyBmdW5jdGlvbiBhbiBzaW1wbHkgc3RyX2VudHJ5IHdpdGggc2Vjb25kIGFyZ3VtZW50IG51bGwKICogaXMgdGhhdCB0aGlzIGZ1bmN0aW9uIHdpbGwgYWxzbyBrZWVwIGEgbm90ZSBpbiB0aGUgbWV0YWRhdGEgdGhhdCB0eXBlIG1pZ2h0IG5vdCBiZSBmaW5hbC4KICogRm9yIGV4YW1wbGUgd2hlbiB3ZSBuZWVkIHRvIGd1ZXNzIGNvbHVtbiB0eXBlIGZyb20gcm93cyBiZWNhdXNlIHNjaGVtYSB3YXMgbm90IHByb3ZpZGVkLAogKiBhbmQgZ2l2ZW4gY29sdW1uIGluIHRoZSBmaXJzdCByb3cgaXMgbnVsbCwgaXQgbWlnaHQgc3RpbGwgY2hhbmdlIG9uY2Ugd2UgZ2V0IHRvIHRoZSBzZWNvbmQgcm93LgogKiBUaGF0IG1ldGFkYXRhIGlzIHVzZWQgdG8gZGV0ZXJtaW5lIGlmIHN0cmluZ19lbnRyeSB3YXMgY3JlYXRlZCBmcm9tIG51bGwgb3Igbm90LgogKgogKiBCeSBkZXNpZ24gZmxvdyBhc3N1bWVzIHdoZW4gZ3Vlc3NpbmcgY29sdW1uIHR5cGUgdGhhdCBudWxsIHdvdWxkIGJlIGEgc3RyaW5nICh0aGUgbW9zdCBmbGV4aWJsZSB0eXBlKS4KICoKICogQHJldHVybiBFbnRyeTw\/c3RyaW5nPgogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":619,"slug":"string-entry","name":"string_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":"value","type":[{"name":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gRW50cnk8P3N0cmluZz4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":628,"slug":"uuid-entry","name":"uuid_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":"value","type":[{"name":"Uuid","namespace":"Flow\\Types\\Value","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":false,"is_nullable":true,"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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gRW50cnk8P1xGbG93XFR5cGVzXFZhbHVlXFV1aWQ+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":637,"slug":"xml-entry","name":"xml_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":"value","type":[{"name":"DOMDocument","namespace":"","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":false,"is_nullable":true,"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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gRW50cnk8P1xET01Eb2N1bWVudD4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":646,"slug":"xml-element-entry","name":"xml_element_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":"value","type":[{"name":"DOMElement","namespace":"","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":false,"is_nullable":true,"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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gRW50cnk8P1xET01FbGVtZW50PgogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":655,"slug":"html-entry","name":"html_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":"value","type":[{"name":"Dom\\HTMLDocument","namespace":null,"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":false,"is_nullable":true,"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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gRW50cnk8P0hUTUxEb2N1bWVudD4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":664,"slug":"html-element-entry","name":"html_element_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":"value","type":[{"name":"Dom\\HTMLElement","namespace":null,"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":false,"is_nullable":true,"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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gRW50cnk8P0hUTUxFbGVtZW50PgogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":673,"slug":"entries","name":"entries","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"entries","type":[{"name":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"Entries","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBFbnRyeTxtaXhlZD4gLi4uJGVudHJpZXMKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":687,"slug":"struct-entry","name":"struct_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":"value","type":[{"name":"array","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":"StructureType","namespace":"Flow\\Types\\Type\\Logical","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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSA\/YXJyYXk8c3RyaW5nLCBtaXhlZD4gJHZhbHVlCiAqIEBwYXJhbSBTdHJ1Y3R1cmVUeXBlPFQ+ICR0eXBlCiAqCiAqIEByZXR1cm4gRW50cnk8P2FycmF5PHN0cmluZywgVD4+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":701,"slug":"structure-entry","name":"structure_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":"value","type":[{"name":"array","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":"StructureType","namespace":"Flow\\Types\\Type\\Logical","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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSA\/YXJyYXk8c3RyaW5nLCBtaXhlZD4gJHZhbHVlCiAqIEBwYXJhbSBTdHJ1Y3R1cmVUeXBlPFQ+ICR0eXBlCiAqCiAqIEByZXR1cm4gRW50cnk8P2FycmF5PHN0cmluZywgVD4+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":715,"slug":"list-entry","name":"list_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":"value","type":[{"name":"array","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":"ListType","namespace":"Flow\\Types\\Type\\Logical","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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBudWxsfGxpc3Q8bWl4ZWQ+ICR2YWx1ZQogKiBAcGFyYW0gTGlzdFR5cGU8VD4gJHR5cGUKICoKICogQHJldHVybiBFbnRyeTxtaXhlZD4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":730,"slug":"map-entry","name":"map_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":"value","type":[{"name":"array","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":false,"is_nullable":true,"is_variadic":false,"default_value":null},{"name":"mapType","type":[{"name":"MapType","namespace":"Flow\\Types\\Type\\Logical","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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"ENTRY"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUS2V5IG9mIGFycmF5LWtleQogKiBAdGVtcGxhdGUgVFZhbHVlCiAqCiAqIEBwYXJhbSA\/YXJyYXk8YXJyYXkta2V5LCBtaXhlZD4gJHZhbHVlCiAqIEBwYXJhbSBNYXBUeXBlPFRLZXksIFRWYWx1ZT4gJG1hcFR5cGUKICoKICogQHJldHVybiBFbnRyeTw\/YXJyYXk8VEtleSwgVFZhbHVlPj4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":739,"slug":"row","name":"row","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"entry","type":[{"name":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"Row","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBFbnRyeTxtaXhlZD4gLi4uJGVudHJ5CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":745,"slug":"rows","name":"rows","namespace":"Flow\\ETL\\DSL","parameters":[{"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":755,"slug":"rows-partitioned","name":"rows_partitioned","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"rows","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":"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":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\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxSb3c+ICRyb3dzCiAqIEBwYXJhbSBhcnJheTxcRmxvd1xGaWxlc3lzdGVtXFBhcnRpdGlvbnxzdHJpbmc+fFBhcnRpdGlvbnMgJHBhcnRpdGlvbnMKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":764,"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":"EntryReference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":774,"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":"EntryReference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"columns","option":"create"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIEFuIGFsaWFzIGZvciBgcmVmYC4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":781,"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":"EntryReference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"columns","option":"create"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":787,"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\\ETL\\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":793,"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\\ETL\\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":799,"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\\ETL\\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":805,"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\\ETL\\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":811,"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\\ETL\\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":817,"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\\ETL\\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":826,"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\\ETL\\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":832,"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\\ETL\\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":841,"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\\ETL\\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":847,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":854,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"columns","option":"create"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":860,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"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":"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":872,"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":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":881,"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\\ETL\\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":887,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":896,"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\\ETL\\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":906,"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\\ETL\\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":915,"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\\ETL\\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":921,"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":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"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":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"string","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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":927,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":933,"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":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"Sort","namespace":"Flow\\ETL\\Function\\ArraySort","is_nullable":false,"is_variadic":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":"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":946,"slug":"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":"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":"ArrayReverse","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":952,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":958,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":964,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":970,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":976,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":982,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":992,"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\\ETL\\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":1001,"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\\ETL\\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":1010,"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\\ETL\\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":1016,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"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":"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\\ETL\\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":1031,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"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":"count","name":"count","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"function","type":[{"name":"EntryReference","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\\ETL\\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":1050,"slug":"call","name":"call","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"callable","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"callable","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":"return_type","type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"CallUserFunc","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIENhbGxzIGEgdXNlci1kZWZpbmVkIGZ1bmN0aW9uIHdpdGggdGhlIGdpdmVuIHBhcmFtZXRlcnMuCiAqCiAqIEBwYXJhbSBjYWxsYWJsZXxTY2FsYXJGdW5jdGlvbiAkY2FsbGFibGUKICogQHBhcmFtIGFycmF5PG1peGVkPiAkcGFyYW1ldGVycwogKiBAcGFyYW0gbnVsbHxUeXBlPG1peGVkPiAkcmV0dXJuX3R5cGUKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1079,"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":"skip_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":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"entry_prefix","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":"ArrayUnpack","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxhcnJheS1rZXksIG1peGVkPnxTY2FsYXJGdW5jdGlvbiAkYXJyYXkKICogQHBhcmFtIGFycmF5PGFycmF5LWtleSwgbWl4ZWQ+fFNjYWxhckZ1bmN0aW9uICRza2lwX2tleXMKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1105,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":"LyoqCiAqIEV4cGFuZHMgZWFjaCB2YWx1ZSBpbnRvIGVudHJ5LCBpZiB0aGVyZSBhcmUgbW9yZSB0aGFuIG9uZSB2YWx1ZSwgbXVsdGlwbGUgcm93cyB3aWxsIGJlIGNyZWF0ZWQuCiAqIEFycmF5IGtleXMgYXJlIGlnbm9yZWQsIG9ubHkgdmFsdWVzIGFyZSB1c2VkIHRvIGNyZWF0ZSBuZXcgcm93cy4KICoKICogQmVmb3JlOgogKiAgICstLSstLS0tLS0tLS0tLS0tLS0tLS0tKwogKiAgIHxpZHwgICAgICAgICAgICAgIGFycmF5fAogKiAgICstLSstLS0tLS0tLS0tLS0tLS0tLS0tKwogKiAgIHwgMXx7ImEiOjEsImIiOjIsImMiOjN9fAogKiAgICstLSstLS0tLS0tLS0tLS0tLS0tLS0tKwogKgogKiBBZnRlcjoKICogICArLS0rLS0tLS0tLS0rCiAqICAgfGlkfGV4cGFuZGVkfAogKiAgICstLSstLS0tLS0tLSsKICogICB8IDF8ICAgICAgIDF8CiAqICAgfCAxfCAgICAgICAyfAogKiAgIHwgMXwgICAgICAgM3wKICogICArLS0rLS0tLS0tLS0rCiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1111,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"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":"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1123,"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},{"name":"null","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1129,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"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":"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"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":"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"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":"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1153,"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\\ETL\\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":1159,"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\\ETL\\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":1165,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1171,"slug":"to-timezone","name":"to_timezone","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"value","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"DateTimeInterface","namespace":"","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"timeZone","type":[{"name":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false},{"name":"DateTimeZone","namespace":"","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"ToTimeZone","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1177,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1183,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1189,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1195,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1201,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1207,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1213,"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":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_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":"Regex","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1219,"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":"ScalarFunction","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_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":"RegexAll","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1225,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1231,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1237,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1243,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1254,"slug":"to-entry","name":"to_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":"data","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":"entryFactory","type":[{"name":"EntryFactory","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":"Entry","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxtaXhlZD4gJGRhdGEKICoKICogQHJldHVybiBFbnRyeTxtaXhlZD4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1265,"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":"entryFactory","type":[{"name":"EntryFactory","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"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":"[]"},{"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":"Row","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxhcnJheTxtaXhlZD4+fGFycmF5PG1peGVkfHN0cmluZz4gJGRhdGEKICogQHBhcmFtIGFycmF5PFBhcnRpdGlvbj58UGFydGl0aW9ucyAkcGFydGl0aW9ucwogKiBAcGFyYW0gbnVsbHxTY2hlbWEgJHNjaGVtYQogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1310,"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":"entryFactory","type":[{"name":"EntryFactory","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"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":"[]"},{"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":"Rows","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxhcnJheTxtaXhlZD4+fGFycmF5PG1peGVkfHN0cmluZz4gJGRhdGEKICogQHBhcmFtIGFycmF5PFBhcnRpdGlvbj58UGFydGl0aW9ucyAkcGFydGl0aW9ucwogKiBAcGFyYW0gbnVsbHxTY2hlbWEgJHNjaGVtYQogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1339,"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\\ETL\\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":1345,"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\\ETL\\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":1351,"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\\ETL\\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":1357,"slug":"average","name":"average","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"ref","type":[{"name":"EntryReference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"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\\ETL\\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":1363,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1369,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCALAR_FUNCTION"}}],"scalar_function_chain":true,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1375,"slug":"collect","name":"collect","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"ref","type":[{"name":"EntryReference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","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\\ETL\\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":1381,"slug":"string-agg","name":"string_agg","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"ref","type":[{"name":"EntryReference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"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\\ETL\\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":1387,"slug":"collect-unique","name":"collect_unique","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"ref","type":[{"name":"EntryReference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","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\\ETL\\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":1393,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1399,"slug":"sum","name":"sum","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"ref","type":[{"name":"EntryReference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Sum","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":1405,"slug":"first","name":"first","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"ref","type":[{"name":"EntryReference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","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\\ETL\\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":1411,"slug":"last","name":"last","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"ref","type":[{"name":"EntryReference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","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\\ETL\\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":1417,"slug":"max","name":"max","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"ref","type":[{"name":"EntryReference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","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\\ETL\\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":1423,"slug":"min","name":"min","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"ref","type":[{"name":"EntryReference","namespace":"Flow\\ETL\\Row","is_nullable":false,"is_variadic":false},{"name":"string","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\\ETL\\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":1429,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1440,"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\\ETL\\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":1449,"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\\ETL\\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":1458,"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\\ETL\\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":1467,"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\\ETL\\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":1477,"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":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":1483,"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\\ETL\\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":1489,"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\\ETL\\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":1495,"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\\ETL\\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":1504,"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\\ETL\\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":1516,"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\\ETL\\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":1525,"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\\ETL\\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":1531,"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\\ETL\\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":"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\\ETL\\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":1546,"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\\ETL\\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":1552,"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\\ETL\\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":1558,"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\\ETL\\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":"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUS2V5IG9mIGFycmF5LWtleQogKiBAdGVtcGxhdGUgVFZhbHVlCiAqCiAqIEBwYXJhbSBNYXBUeXBlPFRLZXksIFRWYWx1ZT58VHlwZTxhcnJheTxUS2V5LCBUVmFsdWU+PiAkdHlwZQogKgogKiBAcmV0dXJuIE1hcERlZmluaXRpb248VEtleSwgVFZhbHVlPgogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1586,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBMaXN0VHlwZTxUPnxUeXBlPGxpc3Q8VD4+ICR0eXBlCiAqCiAqIEByZXR1cm4gTGlzdERlZmluaXRpb248VD4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1600,"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\\ETL\\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":1606,"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":"StringDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1612,"slug":"datetime-schema","name":"datetime_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","type":[{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"nullable","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"},{"name":"metadata","type":[{"name":"Metadata","namespace":"Flow\\ETL\\Schema","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"DateTimeDefinition","namespace":"Flow\\ETL\\Schema\\Definition","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":1618,"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\\ETL\\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":1624,"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\\ETL\\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":1630,"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\\ETL\\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":1636,"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\\ETL\\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":1642,"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\\ETL\\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":1648,"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\\ETL\\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":1654,"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\\ETL\\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":1667,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBTdHJ1Y3R1cmVUeXBlPFQ+fFR5cGU8YXJyYXk8c3RyaW5nLCBUPj4gJHR5cGUKICoKICogQHJldHVybiBTdHJ1Y3R1cmVEZWZpbml0aW9uPFQ+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1674,"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\\ETL\\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":1687,"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\\ETL\\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":1720,"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\\ETL\\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":1746,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1752,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1758,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1764,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1773,"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\\ETL\\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":1779,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1788,"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\\ETL\\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":1794,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1803,"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\\ETL\\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":1809,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"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":"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\\ETL\\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":1824,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1834,"slug":"execution-strict","name":"execution_strict","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"ExecutionMode","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEluIHRoaXMgbW9kZSwgZnVuY3Rpb25zIHRocm93cyBleGNlcHRpb25zIGlmIHRoZSBnaXZlbiBlbnRyeSBpcyBub3QgZm91bmQKICogb3IgcGFzc2VkIHBhcmFtZXRlcnMgYXJlIGludmFsaWQuCiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1843,"slug":"execution-lenient","name":"execution_lenient","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"ExecutionMode","namespace":"Flow\\ETL\\Function","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEluIHRoaXMgbW9kZSwgZnVuY3Rpb25zIHJldHVybnMgbnVsbHMgaW5zdGVhZCBvZiB0aHJvd2luZyBleGNlcHRpb25zLgogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1849,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1855,"slug":"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\\ETL\\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":1861,"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\\ETL\\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":1867,"slug":"compare-all","name":"compare_all","namespace":"Flow\\ETL\\DSL","parameters":[{"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\\ETL\\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":1873,"slug":"compare-any","name":"compare_any","namespace":"Flow\\ETL\\DSL","parameters":[{"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\\ETL\\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":"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"join","example":"join"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"join","example":"join_each"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxcRmxvd1xFVExcSm9pblxDb21wYXJpc29ufHN0cmluZz58Q29tcGFyaXNvbiAkY29tcGFyaXNvbnMKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1890,"slug":"compare-entries-by-name","name":"compare_entries_by_name","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"order","type":[{"name":"Order","namespace":"Flow\\ETL\\Transformer\\OrderEntries","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Transformer\\OrderEntries\\Order::..."}],"return_type":[{"name":"Comparator","namespace":"Flow\\ETL\\Transformer\\OrderEntries","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1896,"slug":"compare-entries-by-name-desc","name":"compare_entries_by_name_desc","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"Comparator","namespace":"Flow\\ETL\\Transformer\\OrderEntries","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1905,"slug":"compare-entries-by-type","name":"compare_entries_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":"Order","namespace":"Flow\\ETL\\Transformer\\OrderEntries","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Transformer\\OrderEntries\\Order::..."}],"return_type":[{"name":"Comparator","namespace":"Flow\\ETL\\Transformer\\OrderEntries","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxjbGFzcy1zdHJpbmc8RW50cnk8bWl4ZWQ+PiwgaW50PiAkcHJpb3JpdGllcwogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1914,"slug":"compare-entries-by-type-desc","name":"compare_entries_by_type_desc","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":"[...]"}],"return_type":[{"name":"Comparator","namespace":"Flow\\ETL\\Transformer\\OrderEntries","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxjbGFzcy1zdHJpbmc8RW50cnk8bWl4ZWQ+PiwgaW50PiAkcHJpb3JpdGllcwogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1923,"slug":"compare-entries-by-type-and-name","name":"compare_entries_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":"Order","namespace":"Flow\\ETL\\Transformer\\OrderEntries","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Transformer\\OrderEntries\\Order::..."}],"return_type":[{"name":"Comparator","namespace":"Flow\\ETL\\Transformer\\OrderEntries","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxjbGFzcy1zdHJpbmc8RW50cnk8bWl4ZWQ+PiwgaW50PiAkcHJpb3JpdGllcwogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1936,"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\\ETL\\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":1970,"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":"NativePHPRandomValueGenerator","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\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1976,"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":"NativePHPRandomValueGenerator","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\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1982,"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\\ETL\\Attribute","arguments":{"module":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1990,"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\\ETL\\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":2007,"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\\ETL\\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":2024,"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\\ETL\\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":2041,"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\\ETL\\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":2047,"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\\ETL\\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":2053,"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\\ETL\\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":"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\\ETL\\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":"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\\ETL\\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":2079,"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\\ETL\\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":2085,"slug":"retry-any-throwable","name":"retry_any_throwable","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"limit","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"AnyThrowable","namespace":"Flow\\ETL\\Retry\\RetryStrategy","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":2094,"slug":"retry-on-exception-types","name":"retry_on_exception_types","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"exception_types","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"limit","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"OnExceptionTypes","namespace":"Flow\\ETL\\Retry\\RetryStrategy","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxjbGFzcy1zdHJpbmc8XFRocm93YWJsZT4+ICRleGNlcHRpb25fdHlwZXMKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2100,"slug":"delay-linear","name":"delay_linear","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"delay","type":[{"name":"Duration","namespace":"Flow\\ETL\\Time","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"increment","type":[{"name":"Duration","namespace":"Flow\\ETL\\Time","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Linear","namespace":"Flow\\ETL\\Retry\\DelayFactory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":2106,"slug":"delay-exponential","name":"delay_exponential","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"base","type":[{"name":"Duration","namespace":"Flow\\ETL\\Time","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"multiplier","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"2"},{"name":"max_delay","type":[{"name":"Duration","namespace":"Flow\\ETL\\Time","is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Exponential","namespace":"Flow\\ETL\\Retry\\DelayFactory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":2115,"slug":"delay-jitter","name":"delay_jitter","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"delay","type":[{"name":"DelayFactory","namespace":"Flow\\ETL\\Retry","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"jitter_factor","type":[{"name":"float","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Jitter","namespace":"Flow\\ETL\\Retry\\DelayFactory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBmbG9hdCAkaml0dGVyX2ZhY3RvciBhIHZhbHVlIGJldHdlZW4gMCBhbmQgMSByZXByZXNlbnRpbmcgdGhlIG1heGltdW0gcGVyY2VudGFnZSBvZiBqaXR0ZXIgdG8gYXBwbHkKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2121,"slug":"delay-fixed","name":"delay_fixed","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"delay","type":[{"name":"Duration","namespace":"Flow\\ETL\\Time","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Fixed","namespace":"Flow\\ETL\\Retry\\DelayFactory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":2127,"slug":"duration-seconds","name":"duration_seconds","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"seconds","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Duration","namespace":"Flow\\ETL\\Time","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":2133,"slug":"duration-milliseconds","name":"duration_milliseconds","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"milliseconds","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Duration","namespace":"Flow\\ETL\\Time","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":2139,"slug":"duration-microseconds","name":"duration_microseconds","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"microseconds","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Duration","namespace":"Flow\\ETL\\Time","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":2145,"slug":"duration-minutes","name":"duration_minutes","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"minutes","type":[{"name":"int","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"Duration","namespace":"Flow\\ETL\\Time","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":2151,"slug":"write-with-retries","name":"write_with_retries","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"loader","type":[{"name":"Loader","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"retry_strategy","type":[{"name":"RetryStrategy","namespace":"Flow\\ETL\\Retry","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Retry\\RetryStrategy\\AnyThrowable::..."},{"name":"delay_factory","type":[{"name":"DelayFactory","namespace":"Flow\\ETL\\Retry","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Retry\\DelayFactory\\Fixed\\FixedMilliseconds::..."},{"name":"sleep","type":[{"name":"Sleep","namespace":"Flow\\ETL\\Time","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Time\\SystemSleep::..."}],"return_type":[{"name":"RetryLoader","namespace":"Flow\\ETL\\Loader","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":2161,"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\\ETL\\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":13,"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}],"return_type":[{"name":"AvroExtractor","namespace":"Flow\\ETL\\Adapter\\Avro\\FlixTech","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":21,"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"}],"return_type":[{"name":"AvroLoader","namespace":"Flow\\ETL\\Adapter\\Avro\\FlixTech","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":14,"slug":"bar-chart","name":"bar_chart","namespace":"Flow\\ETL\\Adapter\\ChartJS","parameters":[{"name":"label","type":[{"name":"EntryReference","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\\ETL\\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":20,"slug":"line-chart","name":"line_chart","namespace":"Flow\\ETL\\Adapter\\ChartJS","parameters":[{"name":"label","type":[{"name":"EntryReference","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\\ETL\\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":26,"slug":"pie-chart","name":"pie_chart","namespace":"Flow\\ETL\\Adapter\\ChartJS","parameters":[{"name":"label","type":[{"name":"EntryReference","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\\ETL\\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":32,"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\\ETL\\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":43,"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"}],"return_type":[{"name":"ChartJSLoader","namespace":"Flow\\ETL\\Adapter\\ChartJS","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":71,"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\\ETL\\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":25,"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":"1000"},{"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":"CSVExtractor","namespace":"Flow\\ETL\\Adapter\\CSV","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CSV","type":"EXTRACTOR"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_reading","option":"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":70,"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'"}],"return_type":[{"name":"CSVLoader","namespace":"Flow\\ETL\\Adapter\\CSV","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":95,"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\\ETL\\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":36,"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\\ETL\\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":56,"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\\ETL\\Attribute","arguments":{"module":"DOCTRINE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBDb25uZWN0aW9uICRjb25uZWN0aW9uCiAqIEBwYXJhbSBzdHJpbmd8VGFibGUgJHRhYmxlCiAqIEBwYXJhbSBhcnJheTxPcmRlckJ5PnxPcmRlckJ5ICRvcmRlcl9ieQogKiBAcGFyYW0gaW50ICRwYWdlX3NpemUKICogQHBhcmFtIG51bGx8aW50ICRtYXhpbXVtCiAqCiAqIEB0aHJvd3MgSW52YWxpZEFyZ3VtZW50RXhjZXB0aW9uCiAqLw=="},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":83,"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\\ETL\\Attribute","arguments":{"module":"DOCTRINE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBDb25uZWN0aW9uICRjb25uZWN0aW9uCiAqIEBwYXJhbSBpbnQgJHBhZ2Vfc2l6ZQogKiBAcGFyYW0gbnVsbHxpbnQgJG1heGltdW0gLSBtYXhpbXVtIGNhbiBhbHNvIGJlIHRha2VuIGZyb20gYSBxdWVyeSBidWlsZGVyLCAkbWF4aW11bSBob3dldmVyIGlzIHVzZWQgcmVnYXJkbGVzcyBvZiB0aGUgcXVlcnkgYnVpbGRlciBpZiBpdCdzIHNldAogKiBAcGFyYW0gaW50ICRvZmZzZXQgLSBvZmZzZXQgY2FuIGFsc28gYmUgdGFrZW4gZnJvbSBhIHF1ZXJ5IGJ1aWxkZXIsICRvZmZzZXQgaG93ZXZlciBpcyB1c2VkIHJlZ2FyZGxlc3Mgb2YgdGhlIHF1ZXJ5IGJ1aWxkZXIgaWYgaXQncyBzZXQgdG8gbm9uIDAgdmFsdWUKICov"},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":104,"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\\ETL\\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\\ETL\\Attribute","arguments":{"module":"DOCTRINE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBudWxsfFBhcmFtZXRlcnNTZXQgJHBhcmFtZXRlcnNfc2V0IC0gZWFjaCBvbmUgcGFyYW1ldGVycyBhcnJheSB3aWxsIGJlIGV2YWx1YXRlZCBhcyBuZXcgcXVlcnkKICogQHBhcmFtIGFycmF5PGludHxzdHJpbmcsIERiYWxBcnJheVR5cGV8RGJhbFBhcmFtZXRlclR5cGV8RGJhbFR5cGV8aW50fHN0cmluZz4gJHR5cGVzCiAqLw=="},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":147,"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\\ETL\\Attribute","arguments":{"module":"DOCTRINE","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBkZXByZWNhdGVkIHVzZSBmcm9tX2RiYWxfcXVlcmllcygpIGluc3RlYWQKICoKICogQHBhcmFtIG51bGx8UGFyYW1ldGVyc1NldCAkcGFyYW1ldGVyc19zZXQgLSBlYWNoIG9uZSBwYXJhbWV0ZXJzIGFycmF5IHdpbGwgYmUgZXZhbHVhdGVkIGFzIG5ldyBxdWVyeQogKiBAcGFyYW0gYXJyYXk8aW50fHN0cmluZywgRGJhbEFycmF5VHlwZXxEYmFsUGFyYW1ldGVyVHlwZXxEYmFsVHlwZXxpbnR8c3RyaW5nPiAkdHlwZXMKICov"},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":161,"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\\ETL\\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":182,"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\\ETL\\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":208,"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\\ETL\\Attribute","arguments":{"module":"DOCTRINE","type":"LOADER"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_writing","option":"database_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":228,"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\\ETL\\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":248,"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\\ETL\\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":265,"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\\ETL\\Attribute","arguments":{"module":"DOCTRINE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENvbnZlcnRzIGEgRmxvd1xFVExcU2NoZW1hIHRvIGEgRG9jdHJpbmVcREJBTFxTY2hlbWFcVGFibGUuCiAqCiAqIEBwYXJhbSBTY2hlbWEgJHNjaGVtYQogKiBAcGFyYW0gYXJyYXk8YXJyYXkta2V5LCBtaXhlZD4gJHRhYmxlX29wdGlvbnMKICogQHBhcmFtIGFycmF5PGNsYXNzLXN0cmluZzxcRmxvd1xUeXBlc1xUeXBlPG1peGVkPj4sIGNsYXNzLXN0cmluZzxcRG9jdHJpbmVcREJBTFxUeXBlc1xUeXBlPj4gJHR5cGVzX21hcAogKi8="},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":278,"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\\ETL\\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":289,"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\\ETL\\Attribute","arguments":{"module":"DOCTRINE","type":"HELPER"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_writing","option":"database_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":298,"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\\ETL\\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":308,"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\\ETL\\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":318,"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\\ETL\\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":339,"slug":"to-dbal-transaction","name":"to_dbal_transaction","namespace":"Flow\\ETL\\Adapter\\Doctrine","parameters":[{"name":"connection","type":[{"name":"Connection","namespace":"Doctrine\\DBAL","is_nullable":false,"is_variadic":false},{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"name":"loaders","type":[{"name":"Loader","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":true,"default_value":null}],"return_type":[{"name":"TransactionalDbalLoader","namespace":"Flow\\ETL\\Adapter\\Doctrine","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"DOCTRINE","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEV4ZWN1dGUgbXVsdGlwbGUgbG9hZGVycyB3aXRoaW4gYSBkYXRhYmFzZSB0cmFuc2FjdGlvbi4KICogRWFjaCBiYXRjaCBvZiByb3dzIHdpbGwgYmUgcHJvY2Vzc2VkIGluIGl0cyBvd24gdHJhbnNhY3Rpb24uCiAqIElmIGFueSBsb2FkZXIgZmFpbHMsIHRoZSBlbnRpcmUgYmF0Y2ggd2lsbCBiZSByb2xsZWQgYmFjay4KICoKICogQHBhcmFtIGFycmF5PHN0cmluZywgbWl4ZWQ+fENvbm5lY3Rpb24gJGNvbm5lY3Rpb24KICogQHBhcmFtIExvYWRlciAuLi4kbG9hZGVycyAtIExvYWRlcnMgdG8gZXhlY3V0ZSB3aXRoaW4gdGhlIHRyYW5zYWN0aW9uCiAqCiAqIEB0aHJvd3MgSW52YWxpZEFyZ3VtZW50RXhjZXB0aW9uCiAqLw=="},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":349,"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},{"name":"int","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\\ETL\\Attribute","arguments":{"module":"DOCTRINE","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-doctrine\/src\/Flow\/ETL\/Adapter\/Doctrine\/functions.php","start_line_in_file":355,"slug":"pagination-key-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},{"name":"int","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\\ETL\\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":361,"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\\ETL\\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":18,"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}],"return_type":[{"name":"ExcelExtractor","namespace":"Flow\\ETL\\Adapter\\Excel","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":25,"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}],"return_type":[{"name":"ExcelLoader","namespace":"Flow\\ETL\\Adapter\\Excel","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":31,"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\\ETL\\Attribute","arguments":{"module":"EXCEL","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-elasticsearch\/src\/Flow\/ETL\/Adapter\/Elasticsearch\/functions.php","start_line_in_file":36,"slug":"to-es-bulk-index","name":"to_es_bulk_index","namespace":"Flow\\ETL\\Adapter\\Elasticsearch","parameters":[{"name":"config","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":"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},{"name":"id_factory","type":[{"name":"IdFactory","namespace":"Flow\\ETL\\Adapter\\Elasticsearch","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":"ElasticsearchLoader","namespace":"Flow\\ETL\\Adapter\\Elasticsearch\\ElasticsearchPHP","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"ELASTIC_SEARCH","type":"LOADER"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_writing","option":"elasticsearch"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIGh0dHBzOi8vd3d3LmVsYXN0aWMuY28vZ3VpZGUvZW4vZWxhc3RpY3NlYXJjaC9yZWZlcmVuY2UvbWFzdGVyL2RvY3MtYnVsay5odG1sLgogKgogKiBJbiBvcmRlciB0byBjb250cm9sIHRoZSBzaXplIG9mIHRoZSBzaW5nbGUgcmVxdWVzdCwgdXNlIERhdGFGcmFtZTo6Y2h1bmtTaXplKCkgbWV0aG9kIGp1c3QgYmVmb3JlIGNhbGxpbmcgRGF0YUZyYW1lOjpsb2FkKCkuCiAqCiAqIEBwYXJhbSBhcnJheXsKICogIGhvc3RzPzogYXJyYXk8c3RyaW5nPiwKICogIGNvbm5lY3Rpb25QYXJhbXM\/OiBhcnJheTxtaXhlZD4sCiAqICByZXRyaWVzPzogaW50LAogKiAgc25pZmZPblN0YXJ0PzogYm9vbCwKICogIHNzbENlcnQ\/OiBhcnJheTxzdHJpbmc+LAogKiAgc3NsS2V5PzogYXJyYXk8c3RyaW5nPiwKICogIHNzbFZlcmlmaWNhdGlvbj86IGJvb2x8c3RyaW5nLAogKiAgZWxhc3RpY01ldGFIZWFkZXI\/OiBib29sLAogKiAgaW5jbHVkZVBvcnRJbkhvc3RIZWFkZXI\/OiBib29sCiAqIH0gJGNvbmZpZwogKiBAcGFyYW0gc3RyaW5nICRpbmRleAogKiBAcGFyYW0gSWRGYWN0b3J5ICRpZF9mYWN0b3J5CiAqIEBwYXJhbSBhcnJheTxtaXhlZD4gJHBhcmFtZXRlcnMgLSBodHRwczovL3d3dy5lbGFzdGljLmNvL2d1aWRlL2VuL2VsYXN0aWNzZWFyY2gvcmVmZXJlbmNlL21hc3Rlci9kb2NzLWJ1bGsuaHRtbCAtIEBkZXByZWNhdGVkIHVzZSB3aXRoUGFyYW1ldGVycyBtZXRob2QgaW5zdGVhZAogKi8="},{"repository_path":"src\/adapter\/etl-adapter-elasticsearch\/src\/Flow\/ETL\/Adapter\/Elasticsearch\/functions.php","start_line_in_file":47,"slug":"entry-id-factory","name":"entry_id_factory","namespace":"Flow\\ETL\\Adapter\\Elasticsearch","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}],"return_type":[{"name":"IdFactory","namespace":"Flow\\ETL\\Adapter\\Elasticsearch","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"ELASTIC_SEARCH","type":"HELPER"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_writing","option":"elasticsearch"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-elasticsearch\/src\/Flow\/ETL\/Adapter\/Elasticsearch\/functions.php","start_line_in_file":53,"slug":"hash-id-factory","name":"hash_id_factory","namespace":"Flow\\ETL\\Adapter\\Elasticsearch","parameters":[{"name":"entry_names","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":"IdFactory","namespace":"Flow\\ETL\\Adapter\\Elasticsearch","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"ELASTIC_SEARCH","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/adapter\/etl-adapter-elasticsearch\/src\/Flow\/ETL\/Adapter\/Elasticsearch\/functions.php","start_line_in_file":79,"slug":"to-es-bulk-update","name":"to_es_bulk_update","namespace":"Flow\\ETL\\Adapter\\Elasticsearch","parameters":[{"name":"config","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":"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},{"name":"id_factory","type":[{"name":"IdFactory","namespace":"Flow\\ETL\\Adapter\\Elasticsearch","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":"ElasticsearchLoader","namespace":"Flow\\ETL\\Adapter\\Elasticsearch\\ElasticsearchPHP","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"ELASTIC_SEARCH","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqICBodHRwczovL3d3dy5lbGFzdGljLmNvL2d1aWRlL2VuL2VsYXN0aWNzZWFyY2gvcmVmZXJlbmNlL21hc3Rlci9kb2NzLWJ1bGsuaHRtbC4KICoKICogSW4gb3JkZXIgdG8gY29udHJvbCB0aGUgc2l6ZSBvZiB0aGUgc2luZ2xlIHJlcXVlc3QsIHVzZSBEYXRhRnJhbWU6OmNodW5rU2l6ZSgpIG1ldGhvZCBqdXN0IGJlZm9yZSBjYWxsaW5nIERhdGFGcmFtZTo6bG9hZCgpLgogKgogKiBAcGFyYW0gYXJyYXl7CiAqICBob3N0cz86IGFycmF5PHN0cmluZz4sCiAqICBjb25uZWN0aW9uUGFyYW1zPzogYXJyYXk8bWl4ZWQ+LAogKiAgcmV0cmllcz86IGludCwKICogIHNuaWZmT25TdGFydD86IGJvb2wsCiAqICBzc2xDZXJ0PzogYXJyYXk8c3RyaW5nPiwKICogIHNzbEtleT86IGFycmF5PHN0cmluZz4sCiAqICBzc2xWZXJpZmljYXRpb24\/OiBib29sfHN0cmluZywKICogIGVsYXN0aWNNZXRhSGVhZGVyPzogYm9vbCwKICogIGluY2x1ZGVQb3J0SW5Ib3N0SGVhZGVyPzogYm9vbAogKiB9ICRjb25maWcKICogQHBhcmFtIHN0cmluZyAkaW5kZXgKICogQHBhcmFtIElkRmFjdG9yeSAkaWRfZmFjdG9yeQogKiBAcGFyYW0gYXJyYXk8bWl4ZWQ+ICRwYXJhbWV0ZXJzIC0gaHR0cHM6Ly93d3cuZWxhc3RpYy5jby9ndWlkZS9lbi9lbGFzdGljc2VhcmNoL3JlZmVyZW5jZS9tYXN0ZXIvZG9jcy1idWxrLmh0bWwgLSBAZGVwcmVjYXRlZCB1c2Ugd2l0aFBhcmFtZXRlcnMgbWV0aG9kIGluc3RlYWQKICov"},{"repository_path":"src\/adapter\/etl-adapter-elasticsearch\/src\/Flow\/ETL\/Adapter\/Elasticsearch\/functions.php","start_line_in_file":95,"slug":"es-hits-to-rows","name":"es_hits_to_rows","namespace":"Flow\\ETL\\Adapter\\Elasticsearch","parameters":[{"name":"source","type":[{"name":"DocumentDataSource","namespace":"Flow\\ETL\\Adapter\\Elasticsearch\\ElasticsearchPHP","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\ETL\\Adapter\\Elasticsearch\\ElasticsearchPHP\\DocumentDataSource::..."}],"return_type":[{"name":"HitsIntoRowsTransformer","namespace":"Flow\\ETL\\Adapter\\Elasticsearch\\ElasticsearchPHP","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"ELASTIC_SEARCH","type":"HELPER"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_writing","option":"elasticsearch"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFRyYW5zZm9ybXMgZWxhc3RpY3NlYXJjaCByZXN1bHRzIGludG8gY2xlYXIgRmxvdyBSb3dzIHVzaW5nIFsnaGl0cyddWydoaXRzJ11beF1bJ19zb3VyY2UnXS4KICoKICogQHJldHVybiBIaXRzSW50b1Jvd3NUcmFuc2Zvcm1lcgogKi8="},{"repository_path":"src\/adapter\/etl-adapter-elasticsearch\/src\/Flow\/ETL\/Adapter\/Elasticsearch\/functions.php","start_line_in_file":124,"slug":"from-es","name":"from_es","namespace":"Flow\\ETL\\Adapter\\Elasticsearch","parameters":[{"name":"config","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":"parameters","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":"pit_params","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":"ElasticsearchExtractor","namespace":"Flow\\ETL\\Adapter\\Elasticsearch\\ElasticsearchPHP","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"ELASTIC_SEARCH","type":"EXTRACTOR"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_reading","option":"elasticsearch"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEV4dHJhY3RvciB3aWxsIGF1dG9tYXRpY2FsbHkgdHJ5IHRvIGl0ZXJhdGUgb3ZlciB3aG9sZSBpbmRleCB1c2luZyBvbmUgb2YgdGhlIHR3byBpdGVyYXRpb24gbWV0aG9kczouCiAqCiAqIC0gZnJvbS9zaXplCiAqIC0gc2VhcmNoX2FmdGVyCiAqCiAqIFNlYXJjaCBhZnRlciBpcyBzZWxlY3RlZCB3aGVuIHlvdSBwcm92aWRlIGRlZmluZSBzb3J0IHBhcmFtZXRlcnMgaW4gcXVlcnksIG90aGVyd2lzZSBpdCB3aWxsIGZhbGxiYWNrIHRvIGZyb20vc2l6ZS4KICoKICogQHBhcmFtIGFycmF5ewogKiAgaG9zdHM\/OiBhcnJheTxzdHJpbmc+LAogKiAgY29ubmVjdGlvblBhcmFtcz86IGFycmF5PG1peGVkPiwKICogIHJldHJpZXM\/OiBpbnQsCiAqICBzbmlmZk9uU3RhcnQ\/OiBib29sLAogKiAgc3NsQ2VydD86IGFycmF5PHN0cmluZz4sCiAqICBzc2xLZXk\/OiBhcnJheTxzdHJpbmc+LAogKiAgc3NsVmVyaWZpY2F0aW9uPzogYm9vbHxzdHJpbmcsCiAqICBlbGFzdGljTWV0YUhlYWRlcj86IGJvb2wsCiAqICBpbmNsdWRlUG9ydEluSG9zdEhlYWRlcj86IGJvb2wKICogfSAkY29uZmlnCiAqIEBwYXJhbSBhcnJheTxtaXhlZD4gJHBhcmFtZXRlcnMgLSBodHRwczovL3d3dy5lbGFzdGljLmNvL2d1aWRlL2VuL2VsYXN0aWNzZWFyY2gvcmVmZXJlbmNlL21hc3Rlci9zZWFyY2gtc2VhcmNoLmh0bWwKICogQHBhcmFtID9hcnJheTxtaXhlZD4gJHBpdF9wYXJhbXMgLSB3aGVuIHVzZWQgZXh0cmFjdG9yIHdpbGwgY3JlYXRlIHBvaW50IGluIHRpbWUgdG8gc3RhYmlsaXplIHNlYXJjaCByZXN1bHRzLiBQb2ludCBpbiB0aW1lIGlzIGF1dG9tYXRpY2FsbHkgY2xvc2VkIHdoZW4gbGFzdCBlbGVtZW50IGlzIGV4dHJhY3RlZC4gaHR0cHM6Ly93d3cuZWxhc3RpYy5jby9ndWlkZS9lbi9lbGFzdGljc2VhcmNoL3JlZmVyZW5jZS9tYXN0ZXIvcG9pbnQtaW4tdGltZS1hcGkuaHRtbCAtIEBkZXByZWNhdGVkIHVzZSB3aXRoUG9pbnRJblRpbWUgbWV0aG9kIGluc3RlYWQKICov"},{"repository_path":"src\/adapter\/etl-adapter-google-sheet\/src\/Flow\/ETL\/Adapter\/GoogleSheet\/functions.php","start_line_in_file":20,"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\\ETL\\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":57,"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\\ETL\\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":15,"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}],"return_type":[{"name":"PsrHttpClientDynamicExtractor","namespace":"Flow\\ETL\\Adapter\\Http","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":29,"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}],"return_type":[{"name":"PsrHttpClientStaticExtractor","namespace":"Flow\\ETL\\Adapter\\Http","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"HTTP","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBpdGVyYWJsZTxSZXF1ZXN0SW50ZXJmYWNlPiAkcmVxdWVzdHMKICov"},{"repository_path":"src\/adapter\/etl-adapter-json\/src\/Flow\/ETL\/Adapter\/JSON\/functions.php","start_line_in_file":20,"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"}],"return_type":[{"name":"JsonExtractor","namespace":"Flow\\ETL\\Adapter\\JSON\\JSONMachine","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"JSON","type":"EXTRACTOR"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_reading","option":"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":45,"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}],"return_type":[{"name":"JsonLinesExtractor","namespace":"Flow\\ETL\\Adapter\\JSON\\JSONMachine","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"JSON","type":"EXTRACTOR"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_reading","option":"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":60,"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"}],"return_type":[{"name":"JsonLoader","namespace":"Flow\\ETL\\Adapter\\JSON","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":80,"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}],"return_type":[{"name":"JsonLinesLoader","namespace":"Flow\\ETL\\Adapter\\JSON","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"JSON","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFVzZWQgdG8gd3JpdGUgdG8gYSBKU09OIGxpbmVzIGh0dHBzOi8vanNvbmxpbmVzLm9yZy8gZm9ybWF0dGVkIGZpbGUuCiAqCiAqIEBwYXJhbSBQYXRofHN0cmluZyAkcGF0aAogKgogKiBAcmV0dXJuIEpzb25MaW5lc0xvYWRlcgogKi8="},{"repository_path":"src\/adapter\/etl-adapter-parquet\/src\/Flow\/ETL\/Adapter\/Parquet\/functions.php","start_line_in_file":28,"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"}],"return_type":[{"name":"ParquetExtractor","namespace":"Flow\\ETL\\Adapter\\Parquet","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PARQUET","type":"EXTRACTOR"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_reading","option":"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":58,"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"}],"return_type":[{"name":"ParquetLoader","namespace":"Flow\\ETL\\Adapter\\Parquet","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PARQUET","type":"LOADER"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_writing","option":"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":86,"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\\ETL\\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":94,"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\\ETL\\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":100,"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\\ETL\\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":106,"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\\ETL\\Attribute","arguments":{"module":"PARQUET","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":15,"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}],"return_type":[{"name":"TextExtractor","namespace":"Flow\\ETL\\Adapter\\Text","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":30,"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'"}],"return_type":[{"name":"Loader","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TEXT","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBQYXRofHN0cmluZyAkcGF0aAogKiBAcGFyYW0gc3RyaW5nICRuZXdfbGluZV9zZXBhcmF0b3IgLSBkZWZhdWx0IFBIUF9FT0wgLSBAZGVwcmVjYXRlZCB1c2Ugd2l0aE5ld0xpbmVTZXBhcmF0b3IgbWV0aG9kIGluc3RlYWQKICoKICogQHJldHVybiBMb2FkZXIKICov"},{"repository_path":"src\/adapter\/etl-adapter-xml\/src\/Flow\/ETL\/Adapter\/XML\/functions.php","start_line_in_file":34,"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":"''"}],"return_type":[{"name":"XMLParserExtractor","namespace":"Flow\\ETL\\Adapter\\XML","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"XML","type":"EXTRACTOR"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_reading","option":"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":50,"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\\DOMDocumentWriter::..."}],"return_type":[{"name":"XMLLoader","namespace":"Flow\\ETL\\Adapter\\XML\\Loader","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":23,"slug":"protocol","name":"protocol","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":"Protocol","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":29,"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\\ETL\\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":35,"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\\ETL\\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":54,"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\\ETL\\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":67,"slug":"path-stdout","name":"path_stdout","namespace":"Flow\\Filesystem\\DSL","parameters":[{"name":"options","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":"Path","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHBhdGggdG8gcGhwIHN0ZG91dCBzdHJlYW0uCiAqCiAqIEBwYXJhbSBudWxsfGFycmF5eydzdHJlYW0nOiAnb3V0cHV0J3wnc3RkZXJyJ3wnc3Rkb3V0J30gJG9wdGlvbnMKICoKICogQHJldHVybiBQYXRoCiAqLw=="},{"repository_path":"src\/lib\/filesystem\/src\/Flow\/Filesystem\/DSL\/functions.php","start_line_in_file":81,"slug":"path-memory","name":"path_memory","namespace":"Flow\\Filesystem\\DSL","parameters":[{"name":"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":"options","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":"Path","namespace":"Flow\\Filesystem","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHBhdGggdG8gcGhwIG1lbW9yeSBzdHJlYW0uCiAqCiAqIEBwYXJhbSBzdHJpbmcgJHBhdGggLSBkZWZhdWx0ID0gJycgLSBwYXRoIGlzIHVzZWQgYXMgYW4gaWRlbnRpZmllciBpbiBtZW1vcnkgZmlsZXN5c3RlbSwgc28gd2UgY2FuIHdyaXRlIG11bHRpcGxlIGZpbGVzIHRvIG1lbW9yeSBhdCBvbmNlLCBlYWNoIHBhdGggaXMgYSBuZXcgaGFuZGxlCiAqIEBwYXJhbSBudWxsfGFycmF5eydzdHJlYW0nOiAnbWVtb3J5J3wndGVtcCd9ICRvcHRpb25zIC0gd2hlbiBub3RoaW5nIGlzIHByb3ZpZGVkLCAndGVtcCcgc3RyZWFtIGlzIHVzZWQgYnkgZGVmYXVsdAogKgogKiBAcmV0dXJuIFBhdGgKICov"},{"repository_path":"src\/lib\/filesystem\/src\/Flow\/Filesystem\/DSL\/functions.php","start_line_in_file":92,"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\\ETL\\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":98,"slug":"native-local-filesystem","name":"native_local_filesystem","namespace":"Flow\\Filesystem\\DSL","parameters":[],"return_type":[{"name":"NativeLocalFilesystem","namespace":"Flow\\Filesystem\\Local","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":108,"slug":"stdout-filesystem","name":"stdout_filesystem","namespace":"Flow\\Filesystem\\DSL","parameters":[],"return_type":[{"name":"StdOutFilesystem","namespace":"Flow\\Filesystem\\Local","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":117,"slug":"memory-filesystem","name":"memory_filesystem","namespace":"Flow\\Filesystem\\DSL","parameters":[],"return_type":[{"name":"MemoryFilesystem","namespace":"Flow\\Filesystem\\Local","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":128,"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\\ETL\\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":144,"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\\ETL\\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":155,"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\\ETL\\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":170,"slug":"filesystem-telemetry-options","name":"filesystem_telemetry_options","namespace":"Flow\\Filesystem\\DSL","parameters":[{"name":"traceStreams","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"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"}],"return_type":[{"name":"FilesystemTelemetryOptions","namespace":"Flow\\Filesystem\\Telemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBvcHRpb25zIGZvciBmaWxlc3lzdGVtIHRlbGVtZXRyeS4KICoKICogQHBhcmFtIGJvb2wgJHRyYWNlU3RyZWFtcyBDcmVhdGUgYSBzaW5nbGUgc3BhbiBwZXIgc3RyZWFtIGxpZmVjeWNsZSAoZGVmYXVsdDogT04pCiAqIEBwYXJhbSBib29sICRjb2xsZWN0TWV0cmljcyBDb2xsZWN0IG1ldHJpY3MgZm9yIGJ5dGVzL29wZXJhdGlvbiBjb3VudHMgKGRlZmF1bHQ6IE9OKQogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":56,"slug":"type-structure","name":"type_structure","namespace":"Flow\\Types\\DSL","parameters":[{"name":"elements","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"optional_elements","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"},{"name":"allow_extra","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"false"}],"return_type":[{"name":"StructureType","namespace":"Flow\\Types\\Type\\Logical","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBhcnJheTxzdHJpbmcsIFR5cGU8VD4+ICRlbGVtZW50cwogKiBAcGFyYW0gYXJyYXk8c3RyaW5nLCBUeXBlPFQ+PiAkb3B0aW9uYWxfZWxlbWVudHMKICoKICogQHJldHVybiBTdHJ1Y3R1cmVUeXBlPFQ+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":73,"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":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqIEB0ZW1wbGF0ZSBUCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBUeXBlPFQ+ICRmaXJzdAogKiBAcGFyYW0gVHlwZTxUPiAkc2Vjb25kCiAqIEBwYXJhbSBUeXBlPFQ+IC4uLiR0eXBlcwogKgogKiBAcmV0dXJuIFR5cGU8VD4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":94,"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":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBUeXBlPFQ+ICRmaXJzdAogKiBAcGFyYW0gVHlwZTxUPiAkc2Vjb25kCiAqIEBwYXJhbSBUeXBlPFQ+IC4uLiR0eXBlcwogKgogKiBAcmV0dXJuIFR5cGU8VD4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":109,"slug":"type-numeric-string","name":"type_numeric_string","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxudW1lcmljLXN0cmluZz4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":122,"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":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBUeXBlPFQ+ICR0eXBlCiAqCiAqIEByZXR1cm4gVHlwZTxUPgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":133,"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\\ETL\\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":144,"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\\ETL\\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":166,"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\\ETL\\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":179,"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\\ETL\\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":192,"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\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBUeXBlPFQ+ICRlbGVtZW50CiAqCiAqIEByZXR1cm4gTGlzdFR5cGU8VD4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":207,"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\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUS2V5IG9mIGFycmF5LWtleQogKiBAdGVtcGxhdGUgVFZhbHVlCiAqCiAqIEBwYXJhbSBUeXBlPFRLZXk+ICRrZXlfdHlwZQogKiBAcGFyYW0gVHlwZTxUVmFsdWU+ICR2YWx1ZV90eXBlCiAqCiAqIEByZXR1cm4gTWFwVHlwZTxUS2V5LCBUVmFsdWU+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":216,"slug":"type-json","name":"type_json","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxKc29uPgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":225,"slug":"type-datetime","name":"type_datetime","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxcRGF0ZVRpbWVJbnRlcmZhY2U+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":234,"slug":"type-date","name":"type_date","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxcRGF0ZVRpbWVJbnRlcmZhY2U+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":243,"slug":"type-time","name":"type_time","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxcRGF0ZUludGVydmFsPgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":252,"slug":"type-time-zone","name":"type_time_zone","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxcRGF0ZVRpbWVab25lPgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":261,"slug":"type-xml","name":"type_xml","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxcRE9NRG9jdW1lbnQ+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":270,"slug":"type-xml-element","name":"type_xml_element","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxcRE9NRWxlbWVudD4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":279,"slug":"type-uuid","name":"type_uuid","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxVdWlkPgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":288,"slug":"type-integer","name":"type_integer","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxpbnQ+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":297,"slug":"type-string","name":"type_string","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxzdHJpbmc+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":306,"slug":"type-float","name":"type_float","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxmbG9hdD4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":315,"slug":"type-boolean","name":"type_boolean","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxib29sPgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":328,"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":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUIG9mIG9iamVjdAogKgogKiBAcGFyYW0gY2xhc3Mtc3RyaW5nPFQ+ICRjbGFzcwogKgogKiBAcmV0dXJuIFR5cGU8VD4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":337,"slug":"type-object","name":"type_object","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxvYmplY3Q+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":346,"slug":"type-scalar","name":"type_scalar","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxib29sfGZsb2F0fGludHxzdHJpbmc+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":355,"slug":"type-resource","name":"type_resource","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxyZXNvdXJjZT4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":364,"slug":"type-array","name":"type_array","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxhcnJheTxtaXhlZD4+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":373,"slug":"type-callable","name":"type_callable","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxjYWxsYWJsZT4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":382,"slug":"type-null","name":"type_null","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxudWxsPgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":391,"slug":"type-mixed","name":"type_mixed","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxtaXhlZD4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":400,"slug":"type-positive-integer","name":"type_positive_integer","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxpbnQ8MCwgbWF4Pj4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":409,"slug":"type-non-empty-string","name":"type_non_empty_string","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxub24tZW1wdHktc3RyaW5nPgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":422,"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":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUIG9mIFVuaXRFbnVtCiAqCiAqIEBwYXJhbSBjbGFzcy1zdHJpbmc8VD4gJGNsYXNzCiAqCiAqIEByZXR1cm4gVHlwZTxUPgogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":435,"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\\ETL\\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":444,"slug":"type-html","name":"type_html","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxIVE1MRG9jdW1lbnQ+CiAqLw=="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":453,"slug":"type-html-element","name":"type_html_element","namespace":"Flow\\Types\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEByZXR1cm4gVHlwZTxIVE1MRWxlbWVudD4KICov"},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":465,"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\\ETL\\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":478,"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\\ETL\\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":487,"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\\ETL\\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":500,"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":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TYPES","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUIG9mIG9iamVjdAogKgogKiBAcGFyYW0gbnVsbHxjbGFzcy1zdHJpbmc8VD4gJGNsYXNzCiAqCiAqIEByZXR1cm4gKCRjbGFzcyBpcyBudWxsID8gVHlwZTxjbGFzcy1zdHJpbmc+IDogVHlwZTxjbGFzcy1zdHJpbmc8VD4+KQogKi8="},{"repository_path":"src\/lib\/types\/src\/Flow\/Types\/DSL\/functions.php","start_line_in_file":506,"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\\ETL\\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":112,"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\\ETL\\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":123,"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\\ETL\\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":134,"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\\ETL\\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":147,"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\\ETL\\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":156,"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\\ETL\\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":187,"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\\ETL\\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":216,"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\\ETL\\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":250,"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\\ETL\\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":261,"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\\ETL\\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":279,"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\\ETL\\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":288,"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\\ETL\\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":297,"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\\ETL\\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":306,"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\\ETL\\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":315,"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\\ETL\\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":324,"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\\ETL\\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":339,"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\\ETL\\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":354,"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\\ETL\\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":369,"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\\ETL\\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":384,"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\\ETL\\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":399,"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\\ETL\\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":414,"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\\ETL\\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":423,"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\\ETL\\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":432,"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\\ETL\\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":441,"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\\ETL\\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":450,"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\\ETL\\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":459,"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\\ETL\\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":468,"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\\ETL\\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":480,"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\\ETL\\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":492,"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\\ETL\\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":506,"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\\ETL\\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":518,"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\\ETL\\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":533,"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\\ETL\\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":545,"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\\ETL\\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":559,"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\\ETL\\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":578,"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\\ETL\\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":597,"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\\ETL\\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":616,"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\\ETL\\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":635,"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\\ETL\\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":651,"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\\ETL\\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":665,"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\\ETL\\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":681,"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\\ETL\\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":700,"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\\ETL\\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":718,"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\\ETL\\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":737,"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\\ETL\\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":756,"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\\ETL\\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":776,"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\\ETL\\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":785,"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\\ETL\\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":794,"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\\ETL\\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":803,"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\\ETL\\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":812,"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\\ETL\\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":821,"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\\ETL\\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":830,"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\\ETL\\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":839,"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\\ETL\\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":848,"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\\ETL\\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":857,"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\\ETL\\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":866,"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\\ETL\\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":875,"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\\ETL\\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":884,"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\\ETL\\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":893,"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\\ETL\\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":902,"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\\ETL\\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":911,"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\\ETL\\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":920,"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\\ETL\\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":929,"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\\ETL\\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":938,"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\\ETL\\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":947,"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\\ETL\\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":956,"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\\ETL\\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":965,"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\\ETL\\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":974,"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\\ETL\\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":983,"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\\ETL\\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":992,"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\\ETL\\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":1001,"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\\ETL\\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":1010,"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\\ETL\\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":1019,"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\\ETL\\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":1031,"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\\ETL\\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":1044,"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\\ETL\\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":1052,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1058,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1064,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1070,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1076,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1082,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1088,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1094,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1100,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1106,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1112,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1118,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1124,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1130,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1136,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1142,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1148,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1154,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1160,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1166,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1172,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1178,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1184,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1190,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1196,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1202,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1208,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1214,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1220,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1226,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1232,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1238,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1244,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1250,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1256,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1262,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1268,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1274,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1280,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1286,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1292,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1298,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1304,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1310,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1316,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1322,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1328,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","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":"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\\ETL\\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":1370,"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\\ETL\\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":1391,"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":"string","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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1406,"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":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1412,"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":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1418,"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":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1424,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1430,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1436,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1442,"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":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1448,"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":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1454,"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":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1460,"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":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1466,"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":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1472,"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":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1478,"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":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1484,"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":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1490,"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":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1496,"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":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1502,"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":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1508,"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":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1514,"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":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1520,"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":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1526,"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":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1532,"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":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1538,"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":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1544,"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":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1550,"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":"string","namespace":null,"is_nullable":true,"is_variadic":false}],"has_default_value":true,"is_nullable":true,"is_variadic":false,"default_value":"null"}],"return_type":[{"name":"Column","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1559,"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\\ETL\\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":1569,"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\\ETL\\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":1587,"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\\ETL\\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":1593,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1599,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1608,"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\\ETL\\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":1620,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","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-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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1645,"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\\ETL\\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":1654,"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\\ETL\\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":1670,"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\\ETL\\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":1683,"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\\ETL\\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":1699,"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":"string","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\\ETL\\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":1710,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","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":"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":"excludeTables","type":[{"name":"array","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"[]"}],"return_type":[{"name":"CatalogProvider","namespace":"Flow\\PostgreSql\\Schema","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSA\/bGlzdDxzdHJpbmc+ICRzY2hlbWFOYW1lcwogKiBAcGFyYW0gbGlzdDxzdHJpbmc+ICRleGNsdWRlVGFibGVzCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1726,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1732,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","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":"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"}],"return_type":[{"name":"CatalogComparator","namespace":"Flow\\PostgreSql\\Schema\\Diff","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":1747,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1753,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1759,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1768,"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\\ETL\\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":1774,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":null},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/schema.php","start_line_in_file":1780,"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\\ETL\\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":97,"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\\ETL\\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":115,"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\\ETL\\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":127,"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\\ETL\\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":140,"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\\ETL\\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":156,"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\\ETL\\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":165,"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\\ETL\\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":174,"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\\ETL\\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":186,"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\\ETL\\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":200,"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\\ETL\\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":221,"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\\ETL\\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":250,"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\\ETL\\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":266,"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\\ETL\\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":281,"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\\ETL\\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":290,"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\\ETL\\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":316,"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\\ETL\\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":335,"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\\ETL\\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":352,"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\\ETL\\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":365,"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\\ETL\\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":374,"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\\ETL\\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":383,"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\\ETL\\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":392,"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\\ETL\\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":403,"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\\ETL\\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":415,"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\\ETL\\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":429,"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\\ETL\\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":443,"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\\ETL\\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":458,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHR5cGUgY2FzdCBleHByZXNzaW9uLgogKgogKiBAcGFyYW0gRXhwcmVzc2lvbiAkZXhwciBFeHByZXNzaW9uIHRvIGNhc3QKICogQHBhcmFtIENvbHVtblR5cGUgJGRhdGFUeXBlIFRhcmdldCBkYXRhIHR5cGUgKHVzZSBjb2x1bW5fdHlwZV8qIGZ1bmN0aW9ucykKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":473,"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\\ETL\\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":488,"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\\ETL\\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":503,"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\\ETL\\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":516,"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\\ETL\\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":529,"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\\ETL\\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":541,"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\\ETL\\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":555,"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\\ETL\\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":569,"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\\ETL\\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":581,"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\\ETL\\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":599,"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\\ETL\\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":624,"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\\ETL\\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":655,"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\\ETL\\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":670,"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\\ETL\\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":684,"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\\ETL\\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":696,"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\\ETL\\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":715,"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\\ETL\\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":724,"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\\ETL\\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":736,"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\\ETL\\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":745,"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\\ETL\\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":759,"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\\ETL\\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":781,"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\\ETL\\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":802,"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\\ETL\\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":815,"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\\ETL\\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":824,"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\\ETL\\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":833,"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\\ETL\\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":842,"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\\ETL\\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":851,"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\\ETL\\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":864,"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\\ETL\\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":878,"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\\ETL\\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":889,"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\\ETL\\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":898,"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\\ETL\\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":910,"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\\ETL\\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":924,"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\\ETL\\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":933,"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\\ETL\\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":944,"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\\ETL\\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":956,"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\\ETL\\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":968,"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\\ETL\\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":980,"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\\ETL\\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":992,"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\\ETL\\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":1004,"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\\ETL\\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":1016,"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\\ETL\\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":1028,"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\\ETL\\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":1040,"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\\ETL\\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":1052,"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\\ETL\\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":1064,"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\\ETL\\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":1076,"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\\ETL\\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":1088,"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\\ETL\\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":1111,"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":"string","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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIERlY2xhcmUgYSBzZXJ2ZXItc2lkZSBjdXJzb3IgZm9yIGEgcXVlcnkuCiAqCiAqIEN1cnNvcnMgbXVzdCBiZSBkZWNsYXJlZCB3aXRoaW4gYSB0cmFuc2FjdGlvbiBhbmQgcHJvdmlkZSBtZW1vcnktZWZmaWNpZW50CiAqIGl0ZXJhdGlvbiBvdmVyIGxhcmdlIHJlc3VsdCBzZXRzIHZpYSBGRVRDSCBjb21tYW5kcy4KICoKICogRXhhbXBsZSB3aXRoIHF1ZXJ5IGJ1aWxkZXI6CiAqICAgZGVjbGFyZV9jdXJzb3IoJ215X2N1cnNvcicsIHNlbGVjdChzdGFyKCkpLT5mcm9tKHRhYmxlKCd1c2VycycpKSktPm5vU2Nyb2xsKCkKICogICBQcm9kdWNlczogREVDTEFSRSBteV9jdXJzb3IgTk8gU0NST0xMIENVUlNPUiBGT1IgU0VMRUNUICogRlJPTSB1c2VycwogKgogKiBFeGFtcGxlIHdpdGggcmF3IFNRTDoKICogICBkZWNsYXJlX2N1cnNvcignbXlfY3Vyc29yJywgJ1NFTEVDVCAqIEZST00gdXNlcnMgV0hFUkUgYWN0aXZlID0gdHJ1ZScpLT53aXRoSG9sZCgpCiAqICAgUHJvZHVjZXM6IERFQ0xBUkUgbXlfY3Vyc29yIE5PIFNDUk9MTCBDVVJTT1IgV0lUSCBIT0xEIEZPUiBTRUxFQ1QgKiBGUk9NIHVzZXJzIFdIRVJFIGFjdGl2ZSA9IHRydWUKICoKICogQHBhcmFtIHN0cmluZyAkY3Vyc29yTmFtZSBVbmlxdWUgY3Vyc29yIG5hbWUKICogQHBhcmFtIFNlbGVjdEZpbmFsU3RlcHxTcWx8c3RyaW5nICRxdWVyeSBRdWVyeSB0byBpdGVyYXRlIG92ZXIKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/query.php","start_line_in_file":1132,"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\\ETL\\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":1149,"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\\ETL\\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":36,"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\\ETL\\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":49,"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\\ETL\\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":62,"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\\ETL\\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":75,"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\\ETL\\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":88,"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\\ETL\\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":101,"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\\ETL\\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":114,"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\\ETL\\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":131,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBJTiBjb25kaXRpb24uCiAqCiAqIEBwYXJhbSBFeHByZXNzaW9ufHN0cmluZyAkZXhwciBFeHByZXNzaW9uIHRvIGNoZWNrCiAqIEBwYXJhbSBsaXN0PEV4cHJlc3Npb24+ICR2YWx1ZXMgTGlzdCBvZiB2YWx1ZXMKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/condition.php","start_line_in_file":140,"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\\ETL\\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":149,"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\\ETL\\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":163,"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\\ETL\\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":175,"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\\ETL\\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":188,"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\\ETL\\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":203,"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\\ETL\\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":224,"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\\ETL\\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":244,"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\\ETL\\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":256,"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\\ETL\\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":284,"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\\ETL\\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":295,"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\\ETL\\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":306,"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\\ETL\\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":318,"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\\ETL\\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":330,"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\\ETL\\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":346,"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\\ETL\\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":363,"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\\ETL\\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":380,"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\\ETL\\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":397,"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\\ETL\\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":414,"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\\ETL\\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":430,"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\\ETL\\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":446,"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\\ETL\\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":462,"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\\ETL\\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":478,"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\\ETL\\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":494,"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\\ETL\\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":510,"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\\ETL\\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":528,"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\\ETL\\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":546,"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\\ETL\\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":564,"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\\ETL\\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":582,"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\\ETL\\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":598,"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\\ETL\\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":17,"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\\ETL\\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":23,"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\\ETL\\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":33,"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\\ETL\\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":44,"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\\ETL\\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":54,"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\\ETL\\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":65,"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\\ETL\\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":74,"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\\ETL\\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":88,"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\\ETL\\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":104,"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\\ETL\\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":114,"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\\ETL\\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":129,"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\\ETL\\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":146,"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\\ETL\\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":165,"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\\ETL\\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":187,"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\\ETL\\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":202,"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\\ETL\\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":211,"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\\ETL\\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":220,"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\\ETL\\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":229,"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\\ETL\\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":238,"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\\ETL\\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":252,"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\\ETL\\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":269,"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\\ETL\\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":289,"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\\ETL\\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":311,"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\\ETL\\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":324,"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\\ETL\\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":337,"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\\ETL\\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":32,"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\\ETL\\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":54,"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\\ETL\\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":81,"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\\ETL\\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":110,"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"}],"return_type":[{"name":"Client","namespace":"Flow\\PostgreSql\\Client","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBvc3RncmVTUUwgY2xpZW50IHVzaW5nIGV4dC1wZ3NxbC4KICoKICogVGhlIGNsaWVudCBjb25uZWN0cyBpbW1lZGlhdGVseSBhbmQgaXMgcmVhZHkgdG8gZXhlY3V0ZSBxdWVyaWVzLgogKgogKiBAcGFyYW0gQ2xpZW50XENvbm5lY3Rpb25QYXJhbWV0ZXJzICRwYXJhbXMgQ29ubmVjdGlvbiBwYXJhbWV0ZXJzCiAqIEBwYXJhbSBudWxsfFZhbHVlQ29udmVydGVycyAkdmFsdWVDb252ZXJ0ZXJzIEN1c3RvbSB0eXBlIGNvbnZlcnRlcnMgKG9wdGlvbmFsKQogKgogKiBAdGhyb3dzIENvbm5lY3Rpb25FeGNlcHRpb24gSWYgY29ubmVjdGlvbiBmYWlscwogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/client.php","start_line_in_file":145,"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":"traceTransactions","type":[{"name":"bool","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"true"},{"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSB0ZWxlbWV0cnkgb3B0aW9ucyBmb3IgUG9zdGdyZVNRTCBjbGllbnQgaW5zdHJ1bWVudGF0aW9uLgogKgogKiBDb250cm9scyB3aGljaCB0ZWxlbWV0cnkgc2lnbmFscyAodHJhY2VzLCBtZXRyaWNzLCBsb2dzKSBhcmUgZW5hYmxlZAogKiBhbmQgaG93IHF1ZXJ5IGluZm9ybWF0aW9uIGlzIGNhcHR1cmVkLgogKgogKiBAcGFyYW0gYm9vbCAkdHJhY2VRdWVyaWVzIENyZWF0ZSBzcGFucyBmb3IgcXVlcnkgZXhlY3V0aW9uIChkZWZhdWx0OiB0cnVlKQogKiBAcGFyYW0gYm9vbCAkdHJhY2VUcmFuc2FjdGlvbnMgQ3JlYXRlIHNwYW5zIGZvciB0cmFuc2FjdGlvbnMgKGRlZmF1bHQ6IHRydWUpCiAqIEBwYXJhbSBib29sICRjb2xsZWN0TWV0cmljcyBDb2xsZWN0IGR1cmF0aW9uIGFuZCByb3cgY291bnQgbWV0cmljcyAoZGVmYXVsdDogdHJ1ZSkKICogQHBhcmFtIGJvb2wgJGxvZ1F1ZXJpZXMgTG9nIGV4ZWN1dGVkIHF1ZXJpZXMgKGRlZmF1bHQ6IGZhbHNlKQogKiBAcGFyYW0gbnVsbHxpbnQgJG1heFF1ZXJ5TGVuZ3RoIE1heGltdW0gcXVlcnkgdGV4dCBsZW5ndGggaW4gdGVsZW1ldHJ5IChkZWZhdWx0OiAxMDAwLCBudWxsID0gdW5saW1pdGVkKQogKiBAcGFyYW0gYm9vbCAkaW5jbHVkZVBhcmFtZXRlcnMgSW5jbHVkZSBxdWVyeSBwYXJhbWV0ZXJzIGluIHRlbGVtZXRyeSAoZGVmYXVsdDogZmFsc2UsIHNlY3VyaXR5IGNvbnNpZGVyYXRpb24pCiAqCiAqIEBleGFtcGxlCiAqIC8vIERlZmF1bHQgb3B0aW9ucyAodHJhY2VzIGFuZCBtZXRyaWNzIGVuYWJsZWQpCiAqICRvcHRpb25zID0gcG9zdGdyZXNxbF90ZWxlbWV0cnlfb3B0aW9ucygpOwogKgogKiAvLyBFbmFibGUgcXVlcnkgbG9nZ2luZwogKiAkb3B0aW9ucyA9IHBvc3RncmVzcWxfdGVsZW1ldHJ5X29wdGlvbnMobG9nUXVlcmllczogdHJ1ZSk7CiAqCiAqIC8vIERpc2FibGUgYWxsIGJ1dCBtZXRyaWNzCiAqICRvcHRpb25zID0gcG9zdGdyZXNxbF90ZWxlbWV0cnlfb3B0aW9ucygKICogICAgIHRyYWNlUXVlcmllczogZmFsc2UsCiAqICAgICB0cmFjZVRyYW5zYWN0aW9uczogZmFsc2UsCiAqICAgICBjb2xsZWN0TWV0cmljczogdHJ1ZSwKICogKTsKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/client.php","start_line_in_file":183,"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\\ETL\\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":229,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFdyYXAgYSBQb3N0Z3JlU1FMIGNsaWVudCB3aXRoIHRlbGVtZXRyeSBpbnN0cnVtZW50YXRpb24uCiAqCiAqIFJldHVybnMgYSBkZWNvcmF0b3IgdGhhdCBhZGRzIHNwYW5zLCBtZXRyaWNzLCBhbmQgbG9ncyB0byBhbGwKICogcXVlcnkgYW5kIHRyYW5zYWN0aW9uIG9wZXJhdGlvbnMgZm9sbG93aW5nIE9wZW5UZWxlbWV0cnkgY29udmVudGlvbnMuCiAqCiAqIEBwYXJhbSBDbGllbnRcQ2xpZW50ICRjbGllbnQgVGhlIFBvc3RncmVTUUwgY2xpZW50IHRvIGluc3RydW1lbnQKICogQHBhcmFtIFBvc3RncmVTcWxUZWxlbWV0cnlDb25maWcgJHRlbGVtZXRyeUNvbmZpZyBUZWxlbWV0cnkgY29uZmlndXJhdGlvbgogKgogKiBAZXhhbXBsZQogKiAkY2xpZW50ID0gcGdzcWxfY2xpZW50KHBnc3FsX2Nvbm5lY3Rpb24oJ2hvc3Q9bG9jYWxob3N0IGRibmFtZT1teWRiJykpOwogKgogKiAkdHJhY2VhYmxlQ2xpZW50ID0gdHJhY2VhYmxlX3Bvc3RncmVzcWxfY2xpZW50KAogKiAgICAgJGNsaWVudCwKICogICAgIHBvc3RncmVzcWxfdGVsZW1ldHJ5X2NvbmZpZygKICogICAgICAgICB0ZWxlbWV0cnkocmVzb3VyY2UoWydzZXJ2aWNlLm5hbWUnID0+ICdteS1hcHAnXSkpLAogKiAgICAgICAgIG5ldyBTeXN0ZW1DbG9jaygpLAogKiAgICAgICAgIHBvc3RncmVzcWxfdGVsZW1ldHJ5X29wdGlvbnMoCiAqICAgICAgICAgICAgIHRyYWNlUXVlcmllczogdHJ1ZSwKICogICAgICAgICAgICAgdHJhY2VUcmFuc2FjdGlvbnM6IHRydWUsCiAqICAgICAgICAgICAgIGNvbGxlY3RNZXRyaWNzOiB0cnVlLAogKiAgICAgICAgICAgICBsb2dRdWVyaWVzOiB0cnVlLAogKiAgICAgICAgICAgICBtYXhRdWVyeUxlbmd0aDogNTAwLAogKiAgICAgICAgICksCiAqICAgICApLAogKiApOwogKgogKiAvLyBBbGwgb3BlcmF0aW9ucyBub3cgdHJhY2VkCiAqICR0cmFjZWFibGVDbGllbnQtPnRyYW5zYWN0aW9uKGZ1bmN0aW9uIChDbGllbnQgJGNsaWVudCkgewogKiAgICAgJHVzZXIgPSAkY2xpZW50LT5mZXRjaE9uZSgnU0VMRUNUICogRlJPTSB1c2VycyBXSEVSRSBpZCA9ICQxJywgWzEyM10pOwogKiAgICAgJGNsaWVudC0+ZXhlY3V0ZSgnVVBEQVRFIHVzZXJzIFNFVCBsYXN0X2xvZ2luID0gTk9XKCkgV0hFUkUgaWQgPSAkMScsIFsxMjNdKTsKICogfSk7CiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/client.php","start_line_in_file":271,"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\\ETL\\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":284,"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}],"return_type":[{"name":"TypeMapper","namespace":"Flow\\PostgreSql\\Client\\RowMapper","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBGbG93VHlwZTxUPiAkdHlwZQogKgogKiBAcmV0dXJuIFR5cGVNYXBwZXI8VD4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/client.php","start_line_in_file":313,"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\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFdyYXAgYSB2YWx1ZSB3aXRoIGV4cGxpY2l0IFBvc3RncmVTUUwgdHlwZSBpbmZvcm1hdGlvbiBmb3IgcGFyYW1ldGVyIGJpbmRpbmcuCiAqCiAqIFVzZSB3aGVuIGF1dG8tZGV0ZWN0aW9uIGlzbid0IHN1ZmZpY2llbnQgb3Igd2hlbiB5b3UgbmVlZCB0byBzcGVjaWZ5CiAqIHRoZSBleGFjdCBQb3N0Z3JlU1FMIHR5cGUgKHNpbmNlIG9uZSBQSFAgdHlwZSBjYW4gbWFwIHRvIG11bHRpcGxlIFBvc3RncmVTUUwgdHlwZXMpOgogKiAtIGludCBjb3VsZCBiZSBJTlQyLCBJTlQ0LCBvciBJTlQ4CiAqIC0gc3RyaW5nIGNvdWxkIGJlIFRFWFQsIFZBUkNIQVIsIG9yIENIQVIKICogLSBhcnJheSBtdXN0IGFsd2F5cyB1c2UgdHlwZWQoKSBzaW5jZSBhdXRvLWRldGVjdGlvbiBjYW5ub3QgZGV0ZXJtaW5lIGVsZW1lbnQgdHlwZQogKiAtIERhdGVUaW1lSW50ZXJmYWNlIGNvdWxkIGJlIFRJTUVTVEFNUCBvciBUSU1FU1RBTVBUWgogKiAtIEpzb24gY291bGQgYmUgSlNPTiBvciBKU09OQgogKgogKiBAcGFyYW0gbWl4ZWQgJHZhbHVlIFRoZSB2YWx1ZSB0byBiaW5kCiAqIEBwYXJhbSBWYWx1ZVR5cGUgJHRhcmdldFR5cGUgVGhlIFBvc3RncmVTUUwgdHlwZSB0byBjb252ZXJ0IHRoZSB2YWx1ZSB0bwogKgogKiBAZXhhbXBsZQogKiAkY2xpZW50LT5mZXRjaCgKICogICAgICdTRUxFQ1QgKiBGUk9NIHVzZXJzIFdIRVJFIGlkID0gJDEgQU5EIHRhZ3MgPSAkMicsCiAqICAgICBbCiAqICAgICAgICAgdHlwZWQoJzU1MGU4NDAwLWUyOWItNDFkNC1hNzE2LTQ0NjY1NTQ0MDAwMCcsIFZhbHVlVHlwZTo6VVVJRCksCiAqICAgICAgICAgdHlwZWQoWyd0YWcxJywgJ3RhZzInXSwgVmFsdWVUeXBlOjpURVhUX0FSUkFZKSwKICogICAgIF0KICogKTsKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":39,"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\\ETL\\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":59,"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\\ETL\\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":74,"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\\ETL\\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":89,"slug":"context","name":"context","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"traceId","type":[{"name":"TraceId","namespace":"Flow\\Telemetry\\Context","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":"Context","namespace":"Flow\\Telemetry\\Context","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENvbnRleHQuCiAqCiAqIElmIG5vIFRyYWNlSWQgaXMgcHJvdmlkZWQsIGdlbmVyYXRlcyBhIG5ldyBvbmUuCiAqIElmIG5vIEJhZ2dhZ2UgaXMgcHJvdmlkZWQsIGNyZWF0ZXMgYW4gZW1wdHkgb25lLgogKgogKiBAcGFyYW0gbnVsbHxUcmFjZUlkICR0cmFjZUlkIE9wdGlvbmFsIFRyYWNlSWQgdG8gdXNlCiAqIEBwYXJhbSBudWxsfEJhZ2dhZ2UgJGJhZ2dhZ2UgT3B0aW9uYWwgQmFnZ2FnZSB0byB1c2UKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":106,"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\\ETL\\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":117,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFJlc291cmNlLgogKgogKiBAcGFyYW0gYXJyYXk8c3RyaW5nLCBhcnJheTxib29sfGZsb2F0fGludHxzdHJpbmc+fGJvb2x8ZmxvYXR8aW50fHN0cmluZz58QXR0cmlidXRlcyAkYXR0cmlidXRlcyBSZXNvdXJjZSBhdHRyaWJ1dGVzCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":130,"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\\ETL\\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":143,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFNwYW5FdmVudCAoR2VuZXJpY0V2ZW50KSB3aXRoIGFuIGV4cGxpY2l0IHRpbWVzdGFtcC4KICoKICogQHBhcmFtIHN0cmluZyAkbmFtZSBFdmVudCBuYW1lCiAqIEBwYXJhbSBcRGF0ZVRpbWVJbW11dGFibGUgJHRpbWVzdGFtcCBFdmVudCB0aW1lc3RhbXAKICogQHBhcmFtIGFycmF5PHN0cmluZywgYXJyYXk8Ym9vbHxmbG9hdHxpbnR8c3RyaW5nPnxib29sfGZsb2F0fGludHxzdHJpbmc+fEF0dHJpYnV0ZXMgJGF0dHJpYnV0ZXMgRXZlbnQgYXR0cmlidXRlcwogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":155,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFNwYW5MaW5rLgogKgogKiBAcGFyYW0gU3BhbkNvbnRleHQgJGNvbnRleHQgVGhlIGxpbmtlZCBzcGFuIGNvbnRleHQKICogQHBhcmFtIGFycmF5PHN0cmluZywgYXJyYXk8Ym9vbHxmbG9hdHxpbnR8c3RyaW5nPnxib29sfGZsb2F0fGludHxzdHJpbmc+fEF0dHJpYnV0ZXMgJGF0dHJpYnV0ZXMgTGluayBhdHRyaWJ1dGVzCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":174,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBTcGFuTGltaXRzIGNvbmZpZ3VyYXRpb24uCiAqCiAqIFNwYW5MaW1pdHMgY29udHJvbHMgdGhlIG1heGltdW0gYW1vdW50IG9mIGRhdGEgYSBzcGFuIGNhbiBjb2xsZWN0LAogKiBwcmV2ZW50aW5nIHVuYm91bmRlZCBtZW1vcnkgZ3Jvd3RoIGFuZCBlbnN1cmluZyByZWFzb25hYmxlIHNwYW4gc2l6ZXMuCiAqCiAqIEBwYXJhbSBpbnQgJGF0dHJpYnV0ZUNvdW50TGltaXQgTWF4aW11bSBudW1iZXIgb2YgYXR0cmlidXRlcyBwZXIgc3BhbgogKiBAcGFyYW0gaW50ICRldmVudENvdW50TGltaXQgTWF4aW11bSBudW1iZXIgb2YgZXZlbnRzIHBlciBzcGFuCiAqIEBwYXJhbSBpbnQgJGxpbmtDb3VudExpbWl0IE1heGltdW0gbnVtYmVyIG9mIGxpbmtzIHBlciBzcGFuCiAqIEBwYXJhbSBpbnQgJGF0dHJpYnV0ZVBlckV2ZW50Q291bnRMaW1pdCBNYXhpbXVtIG51bWJlciBvZiBhdHRyaWJ1dGVzIHBlciBldmVudAogKiBAcGFyYW0gaW50ICRhdHRyaWJ1dGVQZXJMaW5rQ291bnRMaW1pdCBNYXhpbXVtIG51bWJlciBvZiBhdHRyaWJ1dGVzIHBlciBsaW5rCiAqIEBwYXJhbSBudWxsfGludCAkYXR0cmlidXRlVmFsdWVMZW5ndGhMaW1pdCBNYXhpbXVtIGxlbmd0aCBmb3Igc3RyaW5nIGF0dHJpYnV0ZSB2YWx1ZXMgKG51bGwgPSB1bmxpbWl0ZWQpCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":202,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBMb2dSZWNvcmRMaW1pdHMgY29uZmlndXJhdGlvbi4KICoKICogTG9nUmVjb3JkTGltaXRzIGNvbnRyb2xzIHRoZSBtYXhpbXVtIGFtb3VudCBvZiBkYXRhIGEgbG9nIHJlY29yZCBjYW4gY29sbGVjdCwKICogcHJldmVudGluZyB1bmJvdW5kZWQgbWVtb3J5IGdyb3d0aCBhbmQgZW5zdXJpbmcgcmVhc29uYWJsZSBsb2cgcmVjb3JkIHNpemVzLgogKgogKiBAcGFyYW0gaW50ICRhdHRyaWJ1dGVDb3VudExpbWl0IE1heGltdW0gbnVtYmVyIG9mIGF0dHJpYnV0ZXMgcGVyIGxvZyByZWNvcmQKICogQHBhcmFtIG51bGx8aW50ICRhdHRyaWJ1dGVWYWx1ZUxlbmd0aExpbWl0IE1heGltdW0gbGVuZ3RoIGZvciBzdHJpbmcgYXR0cmlidXRlIHZhbHVlcyAobnVsbCA9IHVubGltaXRlZCkKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":227,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBNZXRyaWNMaW1pdHMgY29uZmlndXJhdGlvbi4KICoKICogTWV0cmljTGltaXRzIGNvbnRyb2xzIHRoZSBtYXhpbXVtIGNhcmRpbmFsaXR5ICh1bmlxdWUgYXR0cmlidXRlIGNvbWJpbmF0aW9ucykKICogcGVyIG1ldHJpYyBpbnN0cnVtZW50LCBwcmV2ZW50aW5nIG1lbW9yeSBleGhhdXN0aW9uIGZyb20gaGlnaC1jYXJkaW5hbGl0eSBhdHRyaWJ1dGVzLgogKgogKiBXaGVuIHRoZSBjYXJkaW5hbGl0eSBsaW1pdCBpcyBleGNlZWRlZCwgbmV3IGF0dHJpYnV0ZSBjb21iaW5hdGlvbnMgYXJlIGFnZ3JlZ2F0ZWQKICogaW50byBhbiBvdmVyZmxvdyBkYXRhIHBvaW50IHdpdGggYG90ZWwubWV0cmljLm92ZXJmbG93OiB0cnVlYCBhdHRyaWJ1dGUuCiAqCiAqIE5vdGU6IFVubGlrZSBzcGFucyBhbmQgbG9ncywgbWV0cmljcyBhcmUgRVhFTVBUIGZyb20gYXR0cmlidXRlIGNvdW50IGFuZCB2YWx1ZQogKiBsZW5ndGggbGltaXRzIHBlciB0aGUgT3BlblRlbGVtZXRyeSBzcGVjaWZpY2F0aW9uLiBPbmx5IGNhcmRpbmFsaXR5IGlzIGxpbWl0ZWQuCiAqCiAqIEBwYXJhbSBpbnQgJGNhcmRpbmFsaXR5TGltaXQgTWF4aW11bSBudW1iZXIgb2YgdW5pcXVlIGF0dHJpYnV0ZSBjb21iaW5hdGlvbnMgcGVyIGluc3RydW1lbnQKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":242,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFZvaWRTcGFuUHJvY2Vzc29yLgogKgogKiBOby1vcCBzcGFuIHByb2Nlc3NvciB0aGF0IGRpc2NhcmRzIGFsbCBkYXRhLgogKiBVc2UgdGhpcyB3aGVuIHRyYWNpbmcgaXMgZGlzYWJsZWQgdG8gbWluaW1pemUgb3ZlcmhlYWQuCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":254,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFZvaWRNZXRyaWNQcm9jZXNzb3IuCiAqCiAqIE5vLW9wIG1ldHJpYyBwcm9jZXNzb3IgdGhhdCBkaXNjYXJkcyBhbGwgZGF0YS4KICogVXNlIHRoaXMgd2hlbiBtZXRyaWNzIGNvbGxlY3Rpb24gaXMgZGlzYWJsZWQgdG8gbWluaW1pemUgb3ZlcmhlYWQuCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":266,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFZvaWRMb2dQcm9jZXNzb3IuCiAqCiAqIE5vLW9wIGxvZyBwcm9jZXNzb3IgdGhhdCBkaXNjYXJkcyBhbGwgZGF0YS4KICogVXNlIHRoaXMgd2hlbiBsb2dnaW5nIGlzIGRpc2FibGVkIHRvIG1pbmltaXplIG92ZXJoZWFkLgogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":278,"slug":"void-span-exporter","name":"void_span_exporter","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"VoidSpanExporter","namespace":"Flow\\Telemetry\\Provider\\Void","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFZvaWRTcGFuRXhwb3J0ZXIuCiAqCiAqIE5vLW9wIHNwYW4gZXhwb3J0ZXIgdGhhdCBkaXNjYXJkcyBhbGwgZGF0YS4KICogVXNlIHRoaXMgd2hlbiB0ZWxlbWV0cnkgZXhwb3J0IGlzIGRpc2FibGVkIHRvIG1pbmltaXplIG92ZXJoZWFkLgogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":290,"slug":"void-metric-exporter","name":"void_metric_exporter","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"VoidMetricExporter","namespace":"Flow\\Telemetry\\Provider\\Void","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFZvaWRNZXRyaWNFeHBvcnRlci4KICoKICogTm8tb3AgbWV0cmljIGV4cG9ydGVyIHRoYXQgZGlzY2FyZHMgYWxsIGRhdGEuCiAqIFVzZSB0aGlzIHdoZW4gdGVsZW1ldHJ5IGV4cG9ydCBpcyBkaXNhYmxlZCB0byBtaW5pbWl6ZSBvdmVyaGVhZC4KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":302,"slug":"void-log-exporter","name":"void_log_exporter","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"VoidLogExporter","namespace":"Flow\\Telemetry\\Provider\\Void","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFZvaWRMb2dFeHBvcnRlci4KICoKICogTm8tb3AgbG9nIGV4cG9ydGVyIHRoYXQgZGlzY2FyZHMgYWxsIGRhdGEuCiAqIFVzZSB0aGlzIHdoZW4gdGVsZW1ldHJ5IGV4cG9ydCBpcyBkaXNhYmxlZCB0byBtaW5pbWl6ZSBvdmVyaGVhZC4KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":315,"slug":"memory-span-exporter","name":"memory_span_exporter","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"MemorySpanExporter","namespace":"Flow\\Telemetry\\Provider\\Memory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIE1lbW9yeVNwYW5FeHBvcnRlci4KICoKICogU3BhbiBleHBvcnRlciB0aGF0IHN0b3JlcyBkYXRhIGluIG1lbW9yeS4KICogUHJvdmlkZXMgZGlyZWN0IGdldHRlciBhY2Nlc3MgdG8gZXhwb3J0ZWQgc3BhbnMuCiAqIFVzZWZ1bCBmb3IgdGVzdGluZyBhbmQgaW5zcGVjdGlvbiB3aXRob3V0IHNlcmlhbGl6YXRpb24uCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":328,"slug":"memory-metric-exporter","name":"memory_metric_exporter","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"MemoryMetricExporter","namespace":"Flow\\Telemetry\\Provider\\Memory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIE1lbW9yeU1ldHJpY0V4cG9ydGVyLgogKgogKiBNZXRyaWMgZXhwb3J0ZXIgdGhhdCBzdG9yZXMgZGF0YSBpbiBtZW1vcnkuCiAqIFByb3ZpZGVzIGRpcmVjdCBnZXR0ZXIgYWNjZXNzIHRvIGV4cG9ydGVkIG1ldHJpY3MuCiAqIFVzZWZ1bCBmb3IgdGVzdGluZyBhbmQgaW5zcGVjdGlvbiB3aXRob3V0IHNlcmlhbGl6YXRpb24uCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":341,"slug":"memory-log-exporter","name":"memory_log_exporter","namespace":"Flow\\Telemetry\\DSL","parameters":[],"return_type":[{"name":"MemoryLogExporter","namespace":"Flow\\Telemetry\\Provider\\Memory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIE1lbW9yeUxvZ0V4cG9ydGVyLgogKgogKiBMb2cgZXhwb3J0ZXIgdGhhdCBzdG9yZXMgZGF0YSBpbiBtZW1vcnkuCiAqIFByb3ZpZGVzIGRpcmVjdCBnZXR0ZXIgYWNjZXNzIHRvIGV4cG9ydGVkIGxvZyBlbnRyaWVzLgogKiBVc2VmdWwgZm9yIHRlc3RpbmcgYW5kIGluc3BlY3Rpb24gd2l0aG91dCBzZXJpYWxpemF0aW9uLgogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":355,"slug":"memory-span-processor","name":"memory_span_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"exporter","type":[{"name":"SpanExporter","namespace":"Flow\\Telemetry\\Tracer","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"MemorySpanProcessor","namespace":"Flow\\Telemetry\\Provider\\Memory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIE1lbW9yeVNwYW5Qcm9jZXNzb3IuCiAqCiAqIFNwYW4gcHJvY2Vzc29yIHRoYXQgc3RvcmVzIHNwYW5zIGluIG1lbW9yeSBhbmQgZXhwb3J0cyB2aWEgY29uZmlndXJlZCBleHBvcnRlci4KICogVXNlZnVsIGZvciB0ZXN0aW5nLgogKgogKiBAcGFyYW0gU3BhbkV4cG9ydGVyICRleHBvcnRlciBUaGUgZXhwb3J0ZXIgdG8gc2VuZCBzcGFucyB0bwogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":369,"slug":"memory-metric-processor","name":"memory_metric_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"exporter","type":[{"name":"MetricExporter","namespace":"Flow\\Telemetry\\Meter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"MemoryMetricProcessor","namespace":"Flow\\Telemetry\\Provider\\Memory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIE1lbW9yeU1ldHJpY1Byb2Nlc3Nvci4KICoKICogTWV0cmljIHByb2Nlc3NvciB0aGF0IHN0b3JlcyBtZXRyaWNzIGluIG1lbW9yeSBhbmQgZXhwb3J0cyB2aWEgY29uZmlndXJlZCBleHBvcnRlci4KICogVXNlZnVsIGZvciB0ZXN0aW5nLgogKgogKiBAcGFyYW0gTWV0cmljRXhwb3J0ZXIgJGV4cG9ydGVyIFRoZSBleHBvcnRlciB0byBzZW5kIG1ldHJpY3MgdG8KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":383,"slug":"memory-log-processor","name":"memory_log_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"exporter","type":[{"name":"LogExporter","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":"MemoryLogProcessor","namespace":"Flow\\Telemetry\\Provider\\Memory","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIE1lbW9yeUxvZ1Byb2Nlc3Nvci4KICoKICogTG9nIHByb2Nlc3NvciB0aGF0IHN0b3JlcyBsb2cgcmVjb3JkcyBpbiBtZW1vcnkgYW5kIGV4cG9ydHMgdmlhIGNvbmZpZ3VyZWQgZXhwb3J0ZXIuCiAqIFVzZWZ1bCBmb3IgdGVzdGluZy4KICoKICogQHBhcmFtIExvZ0V4cG9ydGVyICRleHBvcnRlciBUaGUgZXhwb3J0ZXIgdG8gc2VuZCBsb2dzIHRvCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":402,"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\\AlwaysOnSampler::..."},{"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::..."}],"return_type":[{"name":"TracerProvider","namespace":"Flow\\Telemetry\\Tracer","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFRyYWNlclByb3ZpZGVyLgogKgogKiBDcmVhdGVzIGEgcHJvdmlkZXIgdGhhdCB1c2VzIGEgU3BhblByb2Nlc3NvciBmb3IgcHJvY2Vzc2luZyBzcGFucy4KICogRm9yIHZvaWQvZGlzYWJsZWQgdHJhY2luZywgcGFzcyB2b2lkX3Byb2Nlc3NvcigpLgogKiBGb3IgbWVtb3J5LWJhc2VkIHRlc3RpbmcsIHBhc3MgbWVtb3J5X3Byb2Nlc3NvcigpIHdpdGggZXhwb3J0ZXJzLgogKgogKiBAcGFyYW0gU3BhblByb2Nlc3NvciAkcHJvY2Vzc29yIFRoZSBwcm9jZXNzb3IgZm9yIHNwYW5zCiAqIEBwYXJhbSBDbG9ja0ludGVyZmFjZSAkY2xvY2sgVGhlIGNsb2NrIGZvciB0aW1lc3RhbXBzCiAqIEBwYXJhbSBDb250ZXh0U3RvcmFnZSAkY29udGV4dFN0b3JhZ2UgU3RvcmFnZSBmb3IgY29udGV4dCBwcm9wYWdhdGlvbgogKiBAcGFyYW0gU2FtcGxlciAkc2FtcGxlciBTYW1wbGluZyBzdHJhdGVneSBmb3Igc3BhbnMKICogQHBhcmFtIFNwYW5MaW1pdHMgJGxpbWl0cyBMaW1pdHMgZm9yIHNwYW4gYXR0cmlidXRlcywgZXZlbnRzLCBhbmQgbGlua3MKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":431,"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::..."}],"return_type":[{"name":"LoggerProvider","namespace":"Flow\\Telemetry\\Logger","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIExvZ2dlclByb3ZpZGVyLgogKgogKiBDcmVhdGVzIGEgcHJvdmlkZXIgdGhhdCB1c2VzIGEgTG9nUHJvY2Vzc29yIGZvciBwcm9jZXNzaW5nIGxvZ3MuCiAqIEZvciB2b2lkL2Rpc2FibGVkIGxvZ2dpbmcsIHBhc3Mgdm9pZF9wcm9jZXNzb3IoKS4KICogRm9yIG1lbW9yeS1iYXNlZCB0ZXN0aW5nLCBwYXNzIG1lbW9yeV9wcm9jZXNzb3IoKSB3aXRoIGV4cG9ydGVycy4KICoKICogQHBhcmFtIExvZ1Byb2Nlc3NvciAkcHJvY2Vzc29yIFRoZSBwcm9jZXNzb3IgZm9yIGxvZ3MKICogQHBhcmFtIENsb2NrSW50ZXJmYWNlICRjbG9jayBUaGUgY2xvY2sgZm9yIHRpbWVzdGFtcHMKICogQHBhcmFtIENvbnRleHRTdG9yYWdlICRjb250ZXh0U3RvcmFnZSBTdG9yYWdlIGZvciBzcGFuIGNvcnJlbGF0aW9uCiAqIEBwYXJhbSBMb2dSZWNvcmRMaW1pdHMgJGxpbWl0cyBMaW1pdHMgZm9yIGxvZyByZWNvcmQgYXR0cmlidXRlcwogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":459,"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::..."}],"return_type":[{"name":"MeterProvider","namespace":"Flow\\Telemetry\\Meter","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIE1ldGVyUHJvdmlkZXIuCiAqCiAqIENyZWF0ZXMgYSBwcm92aWRlciB0aGF0IHVzZXMgYSBNZXRyaWNQcm9jZXNzb3IgZm9yIHByb2Nlc3NpbmcgbWV0cmljcy4KICogRm9yIHZvaWQvZGlzYWJsZWQgbWV0cmljcywgcGFzcyB2b2lkX3Byb2Nlc3NvcigpLgogKiBGb3IgbWVtb3J5LWJhc2VkIHRlc3RpbmcsIHBhc3MgbWVtb3J5X3Byb2Nlc3NvcigpIHdpdGggZXhwb3J0ZXJzLgogKgogKiBAcGFyYW0gTWV0cmljUHJvY2Vzc29yICRwcm9jZXNzb3IgVGhlIHByb2Nlc3NvciBmb3IgbWV0cmljcwogKiBAcGFyYW0gQ2xvY2tJbnRlcmZhY2UgJGNsb2NrIFRoZSBjbG9jayBmb3IgdGltZXN0YW1wcwogKiBAcGFyYW0gQWdncmVnYXRpb25UZW1wb3JhbGl0eSAkdGVtcG9yYWxpdHkgQWdncmVnYXRpb24gdGVtcG9yYWxpdHkgZm9yIG1ldHJpY3MKICogQHBhcmFtIEV4ZW1wbGFyRmlsdGVyICRleGVtcGxhckZpbHRlciBGaWx0ZXIgZm9yIGV4ZW1wbGFyIHNhbXBsaW5nIChkZWZhdWx0OiBUcmFjZUJhc2VkRXhlbXBsYXJGaWx0ZXIpCiAqIEBwYXJhbSBNZXRyaWNMaW1pdHMgJGxpbWl0cyBDYXJkaW5hbGl0eSBsaW1pdHMgZm9yIG1ldHJpYyBpbnN0cnVtZW50cwogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":486,"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"}],"return_type":[{"name":"Telemetry","namespace":"Flow\\Telemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIG5ldyBUZWxlbWV0cnkgaW5zdGFuY2Ugd2l0aCB0aGUgZ2l2ZW4gcHJvdmlkZXJzLgogKgogKiBJZiBwcm92aWRlcnMgYXJlIG5vdCBzcGVjaWZpZWQsIHZvaWQgcHJvdmlkZXJzIChuby1vcCkgYXJlIHVzZWQuCiAqCiAqIEBwYXJhbSByZXNvdXJjZSAkcmVzb3VyY2UgVGhlIHJlc291cmNlIGRlc2NyaWJpbmcgdGhlIGVudGl0eSBwcm9kdWNpbmcgdGVsZW1ldHJ5CiAqIEBwYXJhbSBudWxsfFRyYWNlclByb3ZpZGVyICR0cmFjZXJQcm92aWRlciBUaGUgdHJhY2VyIHByb3ZpZGVyIChudWxsIGZvciB2b2lkL2Rpc2FibGVkKQogKiBAcGFyYW0gbnVsbHxNZXRlclByb3ZpZGVyICRtZXRlclByb3ZpZGVyIFRoZSBtZXRlciBwcm92aWRlciAobnVsbCBmb3Igdm9pZC9kaXNhYmxlZCkKICogQHBhcmFtIG51bGx8TG9nZ2VyUHJvdmlkZXIgJGxvZ2dlclByb3ZpZGVyIFRoZSBsb2dnZXIgcHJvdmlkZXIgKG51bGwgZm9yIHZvaWQvZGlzYWJsZWQpCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":511,"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\\ETL\\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":530,"slug":"batching-span-processor","name":"batching_span_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"exporter","type":[{"name":"SpanExporter","namespace":"Flow\\Telemetry\\Tracer","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"}],"return_type":[{"name":"BatchingSpanProcessor","namespace":"Flow\\Telemetry\\Tracer\\Processor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEJhdGNoaW5nU3BhblByb2Nlc3Nvci4KICoKICogQ29sbGVjdHMgc3BhbnMgaW4gbWVtb3J5IGFuZCBleHBvcnRzIHRoZW0gaW4gYmF0Y2hlcyBmb3IgZWZmaWNpZW5jeS4KICogU3BhbnMgYXJlIGV4cG9ydGVkIHdoZW4gYmF0Y2ggc2l6ZSBpcyByZWFjaGVkLCBmbHVzaCgpIGlzIGNhbGxlZCwgb3Igc2h1dGRvd24oKS4KICoKICogQHBhcmFtIFNwYW5FeHBvcnRlciAkZXhwb3J0ZXIgVGhlIGV4cG9ydGVyIHRvIHNlbmQgc3BhbnMgdG8KICogQHBhcmFtIGludCAkYmF0Y2hTaXplIE51bWJlciBvZiBzcGFucyB0byBjb2xsZWN0IGJlZm9yZSBleHBvcnRpbmcgKGRlZmF1bHQgNTEyKQogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":544,"slug":"pass-through-span-processor","name":"pass_through_span_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"exporter","type":[{"name":"SpanExporter","namespace":"Flow\\Telemetry\\Tracer","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"PassThroughSpanProcessor","namespace":"Flow\\Telemetry\\Tracer\\Processor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBhc3NUaHJvdWdoU3BhblByb2Nlc3Nvci4KICoKICogRXhwb3J0cyBlYWNoIHNwYW4gaW1tZWRpYXRlbHkgd2hlbiBpdCBlbmRzLgogKiBVc2VmdWwgZm9yIGRlYnVnZ2luZyB3aGVyZSBpbW1lZGlhdGUgdmlzaWJpbGl0eSBpcyBtb3JlIGltcG9ydGFudCB0aGFuIHBlcmZvcm1hbmNlLgogKgogKiBAcGFyYW0gU3BhbkV4cG9ydGVyICRleHBvcnRlciBUaGUgZXhwb3J0ZXIgdG8gc2VuZCBzcGFucyB0bwogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":559,"slug":"batching-metric-processor","name":"batching_metric_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"exporter","type":[{"name":"MetricExporter","namespace":"Flow\\Telemetry\\Meter","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"}],"return_type":[{"name":"BatchingMetricProcessor","namespace":"Flow\\Telemetry\\Meter\\Processor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEJhdGNoaW5nTWV0cmljUHJvY2Vzc29yLgogKgogKiBDb2xsZWN0cyBtZXRyaWNzIGluIG1lbW9yeSBhbmQgZXhwb3J0cyB0aGVtIGluIGJhdGNoZXMgZm9yIGVmZmljaWVuY3kuCiAqIE1ldHJpY3MgYXJlIGV4cG9ydGVkIHdoZW4gYmF0Y2ggc2l6ZSBpcyByZWFjaGVkLCBmbHVzaCgpIGlzIGNhbGxlZCwgb3Igc2h1dGRvd24oKS4KICoKICogQHBhcmFtIE1ldHJpY0V4cG9ydGVyICRleHBvcnRlciBUaGUgZXhwb3J0ZXIgdG8gc2VuZCBtZXRyaWNzIHRvCiAqIEBwYXJhbSBpbnQgJGJhdGNoU2l6ZSBOdW1iZXIgb2YgbWV0cmljcyB0byBjb2xsZWN0IGJlZm9yZSBleHBvcnRpbmcgKGRlZmF1bHQgNTEyKQogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":573,"slug":"pass-through-metric-processor","name":"pass_through_metric_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"exporter","type":[{"name":"MetricExporter","namespace":"Flow\\Telemetry\\Meter","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"PassThroughMetricProcessor","namespace":"Flow\\Telemetry\\Meter\\Processor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBhc3NUaHJvdWdoTWV0cmljUHJvY2Vzc29yLgogKgogKiBFeHBvcnRzIGVhY2ggbWV0cmljIGltbWVkaWF0ZWx5IHdoZW4gcHJvY2Vzc2VkLgogKiBVc2VmdWwgZm9yIGRlYnVnZ2luZyB3aGVyZSBpbW1lZGlhdGUgdmlzaWJpbGl0eSBpcyBtb3JlIGltcG9ydGFudCB0aGFuIHBlcmZvcm1hbmNlLgogKgogKiBAcGFyYW0gTWV0cmljRXhwb3J0ZXIgJGV4cG9ydGVyIFRoZSBleHBvcnRlciB0byBzZW5kIG1ldHJpY3MgdG8KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":588,"slug":"batching-log-processor","name":"batching_log_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"exporter","type":[{"name":"LogExporter","namespace":"Flow\\Telemetry\\Logger","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"}],"return_type":[{"name":"BatchingLogProcessor","namespace":"Flow\\Telemetry\\Logger\\Processor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEJhdGNoaW5nTG9nUHJvY2Vzc29yLgogKgogKiBDb2xsZWN0cyBsb2cgcmVjb3JkcyBpbiBtZW1vcnkgYW5kIGV4cG9ydHMgdGhlbSBpbiBiYXRjaGVzIGZvciBlZmZpY2llbmN5LgogKiBMb2dzIGFyZSBleHBvcnRlZCB3aGVuIGJhdGNoIHNpemUgaXMgcmVhY2hlZCwgZmx1c2goKSBpcyBjYWxsZWQsIG9yIHNodXRkb3duKCkuCiAqCiAqIEBwYXJhbSBMb2dFeHBvcnRlciAkZXhwb3J0ZXIgVGhlIGV4cG9ydGVyIHRvIHNlbmQgbG9ncyB0bwogKiBAcGFyYW0gaW50ICRiYXRjaFNpemUgTnVtYmVyIG9mIGxvZ3MgdG8gY29sbGVjdCBiZWZvcmUgZXhwb3J0aW5nIChkZWZhdWx0IDUxMikKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":602,"slug":"pass-through-log-processor","name":"pass_through_log_processor","namespace":"Flow\\Telemetry\\DSL","parameters":[{"name":"exporter","type":[{"name":"LogExporter","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":"PassThroughLogProcessor","namespace":"Flow\\Telemetry\\Logger\\Processor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFBhc3NUaHJvdWdoTG9nUHJvY2Vzc29yLgogKgogKiBFeHBvcnRzIGVhY2ggbG9nIHJlY29yZCBpbW1lZGlhdGVseSB3aGVuIHByb2Nlc3NlZC4KICogVXNlZnVsIGZvciBkZWJ1Z2dpbmcgd2hlcmUgaW1tZWRpYXRlIHZpc2liaWxpdHkgaXMgbW9yZSBpbXBvcnRhbnQgdGhhbiBwZXJmb3JtYW5jZS4KICoKICogQHBhcmFtIExvZ0V4cG9ydGVyICRleHBvcnRlciBUaGUgZXhwb3J0ZXIgdG8gc2VuZCBsb2dzIHRvCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":617,"slug":"severity-filtering-log-processor","name":"severity_filtering_log_processor","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":"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":"SeverityFilteringLogProcessor","namespace":"Flow\\Telemetry\\Logger\\Processor","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFNldmVyaXR5RmlsdGVyaW5nTG9nUHJvY2Vzc29yLgogKgogKiBGaWx0ZXJzIGxvZyBlbnRyaWVzIGJhc2VkIG9uIG1pbmltdW0gc2V2ZXJpdHkgbGV2ZWwuIE9ubHkgZW50cmllcyBhdCBvciBhYm92ZQogKiB0aGUgY29uZmlndXJlZCB0aHJlc2hvbGQgYXJlIHBhc3NlZCB0byB0aGUgd3JhcHBlZCBwcm9jZXNzb3IuCiAqCiAqIEBwYXJhbSBMb2dQcm9jZXNzb3IgJHByb2Nlc3NvciBUaGUgcHJvY2Vzc29yIHRvIHdyYXAKICogQHBhcmFtIFNldmVyaXR5ICRtaW5pbXVtU2V2ZXJpdHkgTWluaW11bSBzZXZlcml0eSBsZXZlbCAoZGVmYXVsdDogSU5GTykKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":634,"slug":"console-span-exporter","name":"console_span_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":"options","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":"ConsoleSpanExporter","namespace":"Flow\\Telemetry\\Provider\\Console","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENvbnNvbGVTcGFuRXhwb3J0ZXIuCiAqCiAqIE91dHB1dHMgc3BhbnMgdG8gdGhlIGNvbnNvbGUgd2l0aCBBU0NJSSB0YWJsZSBmb3JtYXR0aW5nLgogKiBVc2VmdWwgZm9yIGRlYnVnZ2luZyBhbmQgZGV2ZWxvcG1lbnQuCiAqCiAqIEBwYXJhbSBib29sICRjb2xvcnMgV2hldGhlciB0byB1c2UgQU5TSSBjb2xvcnMgKGRlZmF1bHQ6IHRydWUpCiAqIEBwYXJhbSBDb25zb2xlU3Bhbk9wdGlvbnMgJG9wdGlvbnMgRGlzcGxheSBvcHRpb25zIGZvciB0aGUgZXhwb3J0ZXIKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":649,"slug":"console-metric-exporter","name":"console_metric_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":"options","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::..."}],"return_type":[{"name":"ConsoleMetricExporter","namespace":"Flow\\Telemetry\\Provider\\Console","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENvbnNvbGVNZXRyaWNFeHBvcnRlci4KICoKICogT3V0cHV0cyBtZXRyaWNzIHRvIHRoZSBjb25zb2xlIHdpdGggQVNDSUkgdGFibGUgZm9ybWF0dGluZy4KICogVXNlZnVsIGZvciBkZWJ1Z2dpbmcgYW5kIGRldmVsb3BtZW50LgogKgogKiBAcGFyYW0gYm9vbCAkY29sb3JzIFdoZXRoZXIgdG8gdXNlIEFOU0kgY29sb3JzIChkZWZhdWx0OiB0cnVlKQogKiBAcGFyYW0gQ29uc29sZU1ldHJpY09wdGlvbnMgJG9wdGlvbnMgRGlzcGxheSBvcHRpb25zIGZvciB0aGUgZXhwb3J0ZXIKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":665,"slug":"console-log-exporter","name":"console_log_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":"maxBodyLength","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":"options","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::..."}],"return_type":[{"name":"ConsoleLogExporter","namespace":"Flow\\Telemetry\\Provider\\Console","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENvbnNvbGVMb2dFeHBvcnRlci4KICoKICogT3V0cHV0cyBsb2cgcmVjb3JkcyB0byB0aGUgY29uc29sZSB3aXRoIHNldmVyaXR5LWJhc2VkIGNvbG9yaW5nLgogKiBVc2VmdWwgZm9yIGRlYnVnZ2luZyBhbmQgZGV2ZWxvcG1lbnQuCiAqCiAqIEBwYXJhbSBib29sICRjb2xvcnMgV2hldGhlciB0byB1c2UgQU5TSSBjb2xvcnMgKGRlZmF1bHQ6IHRydWUpCiAqIEBwYXJhbSBudWxsfGludCAkbWF4Qm9keUxlbmd0aCBNYXhpbXVtIGxlbmd0aCBmb3IgYm9keSthdHRyaWJ1dGVzIGNvbHVtbiAobnVsbCA9IG5vIGxpbWl0LCBkZWZhdWx0OiAxMDApCiAqIEBwYXJhbSBDb25zb2xlTG9nT3B0aW9ucyAkb3B0aW9ucyBEaXNwbGF5IG9wdGlvbnMgZm9yIHRoZSBleHBvcnRlcgogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":674,"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\\ETL\\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":683,"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\\ETL\\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":692,"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\\ETL\\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":701,"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\\ETL\\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":710,"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\\ETL\\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":719,"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\\ETL\\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":731,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBBbHdheXNPbkV4ZW1wbGFyRmlsdGVyLgogKgogKiBSZWNvcmRzIGV4ZW1wbGFycyB3aGVuZXZlciBhIHNwYW4gY29udGV4dCBpcyBwcmVzZW50LgogKiBVc2UgdGhpcyBmaWx0ZXIgZm9yIGRlYnVnZ2luZyBvciB3aGVuIGNvbXBsZXRlIHRyYWNlIGNvbnRleHQgaXMgaW1wb3J0YW50LgogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":743,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBBbHdheXNPZmZFeGVtcGxhckZpbHRlci4KICoKICogTmV2ZXIgcmVjb3JkcyBleGVtcGxhcnMuIFVzZSB0aGlzIGZpbHRlciB0byBkaXNhYmxlIGV4ZW1wbGFyIGNvbGxlY3Rpb24KICogZW50aXJlbHkgZm9yIHBlcmZvcm1hbmNlIG9wdGltaXphdGlvbi4KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":755,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFRyYWNlQmFzZWRFeGVtcGxhckZpbHRlci4KICoKICogUmVjb3JkcyBleGVtcGxhcnMgb25seSB3aGVuIHRoZSBzcGFuIGlzIHNhbXBsZWQgKGhhcyBTQU1QTEVEIHRyYWNlIGZsYWcpLgogKiBUaGlzIGlzIHRoZSBkZWZhdWx0IGZpbHRlciwgYmFsYW5jaW5nIGV4ZW1wbGFyIGNvbGxlY3Rpb24gd2l0aCBwZXJmb3JtYW5jZS4KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":770,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFByb3BhZ2F0aW9uQ29udGV4dC4KICoKICogVmFsdWUgb2JqZWN0IGNvbnRhaW5pbmcgYm90aCB0cmFjZSBjb250ZXh0IChTcGFuQ29udGV4dCkgYW5kIGFwcGxpY2F0aW9uCiAqIGRhdGEgKEJhZ2dhZ2UpIHRoYXQgY2FuIGJlIHByb3BhZ2F0ZWQgYWNyb3NzIHByb2Nlc3MgYm91bmRhcmllcy4KICoKICogQHBhcmFtIG51bGx8U3BhbkNvbnRleHQgJHNwYW5Db250ZXh0IE9wdGlvbmFsIHNwYW4gY29udGV4dAogKiBAcGFyYW0gbnVsbHxCYWdnYWdlICRiYWdnYWdlIE9wdGlvbmFsIGJhZ2dhZ2UKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":783,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBBcnJheUNhcnJpZXIuCiAqCiAqIENhcnJpZXIgYmFja2VkIGJ5IGFuIGFzc29jaWF0aXZlIGFycmF5IHdpdGggY2FzZS1pbnNlbnNpdGl2ZSBrZXkgbG9va3VwLgogKgogKiBAcGFyYW0gYXJyYXk8c3RyaW5nLCBzdHJpbmc+ICRkYXRhIEluaXRpYWwgY2FycmllciBkYXRhCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":795,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFN1cGVyZ2xvYmFsQ2Fycmllci4KICoKICogUmVhZC1vbmx5IGNhcnJpZXIgdGhhdCBleHRyYWN0cyBjb250ZXh0IGZyb20gUEhQIHN1cGVyZ2xvYmFscwogKiAoJF9TRVJWRVIsICRfR0VULCAkX1BPU1QsICRfQ09PS0lFKS4KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":807,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFczQ1RyYWNlQ29udGV4dCBwcm9wYWdhdG9yLgogKgogKiBJbXBsZW1lbnRzIFczQyBUcmFjZSBDb250ZXh0IHNwZWNpZmljYXRpb24gZm9yIHByb3BhZ2F0aW5nIHRyYWNlIGNvbnRleHQKICogdXNpbmcgdHJhY2VwYXJlbnQgYW5kIHRyYWNlc3RhdGUgaGVhZGVycy4KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":819,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFczQ0JhZ2dhZ2UgcHJvcGFnYXRvci4KICoKICogSW1wbGVtZW50cyBXM0MgQmFnZ2FnZSBzcGVjaWZpY2F0aW9uIGZvciBwcm9wYWdhdGluZyBhcHBsaWNhdGlvbi1zcGVjaWZpYwogKiBrZXktdmFsdWUgcGFpcnMgdXNpbmcgdGhlIGJhZ2dhZ2UgaGVhZGVyLgogKi8="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":833,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENvbXBvc2l0ZVByb3BhZ2F0b3IuCiAqCiAqIENvbWJpbmVzIG11bHRpcGxlIHByb3BhZ2F0b3JzIGludG8gb25lLiBPbiBleHRyYWN0LCBhbGwgcHJvcGFnYXRvcnMgYXJlCiAqIGludm9rZWQgYW5kIHRoZWlyIGNvbnRleHRzIGFyZSBtZXJnZWQuIE9uIGluamVjdCwgYWxsIHByb3BhZ2F0b3JzIGFyZSBpbnZva2VkLgogKgogKiBAcGFyYW0gUHJvcGFnYXRvciAuLi4kcHJvcGFnYXRvcnMgVGhlIHByb3BhZ2F0b3JzIHRvIGNvbWJpbmUKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":848,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENoYWluRGV0ZWN0b3IuCiAqCiAqIENvbWJpbmVzIG11bHRpcGxlIHJlc291cmNlIGRldGVjdG9ycyBpbnRvIGEgY2hhaW4uIERldGVjdG9ycyBhcmUgZXhlY3V0ZWQKICogaW4gb3JkZXIgYW5kIHRoZWlyIHJlc3VsdHMgYXJlIG1lcmdlZC4gTGF0ZXIgZGV0ZWN0b3JzIHRha2UgcHJlY2VkZW5jZQogKiBvdmVyIGVhcmxpZXIgb25lcyB3aGVuIHRoZXJlIGFyZSBjb25mbGljdGluZyBhdHRyaWJ1dGUga2V5cy4KICoKICogQHBhcmFtIFJlc291cmNlRGV0ZWN0b3IgLi4uJGRldGVjdG9ycyBUaGUgZGV0ZWN0b3JzIHRvIGNoYWluCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":860,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBPc0RldGVjdG9yLgogKgogKiBEZXRlY3RzIG9wZXJhdGluZyBzeXN0ZW0gaW5mb3JtYXRpb24gaW5jbHVkaW5nIG9zLnR5cGUsIG9zLm5hbWUsIG9zLnZlcnNpb24sCiAqIGFuZCBvcy5kZXNjcmlwdGlvbiB1c2luZyBQSFAncyBwaHBfdW5hbWUoKSBmdW5jdGlvbi4KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":872,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEhvc3REZXRlY3Rvci4KICoKICogRGV0ZWN0cyBob3N0IGluZm9ybWF0aW9uIGluY2x1ZGluZyBob3N0Lm5hbWUsIGhvc3QuYXJjaCwgYW5kIGhvc3QuaWQKICogKGZyb20gL2V0Yy9tYWNoaW5lLWlkIG9uIExpbnV4IG9yIElPUGxhdGZvcm1VVUlEIG9uIG1hY09TKS4KICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":885,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFByb2Nlc3NEZXRlY3Rvci4KICoKICogRGV0ZWN0cyBwcm9jZXNzIGluZm9ybWF0aW9uIGluY2x1ZGluZyBwcm9jZXNzLnBpZCwgcHJvY2Vzcy5leGVjdXRhYmxlLnBhdGgsCiAqIHByb2Nlc3MucnVudGltZS5uYW1lIChQSFApLCBwcm9jZXNzLnJ1bnRpbWUudmVyc2lvbiwgcHJvY2Vzcy5jb21tYW5kLAogKiBhbmQgcHJvY2Vzcy5vd25lciAob24gUE9TSVggc3lzdGVtcykuCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":898,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBFbnZpcm9ubWVudERldGVjdG9yLgogKgogKiBEZXRlY3RzIHJlc291cmNlIGF0dHJpYnV0ZXMgZnJvbSBPcGVuVGVsZW1ldHJ5IHN0YW5kYXJkIGVudmlyb25tZW50IHZhcmlhYmxlczoKICogLSBPVEVMX1NFUlZJQ0VfTkFNRTogU2V0cyBzZXJ2aWNlLm5hbWUgYXR0cmlidXRlCiAqIC0gT1RFTF9SRVNPVVJDRV9BVFRSSUJVVEVTOiBTZXRzIGFkZGl0aW9uYWwgYXR0cmlidXRlcyBpbiBrZXk9dmFsdWUsa2V5Mj12YWx1ZTIgZm9ybWF0CiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":910,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENvbXBvc2VyRGV0ZWN0b3IuCiAqCiAqIERldGVjdHMgc2VydmljZS5uYW1lIGFuZCBzZXJ2aWNlLnZlcnNpb24gZnJvbSBDb21wb3NlcidzIEluc3RhbGxlZFZlcnNpb25zCiAqIHVzaW5nIHRoZSByb290IHBhY2thZ2UgaW5mb3JtYXRpb24uCiAqLw=="},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":924,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIE1hbnVhbERldGVjdG9yLgogKgogKiBSZXR1cm5zIG1hbnVhbGx5IHNwZWNpZmllZCByZXNvdXJjZSBhdHRyaWJ1dGVzLiBVc2UgdGhpcyB3aGVuIHlvdSBuZWVkCiAqIHRvIHNldCBhdHRyaWJ1dGVzIGV4cGxpY2l0bHkgcmF0aGVyIHRoYW4gZGV0ZWN0aW5nIHRoZW0gYXV0b21hdGljYWxseS4KICoKICogQHBhcmFtIGFycmF5PHN0cmluZywgYXJyYXk8Ym9vbHxmbG9hdHxpbnR8c3RyaW5nPnxib29sfGZsb2F0fGludHxzdHJpbmc+ICRhdHRyaWJ1dGVzIFJlc291cmNlIGF0dHJpYnV0ZXMKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":939,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIENhY2hpbmdEZXRlY3Rvci4KICoKICogV3JhcHMgYW5vdGhlciBkZXRlY3RvciBhbmQgY2FjaGVzIGl0cyByZXN1bHRzIHRvIGEgZmlsZS4gT24gc3Vic2VxdWVudAogKiBjYWxscywgcmV0dXJucyB0aGUgY2FjaGVkIHJlc291cmNlIGluc3RlYWQgb2YgcnVubmluZyBkZXRlY3Rpb24gYWdhaW4uCiAqCiAqIEBwYXJhbSBSZXNvdXJjZURldGVjdG9yICRkZXRlY3RvciBUaGUgZGV0ZWN0b3IgdG8gd3JhcAogKiBAcGFyYW0gbnVsbHxzdHJpbmcgJGNhY2hlUGF0aCBDYWNoZSBmaWxlIHBhdGggKGRlZmF1bHQ6IHN5c19nZXRfdGVtcF9kaXIoKS9mbG93X3RlbGVtZXRyeV9yZXNvdXJjZS5jYWNoZSkKICov"},{"repository_path":"src\/lib\/telemetry\/src\/Flow\/Telemetry\/DSL\/functions.php","start_line_in_file":959,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHJlc291cmNlIGRldGVjdG9yIGNoYWluLgogKgogKiBXaGVuIG5vIGRldGVjdG9ycyBhcmUgcHJvdmlkZWQsIHVzZXMgdGhlIGRlZmF1bHQgZGV0ZWN0b3IgY2hhaW46CiAqIDEuIE9zRGV0ZWN0b3IgLSBPcGVyYXRpbmcgc3lzdGVtIGluZm9ybWF0aW9uCiAqIDIuIEhvc3REZXRlY3RvciAtIEhvc3QgaW5mb3JtYXRpb24KICogMy4gUHJvY2Vzc0RldGVjdG9yIC0gUHJvY2VzcyBpbmZvcm1hdGlvbgogKiA0LiBDb21wb3NlckRldGVjdG9yIC0gU2VydmljZSBpbmZvcm1hdGlvbiBmcm9tIENvbXBvc2VyCiAqIDUuIEVudmlyb25tZW50RGV0ZWN0b3IgLSBFbnZpcm9ubWVudCB2YXJpYWJsZSBvdmVycmlkZXMgKGhpZ2hlc3QgcHJlY2VkZW5jZSkKICoKICogV2hlbiBkZXRlY3RvcnMgYXJlIHByb3ZpZGVkLCB1c2VzIG9ubHkgdGhvc2UgZGV0ZWN0b3JzLgogKgogKiBAcGFyYW0gYXJyYXk8UmVzb3VyY2VEZXRlY3Rvcj4gJGRldGVjdG9ycyBPcHRpb25hbCBjdXN0b20gZGV0ZWN0b3JzIChlbXB0eSA9IHVzZSBkZWZhdWx0cykKICov"},{"repository_path":"src\/lib\/azure-sdk\/src\/Flow\/Azure\/SDK\/DSL\/functions.php","start_line_in_file":18,"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\\ETL\\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":24,"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\\ETL\\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":30,"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\\ETL\\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":36,"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\\ETL\\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":42,"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\\ETL\\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","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\\ETL\\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":12,"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\\ETL\\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":18,"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::..."}],"return_type":[{"name":"AzureBlobFilesystem","namespace":"Flow\\Filesystem\\Bridge\\Azure","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":15,"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\\ETL\\Attribute","arguments":{"module":"S3_FILESYSTEM","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheTxzdHJpbmcsIG1peGVkPiAkY29uZmlndXJhdGlvbiAtIGZvciBkZXRhaWxzIHBsZWFzZSBzZWUgaHR0cHM6Ly9hc3luYy1hd3MuY29tL2NsaWVudHMvczMuaHRtbAogKi8="},{"repository_path":"src\/bridge\/filesystem\/async-aws\/src\/Flow\/Filesystem\/Bridge\/AsyncAWS\/DSL\/functions.php","start_line_in_file":22,"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::..."}],"return_type":[{"name":"AsyncAWSS3Filesystem","namespace":"Flow\\Filesystem\\Bridge\\AsyncAWS","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"S3_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":32,"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\\ETL\\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":65,"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\\ETL\\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":99,"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\\ETL\\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":144,"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"}],"return_type":[{"name":"TelemetryHandler","namespace":"Flow\\Bridge\\Monolog\\Telemetry","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\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":12,"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\\ETL\\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":18,"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\\ETL\\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":12,"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\\ETL\\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":18,"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\\ETL\\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":13,"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\\ETL\\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":36,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIEpTT04gc2VyaWFsaXplciBmb3IgT1RMUC4KICoKICogUmV0dXJucyBhIEpzb25TZXJpYWxpemVyIHRoYXQgY29udmVydHMgdGVsZW1ldHJ5IGRhdGEgdG8gT1RMUCBKU09OIHdpcmUgZm9ybWF0LgogKiBVc2UgdGhpcyB3aXRoIEh0dHBUcmFuc3BvcnQgZm9yIEpTT04gb3ZlciBIVFRQLgogKgogKiBFeGFtcGxlIHVzYWdlOgogKiBgYGBwaHAKICogJHNlcmlhbGl6ZXIgPSBvdGxwX2pzb25fc2VyaWFsaXplcigpOwogKiAkdHJhbnNwb3J0ID0gb3RscF9odHRwX3RyYW5zcG9ydCgkY2xpZW50LCAkcmVxRmFjdG9yeSwgJHN0cmVhbUZhY3RvcnksICRlbmRwb2ludCwgJHNlcmlhbGl6ZXIpOwogKiBgYGAKICov"},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":58,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIFByb3RvYnVmIHNlcmlhbGl6ZXIgZm9yIE9UTFAuCiAqCiAqIFJldHVybnMgYSBQcm90b2J1ZlNlcmlhbGl6ZXIgdGhhdCBjb252ZXJ0cyB0ZWxlbWV0cnkgZGF0YSB0byBPVExQIFByb3RvYnVmIGJpbmFyeSBmb3JtYXQuCiAqIFVzZSB0aGlzIHdpdGggSHR0cFRyYW5zcG9ydCBmb3IgUHJvdG9idWYgb3ZlciBIVFRQLCBvciB3aXRoIEdycGNUcmFuc3BvcnQuCiAqCiAqIFJlcXVpcmVzOgogKiAtIGdvb2dsZS9wcm90b2J1ZiBwYWNrYWdlCiAqIC0gb3Blbi10ZWxlbWV0cnkvZ2VuLW90bHAtcHJvdG9idWYgcGFja2FnZQogKgogKiBFeGFtcGxlIHVzYWdlOgogKiBgYGBwaHAKICogJHNlcmlhbGl6ZXIgPSBvdGxwX3Byb3RvYnVmX3NlcmlhbGl6ZXIoKTsKICogJHRyYW5zcG9ydCA9IG90bHBfaHR0cF90cmFuc3BvcnQoJGNsaWVudCwgJHJlcUZhY3RvcnksICRzdHJlYW1GYWN0b3J5LCAkZW5kcG9pbnQsICRzZXJpYWxpemVyKTsKICogYGBgCiAqLw=="},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":98,"slug":"otlp-http-transport","name":"otlp_http_transport","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\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":"requestFactory","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":"streamFactory","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},{"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":"Serializer","namespace":"Flow\\Telemetry\\Serializer","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":"[]"}],"return_type":[{"name":"HttpTransport","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Transport","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBIVFRQIHRyYW5zcG9ydCBmb3IgT1RMUCBlbmRwb2ludHMuCiAqCiAqIENyZWF0ZXMgYW4gSHR0cFRyYW5zcG9ydCBjb25maWd1cmVkIHRvIHNlbmQgdGVsZW1ldHJ5IGRhdGEgdG8gYW4gT1RMUC1jb21wYXRpYmxlCiAqIGVuZHBvaW50IHVzaW5nIFBTUi0xOCBIVFRQIGNsaWVudC4gU3VwcG9ydHMgYm90aCBKU09OIGFuZCBQcm90b2J1ZiBmb3JtYXRzLgogKgogKiBFeGFtcGxlIHVzYWdlOgogKiBgYGBwaHAKICogLy8gSlNPTiBvdmVyIEhUVFAKICogJHRyYW5zcG9ydCA9IG90bHBfaHR0cF90cmFuc3BvcnQoCiAqICAgICBjbGllbnQ6ICRjbGllbnQsCiAqICAgICByZXF1ZXN0RmFjdG9yeTogJHBzcjE3RmFjdG9yeSwKICogICAgIHN0cmVhbUZhY3Rvcnk6ICRwc3IxN0ZhY3RvcnksCiAqICAgICBlbmRwb2ludDogJ2h0dHA6Ly9sb2NhbGhvc3Q6NDMxOCcsCiAqICAgICBzZXJpYWxpemVyOiBvdGxwX2pzb25fc2VyaWFsaXplcigpLAogKiApOwogKgogKiAvLyBQcm90b2J1ZiBvdmVyIEhUVFAKICogJHRyYW5zcG9ydCA9IG90bHBfaHR0cF90cmFuc3BvcnQoCiAqICAgICBjbGllbnQ6ICRjbGllbnQsCiAqICAgICByZXF1ZXN0RmFjdG9yeTogJHBzcjE3RmFjdG9yeSwKICogICAgIHN0cmVhbUZhY3Rvcnk6ICRwc3IxN0ZhY3RvcnksCiAqICAgICBlbmRwb2ludDogJ2h0dHA6Ly9sb2NhbGhvc3Q6NDMxOCcsCiAqICAgICBzZXJpYWxpemVyOiBvdGxwX3Byb3RvYnVmX3NlcmlhbGl6ZXIoKSwKICogKTsKICogYGBgCiAqCiAqIEBwYXJhbSBDbGllbnRJbnRlcmZhY2UgJGNsaWVudCBQU1ItMTggSFRUUCBjbGllbnQKICogQHBhcmFtIFJlcXVlc3RGYWN0b3J5SW50ZXJmYWNlICRyZXF1ZXN0RmFjdG9yeSBQU1ItMTcgcmVxdWVzdCBmYWN0b3J5CiAqIEBwYXJhbSBTdHJlYW1GYWN0b3J5SW50ZXJmYWNlICRzdHJlYW1GYWN0b3J5IFBTUi0xNyBzdHJlYW0gZmFjdG9yeQogKiBAcGFyYW0gc3RyaW5nICRlbmRwb2ludCBPVExQIGVuZHBvaW50IFVSTCAoZS5nLiwgJ2h0dHA6Ly9sb2NhbGhvc3Q6NDMxOCcpCiAqIEBwYXJhbSBTZXJpYWxpemVyICRzZXJpYWxpemVyIFNlcmlhbGl6ZXIgZm9yIGVuY29kaW5nIHRlbGVtZXRyeSBkYXRhIChKU09OIG9yIFByb3RvYnVmKQogKiBAcGFyYW0gYXJyYXk8c3RyaW5nLCBzdHJpbmc+ICRoZWFkZXJzIEFkZGl0aW9uYWwgaGVhZGVycyB0byBpbmNsdWRlIGluIHJlcXVlc3RzCiAqLw=="},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":134,"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":"serializer","type":[{"name":"ProtobufSerializer","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Serializer","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"}],"return_type":[{"name":"GrpcTransport","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Transport","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGdSUEMgdHJhbnNwb3J0IGZvciBPVExQIGVuZHBvaW50cy4KICoKICogQ3JlYXRlcyBhIEdycGNUcmFuc3BvcnQgY29uZmlndXJlZCB0byBzZW5kIHRlbGVtZXRyeSBkYXRhIHRvIGFuIE9UTFAtY29tcGF0aWJsZQogKiBlbmRwb2ludCB1c2luZyBnUlBDIHByb3RvY29sIHdpdGggUHJvdG9idWYgc2VyaWFsaXphdGlvbi4KICoKICogUmVxdWlyZXM6CiAqIC0gZXh0LWdycGMgUEhQIGV4dGVuc2lvbgogKiAtIGdvb2dsZS9wcm90b2J1ZiBwYWNrYWdlCiAqIC0gb3Blbi10ZWxlbWV0cnkvZ2VuLW90bHAtcHJvdG9idWYgcGFja2FnZQogKgogKiBFeGFtcGxlIHVzYWdlOgogKiBgYGBwaHAKICogJHRyYW5zcG9ydCA9IG90bHBfZ3JwY190cmFuc3BvcnQoCiAqICAgICBlbmRwb2ludDogJ2xvY2FsaG9zdDo0MzE3JywKICogICAgIHNlcmlhbGl6ZXI6IG90bHBfcHJvdG9idWZfc2VyaWFsaXplcigpLAogKiApOwogKiBgYGAKICoKICogQHBhcmFtIHN0cmluZyAkZW5kcG9pbnQgZ1JQQyBlbmRwb2ludCAoZS5nLiwgJ2xvY2FsaG9zdDo0MzE3JykKICogQHBhcmFtIFByb3RvYnVmU2VyaWFsaXplciAkc2VyaWFsaXplciBQcm90b2J1ZiBzZXJpYWxpemVyIGZvciBlbmNvZGluZyB0ZWxlbWV0cnkgZGF0YQogKiBAcGFyYW0gYXJyYXk8c3RyaW5nLCBzdHJpbmc+ICRoZWFkZXJzIEFkZGl0aW9uYWwgaGVhZGVycyAobWV0YWRhdGEpIHRvIGluY2x1ZGUgaW4gcmVxdWVzdHMKICogQHBhcmFtIGJvb2wgJGluc2VjdXJlIFdoZXRoZXIgdG8gdXNlIGluc2VjdXJlIGNoYW5uZWwgY3JlZGVudGlhbHMgKGRlZmF1bHQgdHJ1ZSBmb3IgbG9jYWwgZGV2KQogKi8="},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":162,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBjdXJsIHRyYW5zcG9ydCBvcHRpb25zIGZvciBPVExQLgogKgogKiBSZXR1cm5zIGEgQ3VybFRyYW5zcG9ydE9wdGlvbnMgYnVpbGRlciBmb3IgY29uZmlndXJpbmcgY3VybCB0cmFuc3BvcnQgc2V0dGluZ3MKICogdXNpbmcgYSBmbHVlbnQgaW50ZXJmYWNlLgogKgogKiBFeGFtcGxlIHVzYWdlOgogKiBgYGBwaHAKICogJG9wdGlvbnMgPSBvdGxwX2N1cmxfb3B0aW9ucygpCiAqICAgICAtPndpdGhUaW1lb3V0KDYwKQogKiAgICAgLT53aXRoQ29ubmVjdFRpbWVvdXQoMTUpCiAqICAgICAtPndpdGhIZWFkZXIoJ0F1dGhvcml6YXRpb24nLCAnQmVhcmVyIHRva2VuJykKICogICAgIC0+d2l0aENvbXByZXNzaW9uKCkKICogICAgIC0+d2l0aFNzbFZlcmlmaWNhdGlvbih2ZXJpZnlQZWVyOiB0cnVlKTsKICoKICogJHRyYW5zcG9ydCA9IG90bHBfY3VybF90cmFuc3BvcnQoJGVuZHBvaW50LCAkc2VyaWFsaXplciwgJG9wdGlvbnMpOwogKiBgYGAKICov"},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":201,"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":"Serializer","namespace":"Flow\\Telemetry\\Serializer","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null},{"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::..."}],"return_type":[{"name":"CurlTransport","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Transport","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBhc3luYyBjdXJsIHRyYW5zcG9ydCBmb3IgT1RMUCBlbmRwb2ludHMuCiAqCiAqIENyZWF0ZXMgYSBDdXJsVHJhbnNwb3J0IHRoYXQgdXNlcyBjdXJsX211bHRpIGZvciBub24tYmxvY2tpbmcgSS9PLgogKiBVbmxpa2UgSHR0cFRyYW5zcG9ydCAoUFNSLTE4KSwgdGhpcyB0cmFuc3BvcnQgcXVldWVzIHJlcXVlc3RzIGFuZCBleGVjdXRlcwogKiB0aGVtIGFzeW5jaHJvbm91c2x5LiBDb21wbGV0ZWQgcmVxdWVzdHMgYXJlIHByb2Nlc3NlZCBvbiBzdWJzZXF1ZW50IHNlbmQoKQogKiBjYWxscyBvciBvbiBzaHV0ZG93bigpLgogKgogKiBSZXF1aXJlczogZXh0LWN1cmwgUEhQIGV4dGVuc2lvbgogKgogKiBFeGFtcGxlIHVzYWdlOgogKiBgYGBwaHAKICogLy8gSlNPTiBvdmVyIEhUVFAgKGFzeW5jKSB3aXRoIGRlZmF1bHQgb3B0aW9ucwogKiAkdHJhbnNwb3J0ID0gb3RscF9jdXJsX3RyYW5zcG9ydCgKICogICAgIGVuZHBvaW50OiAnaHR0cDovL2xvY2FsaG9zdDo0MzE4JywKICogICAgIHNlcmlhbGl6ZXI6IG90bHBfanNvbl9zZXJpYWxpemVyKCksCiAqICk7CiAqCiAqIC8vIFByb3RvYnVmIG92ZXIgSFRUUCAoYXN5bmMpIHdpdGggY3VzdG9tIG9wdGlvbnMKICogJHRyYW5zcG9ydCA9IG90bHBfY3VybF90cmFuc3BvcnQoCiAqICAgICBlbmRwb2ludDogJ2h0dHA6Ly9sb2NhbGhvc3Q6NDMxOCcsCiAqICAgICBzZXJpYWxpemVyOiBvdGxwX3Byb3RvYnVmX3NlcmlhbGl6ZXIoKSwKICogICAgIG9wdGlvbnM6IG90bHBfY3VybF9vcHRpb25zKCkKICogICAgICAgICAtPndpdGhUaW1lb3V0KDYwKQogKiAgICAgICAgIC0+d2l0aEhlYWRlcignQXV0aG9yaXphdGlvbicsICdCZWFyZXIgdG9rZW4nKQogKiAgICAgICAgIC0+d2l0aENvbXByZXNzaW9uKCksCiAqICk7CiAqIGBgYAogKgogKiBAcGFyYW0gc3RyaW5nICRlbmRwb2ludCBPVExQIGVuZHBvaW50IFVSTCAoZS5nLiwgJ2h0dHA6Ly9sb2NhbGhvc3Q6NDMxOCcpCiAqIEBwYXJhbSBTZXJpYWxpemVyICRzZXJpYWxpemVyIFNlcmlhbGl6ZXIgZm9yIGVuY29kaW5nIHRlbGVtZXRyeSBkYXRhIChKU09OIG9yIFByb3RvYnVmKQogKiBAcGFyYW0gQ3VybFRyYW5zcG9ydE9wdGlvbnMgJG9wdGlvbnMgVHJhbnNwb3J0IGNvbmZpZ3VyYXRpb24gb3B0aW9ucwogKi8="},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":221,"slug":"otlp-span-exporter","name":"otlp_span_exporter","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\DSL","parameters":[{"name":"transport","type":[{"name":"Transport","namespace":"Flow\\Telemetry\\Transport","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"OTLPSpanExporter","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Exporter","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBPVExQIHNwYW4gZXhwb3J0ZXIuCiAqCiAqIEV4YW1wbGUgdXNhZ2U6CiAqIGBgYHBocAogKiAkZXhwb3J0ZXIgPSBvdGxwX3NwYW5fZXhwb3J0ZXIoJHRyYW5zcG9ydCk7CiAqICRwcm9jZXNzb3IgPSBiYXRjaGluZ19zcGFuX3Byb2Nlc3NvcigkZXhwb3J0ZXIpOwogKiBgYGAKICoKICogQHBhcmFtIFRyYW5zcG9ydCAkdHJhbnNwb3J0IFRoZSB0cmFuc3BvcnQgZm9yIHNlbmRpbmcgc3BhbiBkYXRhCiAqLw=="},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":238,"slug":"otlp-metric-exporter","name":"otlp_metric_exporter","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\DSL","parameters":[{"name":"transport","type":[{"name":"Transport","namespace":"Flow\\Telemetry\\Transport","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"OTLPMetricExporter","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Exporter","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBPVExQIG1ldHJpYyBleHBvcnRlci4KICoKICogRXhhbXBsZSB1c2FnZToKICogYGBgcGhwCiAqICRleHBvcnRlciA9IG90bHBfbWV0cmljX2V4cG9ydGVyKCR0cmFuc3BvcnQpOwogKiAkcHJvY2Vzc29yID0gYmF0Y2hpbmdfbWV0cmljX3Byb2Nlc3NvcigkZXhwb3J0ZXIpOwogKiBgYGAKICoKICogQHBhcmFtIFRyYW5zcG9ydCAkdHJhbnNwb3J0IFRoZSB0cmFuc3BvcnQgZm9yIHNlbmRpbmcgbWV0cmljIGRhdGEKICov"},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":255,"slug":"otlp-log-exporter","name":"otlp_log_exporter","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\DSL","parameters":[{"name":"transport","type":[{"name":"Transport","namespace":"Flow\\Telemetry\\Transport","is_nullable":false,"is_variadic":false}],"has_default_value":false,"is_nullable":false,"is_variadic":false,"default_value":null}],"return_type":[{"name":"OTLPLogExporter","namespace":"Flow\\Bridge\\Telemetry\\OTLP\\Exporter","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhbiBPVExQIGxvZyBleHBvcnRlci4KICoKICogRXhhbXBsZSB1c2FnZToKICogYGBgcGhwCiAqICRleHBvcnRlciA9IG90bHBfbG9nX2V4cG9ydGVyKCR0cmFuc3BvcnQpOwogKiAkcHJvY2Vzc29yID0gYmF0Y2hpbmdfbG9nX3Byb2Nlc3NvcigkZXhwb3J0ZXIpOwogKiBgYGAKICoKICogQHBhcmFtIFRyYW5zcG9ydCAkdHJhbnNwb3J0IFRoZSB0cmFuc3BvcnQgZm9yIHNlbmRpbmcgbG9nIGRhdGEKICov"},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":276,"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\\AlwaysOnSampler::..."},{"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIHRyYWNlciBwcm92aWRlciBjb25maWd1cmVkIGZvciBPVExQIGV4cG9ydC4KICoKICogRXhhbXBsZSB1c2FnZToKICogYGBgcGhwCiAqICRwcm9jZXNzb3IgPSBiYXRjaGluZ19zcGFuX3Byb2Nlc3NvcihvdGxwX3NwYW5fZXhwb3J0ZXIoJHRyYW5zcG9ydCkpOwogKiAkcHJvdmlkZXIgPSBvdGxwX3RyYWNlcl9wcm92aWRlcigkcHJvY2Vzc29yLCAkY2xvY2spOwogKiAkdHJhY2VyID0gJHByb3ZpZGVyLT50cmFjZXIoJHJlc291cmNlLCAnbXktc2VydmljZScsICcxLjAuMCcpOwogKiBgYGAKICoKICogQHBhcmFtIFNwYW5Qcm9jZXNzb3IgJHByb2Nlc3NvciBUaGUgcHJvY2Vzc29yIGZvciBoYW5kbGluZyBzcGFucwogKiBAcGFyYW0gQ2xvY2tJbnRlcmZhY2UgJGNsb2NrIFRoZSBjbG9jayBmb3IgdGltZXN0YW1wcwogKiBAcGFyYW0gU2FtcGxlciAkc2FtcGxlciBUaGUgc2FtcGxlciBmb3IgZGVjaWRpbmcgd2hldGhlciB0byByZWNvcmQgc3BhbnMKICogQHBhcmFtIENvbnRleHRTdG9yYWdlICRjb250ZXh0U3RvcmFnZSBUaGUgY29udGV4dCBzdG9yYWdlIGZvciBwcm9wYWdhdGluZyB0cmFjZSBjb250ZXh0CiAqLw=="},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":300,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIG1ldGVyIHByb3ZpZGVyIGNvbmZpZ3VyZWQgZm9yIE9UTFAgZXhwb3J0LgogKgogKiBFeGFtcGxlIHVzYWdlOgogKiBgYGBwaHAKICogJHByb2Nlc3NvciA9IGJhdGNoaW5nX21ldHJpY19wcm9jZXNzb3Iob3RscF9tZXRyaWNfZXhwb3J0ZXIoJHRyYW5zcG9ydCkpOwogKiAkcHJvdmlkZXIgPSBvdGxwX21ldGVyX3Byb3ZpZGVyKCRwcm9jZXNzb3IsICRjbG9jayk7CiAqICRtZXRlciA9ICRwcm92aWRlci0+bWV0ZXIoJHJlc291cmNlLCAnbXktc2VydmljZScsICcxLjAuMCcpOwogKiBgYGAKICoKICogQHBhcmFtIE1ldHJpY1Byb2Nlc3NvciAkcHJvY2Vzc29yIFRoZSBwcm9jZXNzb3IgZm9yIGhhbmRsaW5nIG1ldHJpY3MKICogQHBhcmFtIENsb2NrSW50ZXJmYWNlICRjbG9jayBUaGUgY2xvY2sgZm9yIHRpbWVzdGFtcHMKICogQHBhcmFtIEFnZ3JlZ2F0aW9uVGVtcG9yYWxpdHkgJHRlbXBvcmFsaXR5IFRoZSBhZ2dyZWdhdGlvbiB0ZW1wb3JhbGl0eSBmb3IgbWV0cmljcwogKi8="},{"repository_path":"src\/bridge\/telemetry\/otlp\/src\/Flow\/Bridge\/Telemetry\/OTLP\/DSL\/functions.php","start_line_in_file":323,"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\\ETL\\Attribute","arguments":{"module":"TELEMETRY_OTLP","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIENyZWF0ZSBhIGxvZ2dlciBwcm92aWRlciBjb25maWd1cmVkIGZvciBPVExQIGV4cG9ydC4KICoKICogRXhhbXBsZSB1c2FnZToKICogYGBgcGhwCiAqICRwcm9jZXNzb3IgPSBiYXRjaGluZ19sb2dfcHJvY2Vzc29yKG90bHBfbG9nX2V4cG9ydGVyKCR0cmFuc3BvcnQpKTsKICogJHByb3ZpZGVyID0gb3RscF9sb2dnZXJfcHJvdmlkZXIoJHByb2Nlc3NvciwgJGNsb2NrKTsKICogJGxvZ2dlciA9ICRwcm92aWRlci0+bG9nZ2VyKCRyZXNvdXJjZSwgJ215LXNlcnZpY2UnLCAnMS4wLjAnKTsKICogYGBgCiAqCiAqIEBwYXJhbSBMb2dQcm9jZXNzb3IgJHByb2Nlc3NvciBUaGUgcHJvY2Vzc29yIGZvciBoYW5kbGluZyBsb2cgcmVjb3JkcwogKiBAcGFyYW0gQ2xvY2tJbnRlcmZhY2UgJGNsb2NrIFRoZSBjbG9jayBmb3IgdGltZXN0YW1wcwogKiBAcGFyYW0gQ29udGV4dFN0b3JhZ2UgJGNvbnRleHRTdG9yYWdlIFRoZSBjb250ZXh0IHN0b3JhZ2UgZm9yIHByb3BhZ2F0aW5nIGNvbnRleHQKICov"}] \ No newline at end of file diff --git a/web/landing/src/Flow/Website/Model/Documentation/Module.php b/web/landing/src/Flow/Website/Model/Documentation/Module.php index 381ee592a3..10ae82ee25 100644 --- a/web/landing/src/Flow/Website/Model/Documentation/Module.php +++ b/web/landing/src/Flow/Website/Model/Documentation/Module.php @@ -24,6 +24,7 @@ enum Module : string case PARQUET = 'Parquet'; case PG_QUERY = 'PG_QUERY'; case POSTGRESQL = 'POSTGRESQL'; + case POSTGRESQL_MIGRATIONS = 'PostgreSQL Migrations'; case PSR18_TELEMETRY_BRIDGE = 'PSR-18 Telemetry Bridge'; case PSR7_TELEMETRY_BRIDGE = 'PSR-7 Telemetry Bridge'; case S3_FILESYSTEM = 'S3 Filesystem'; @@ -71,6 +72,7 @@ public function priority() : int self::SYMFONY_TELEMETRY_BUNDLE => 24, self::PSR7_TELEMETRY_BRIDGE => 25, self::PSR18_TELEMETRY_BRIDGE => 26, + self::POSTGRESQL_MIGRATIONS => 27, default => 99, }; } diff --git a/web/landing/templates/documentation/navigation_right.html.twig b/web/landing/templates/documentation/navigation_right.html.twig index 3a02398b3a..20637fe6cf 100644 --- a/web/landing/templates/documentation/navigation_right.html.twig +++ b/web/landing/templates/documentation/navigation_right.html.twig @@ -131,6 +131,9 @@
  • Telemetry Bundle
  • +
  • + PostgreSQL Bundle +
  • Streamed Response