diff --git a/.github/workflows/job-pg-query-extension.yml b/.github/workflows/job-pg-query-extension.yml
index e62b113f5..f4586d824 100644
--- a/.github/workflows/job-pg-query-extension.yml
+++ b/.github/workflows/job-pg-query-extension.yml
@@ -50,16 +50,6 @@ jobs:
echo "extension=pg_query.so" | sudo tee -a "$(php -r 'echo php_ini_loaded_file();')"
php -m | grep pg_query
- - name: Run pg-query library tests
- run: composer test:lib:pg-query
-
- - name: Upload to Codecov
- uses: ./.github/actions/codecov-report
- with:
- token: ${{ secrets.CODECOV_TOKEN }}
- php-version: ${{ matrix.php }}
- dependencies: locked
-
pie-install-test:
name: Test PIE Installation
runs-on: ubuntu-latest
diff --git a/.github/workflows/job-tests.yml b/.github/workflows/job-tests.yml
index 04fb0c530..1e9daa3b0 100644
--- a/.github/workflows/job-tests.yml
+++ b/.github/workflows/job-tests.yml
@@ -79,6 +79,8 @@ jobs:
coverage: 'pcov'
extensions: ':psr, bcmath, dom, hash, json, mbstring, xml, xmlwriter, xmlreader, zlib, curl'
ini-values: 'memory_limit=-1, post_max_size=32M, upload_max_filesize=32M'
+ apt-packages: "build-essential autoconf automake libtool protobuf-compiler libprotobuf-c-dev"
+ pie-extensions: "flow-php/pg-query-ext:1.x-dev"
- name: Set up Node.js
uses: actions/setup-node@v5
diff --git a/.github/workflows/job-windows-tests.yml b/.github/workflows/job-windows-tests.yml
index f06459d84..85121e291 100644
--- a/.github/workflows/job-windows-tests.yml
+++ b/.github/workflows/job-windows-tests.yml
@@ -45,7 +45,7 @@ jobs:
php-${{ matrix.php-version }}-${{ matrix.dependencies }}-composer-windows-
- name: "Install locked dependencies"
- run: "composer install --no-interaction --no-progress --no-scripts"
+ run: "composer install --no-interaction --no-progress --no-scripts --ignore-platform-req=ext-pgsql --ignore-platform-req=ext-pg_query"
- name: "Install PHPUnit"
run: "composer install --working-dir=./tools/phpunit --no-interaction --no-progress"
diff --git a/.github/workflows/monorepo-split.yml b/.github/workflows/monorepo-split.yml
index d2c7fc6cb..a102f702f 100644
--- a/.github/workflows/monorepo-split.yml
+++ b/.github/workflows/monorepo-split.yml
@@ -42,8 +42,8 @@ jobs:
split_repository: 'snappy'
- local_path: 'src/lib/types'
split_repository: 'types'
- - local_path: 'src/lib/pg-query'
- split_repository: 'pg-query'
+ - local_path: 'src/lib/postgresql'
+ split_repository: 'postgresql'
- local_path: 'src/adapter/etl-adapter-avro'
split_repository: 'etl-adapter-avro'
diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php
index 32324a423..715309020 100644
--- a/.php-cs-fixer.php
+++ b/.php-cs-fixer.php
@@ -84,6 +84,7 @@
'fopen_flags' => true,
'heredoc_to_nowdoc' => true,
'increment_style' => ['style' => 'post'],
+ 'is_null' => false,
'linebreak_after_opening_tag' => false,
'method_argument_space' => ['on_multiline' => 'ensure_fully_multiline'],
'modernize_types_casting' => false,
diff --git a/bin/docs.php b/bin/docs.php
index 6aa377968..f748dd71c 100755
--- a/bin/docs.php
+++ b/bin/docs.php
@@ -61,7 +61,7 @@ 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/pg-query/src/Flow/PgQuery/DSL/functions.php',
+ __DIR__ . '/../src/lib/postgresql/src/Flow/PostgreSql/DSL/functions.php',
__DIR__ . '/../src/bridge/filesystem/azure/src/Flow/Filesystem/Bridge/Azure/DSL/functions.php',
__DIR__ . '/../src/bridge/filesystem/async-aws/src/Flow/Filesystem/Bridge/AsyncAWS/DSL/functions.php',
__DIR__ . '/../src/lib/azure-sdk/src/Flow/Azure/SDK/DSL/functions.php',
diff --git a/composer.json b/composer.json
index 2c95bf94f..34c184b27 100644
--- a/composer.json
+++ b/composer.json
@@ -20,6 +20,7 @@
"ext-xmlreader": "*",
"ext-xmlwriter": "*",
"ext-zlib": "*",
+ "ext-pgsql": "*",
"composer-runtime-api": "^2.1",
"async-aws/s3": "^2.6",
"brick/math": "^0.11 || ^0.12 || ^0.13 || ^0.14",
@@ -95,7 +96,7 @@
"flow-php/snappy": "self.version",
"flow-php/symfony-http-foundation-bridge": "self.version",
"flow-php/types": "self.version",
- "flow-php/pg-query": "self.version"
+ "flow-php/postgresql": "self.version"
},
"minimum-stability": "dev",
"prefer-stable": true,
@@ -132,7 +133,7 @@
"src/lib/parquet/src/Flow",
"src/lib/snappy/src/Flow",
"src/lib/types/src/Flow",
- "src/lib/pg-query/src/Flow",
+ "src/lib/postgresql/src/Flow",
"src/tools/documentation/src/Flow"
],
"Flow\\Doctrine\\Bulk\\": [
@@ -171,8 +172,8 @@
"src/lib/parquet/src/stubs.php",
"src/lib/snappy/polyfill.php",
"src/lib/types/src/Flow/Types/DSL/functions.php",
- "src/lib/pg-query/src/Flow/PgQuery/DSL/functions.php",
- "src/lib/pg-query/src/stubs.php"
+ "src/lib/postgresql/src/Flow/PostgreSql/DSL/functions.php",
+ "src/lib/postgresql/src/stubs.php"
]
},
"autoload-dev": {
@@ -208,7 +209,7 @@
"src/lib/parquet/tests/Flow",
"src/lib/snappy/tests/Flow",
"src/lib/types/tests/Flow",
- "src/lib/pg-query/tests/Flow",
+ "src/lib/postgresql/tests/Flow",
"src/tools/documentation/tests/Flow"
],
"Flow\\Doctrine\\Bulk\\Tests\\": [
@@ -253,7 +254,7 @@
"@test:lib:filesystem",
"@test:lib:parquet",
"@test:lib:parquet-viewer",
- "@test:lib:pg-query",
+ "@test:lib:postgresql",
"@test:lib:snappy",
"@test:lib:types"
],
@@ -314,8 +315,9 @@
"test:lib:types": [
"tools/phpunit/vendor/bin/phpunit --testsuite=lib-types-unit --log-junit ./var/phpunit/logs/lib-types-unit.junit.xml --coverage-clover=./var/phpunit/coverage/clover/lib-types-unit.coverage.xml --coverage-html=./var/phpunit/coverage/html/lib-types-unit"
],
- "test:lib:pg-query": [
- "tools/phpunit/vendor/bin/phpunit --testsuite=lib-pg-query-unit --log-junit ./var/phpunit/logs/lib-pg-query-unit.junit.xml --coverage-clover=./var/phpunit/coverage/clover/lib-pg-query-unit.coverage.xml --coverage-html=./var/phpunit/coverage/html/lib-pg-query-unit"
+ "test:lib:postgresql": [
+ "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 --coverage-html=./var/phpunit/coverage/html/lib-postgresql-unit",
+ "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 --coverage-html=./var/phpunit/coverage/html/lib-postgresql-integration"
],
"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 --coverage-html=./var/phpunit/coverage/html/bridge-filesystem-azure-unit",
@@ -462,6 +464,7 @@
"./tools/phpdocumentor/vendor/bin/phpdoc --config=./phpdoc/lib.filesystem.xml",
"./tools/phpdocumentor/vendor/bin/phpdoc --config=./phpdoc/lib.parquet.xml",
"./tools/phpdocumentor/vendor/bin/phpdoc --config=./phpdoc/lib.parquet-viewer.xml",
+ "./tools/phpdocumentor/vendor/bin/phpdoc --config=./phpdoc/lib.postgresql.xml",
"./tools/phpdocumentor/vendor/bin/phpdoc --config=./phpdoc/lib.snappy.xml",
"./tools/phpdocumentor/vendor/bin/phpdoc --config=./phpdoc/lib.types.xml",
"./tools/phpdocumentor/vendor/bin/phpdoc --config=./phpdoc/adapter.chartjs.xml",
@@ -489,9 +492,9 @@
"thrift --gen php --out src/lib/parquet/src src/lib/parquet/src/Flow/Parquet/Resources/Thrift/parquet.thrift",
"@cs:php:fix"
],
- "build:pg-query:protobuf": [
- "rm -rf src/lib/pg-query/src/Flow/PgQuery/Protobuf",
- "protoc --php_out=src/lib/pg-query/src --proto_path=src/lib/pg-query/resources/proto pg_query.proto",
+ "build:postgresql:protobuf": [
+ "rm -rf src/lib/postgresql/src/Flow/PostgreSql/Protobuf",
+ "protoc --php_out=src/lib/postgresql/src --proto_path=src/lib/postgresql/resources/proto pg_query.proto",
"@cs:php:fix"
],
"pre-autoload-dump": [
diff --git a/documentation/components/core/core.md b/documentation/components/core/core.md
index 3387480dd..f767eee52 100644
--- a/documentation/components/core/core.md
+++ b/documentation/components/core/core.md
@@ -3,6 +3,7 @@
- [⬅️️ Back](/documentation/quick-start.md)
- [📚API Reference](/documentation/api/core)
- [📁Files](/documentation/api/core/indices/files.html)
+- [🗺DSL](/documentation/api/core/namespaces/flow-etl-dsl.html)
[TOC]
diff --git a/documentation/components/libs/filesystem.md b/documentation/components/libs/filesystem.md
index 552a0f866..bfeb3972d 100644
--- a/documentation/components/libs/filesystem.md
+++ b/documentation/components/libs/filesystem.md
@@ -3,6 +3,7 @@
- [⬅️️ Back](/documentation/introduction.md)
- [📚API Reference](/documentation/api/lib/filesystem)
- [📁Files](/documentation/api/lib/filesystem/indices/files.html)
+- [🗺DSL](/documentation/api/lib/filesystem/namespaces/flow-filesystem-dsl.html)
[TOC]
diff --git a/documentation/components/libs/pg-query.md b/documentation/components/libs/pg-query.md
deleted file mode 100644
index 6da6c308a..000000000
--- a/documentation/components/libs/pg-query.md
+++ /dev/null
@@ -1,456 +0,0 @@
-# PG Query
-
-- [⬅️️ Back](/documentation/introduction.md)
-
-[TOC]
-
-PostgreSQL Query Parser library provides strongly-typed AST (Abstract Syntax Tree) parsing for PostgreSQL SQL queries using the [libpg_query](https://github.com/pganalyze/libpg_query) library through a PHP extension.
-
-## Requirements
-
-This library requires the `pg_query` PHP extension. See [pg-query-ext documentation](/documentation/components/extensions/pg-query-ext.md) for installation instructions.
-
-## Installation
-
-```
-composer require flow-php/pg-query:~--FLOW_PHP_VERSION--
-```
-
-## Quick Start
-
-```php
-all() as $table) {
- echo $table->name(); // 'users', 'orders'
- echo $table->alias(); // 'u', 'o'
-}
-
-// Get all columns
-foreach (pg_query_columns($query)->all() as $column) {
- echo $column->name(); // 'id', 'name', 'id', 'user_id'
- echo $column->table(); // 'u', 'u', 'u', 'o'
-}
-
-// Get columns for specific table
-$userColumns = pg_query_columns($query)->forTable('u');
-
-// Get all function calls
-foreach (pg_query_functions($query)->all() as $func) {
- echo $func->name(); // function name
- echo $func->schema(); // schema if qualified (e.g., 'pg_catalog')
-}
-```
-
-## Parsing and Utilities
-
-```php
-indentSize(2) // 2 spaces per indent level
- ->maxLineLength(60) // Wrap at 60 characters
- ->trailingNewline() // Add newline at end
- ->commasStartOfLine() // Place commas at line start
-);
-
-// Shorthand: parse and format in one step
-$formatted = pg_format('SELECT id,name FROM users WHERE active=true');
-```
-
-### DeparseOptions
-
-| Method | Description | Default |
-|--------|-------------|---------|
-| `prettyPrint(bool)` | Enable/disable pretty printing | `true` |
-| `indentSize(int)` | Spaces per indentation level | `4` |
-| `maxLineLength(int)` | Maximum line length before wrapping | `80` |
-| `trailingNewline(bool)` | Add trailing newline at end | `false` |
-| `commasStartOfLine(bool)` | Place commas at start of lines | `false` |
-
-## Custom AST Traversal
-
-For advanced use cases, you can traverse the AST with custom visitors:
-
-```php
-count++;
- return null;
- }
-
- public function leave(object $node): ?int
- {
- return null;
- }
-}
-
-$query = pg_parse('SELECT id, name, email FROM users');
-
-$counter = new ColumnCounter();
-$query->traverse($counter);
-
-echo $counter->count; // 3
-```
-
-### NodeVisitor Interface
-
-```php
-interface NodeVisitor
-{
- public const DONT_TRAVERSE_CHILDREN = 1;
- public const STOP_TRAVERSAL = 2;
-
- /** @return class-string */
- public static function nodeClass(): string;
-
- public function enter(object $node): ?int;
- public function leave(object $node): ?int;
-}
-```
-
-Visitors declare which node type they handle via `nodeClass()`. Return values:
-- `null` - continue traversal
-- `DONT_TRAVERSE_CHILDREN` - skip children (from `enter()` only)
-- `STOP_TRAVERSAL` - stop entire traversal
-
-### Built-in Visitors
-
-- `ColumnRefCollector` - collects all `ColumnRef` nodes
-- `FuncCallCollector` - collects all `FuncCall` nodes
-- `RangeVarCollector` - collects all `RangeVar` nodes
-
-## Query Modification
-
-Beyond reading the AST, you can modify queries programmatically using modifiers. The library includes pagination modifiers as the primary use case.
-
-### Offset-Based Pagination
-
-Add LIMIT/OFFSET pagination to any SELECT query:
-
-```php
-traverse(pg_pagination(limit: 10, offset: 20));
-echo $query->deparse(); // SELECT * FROM users ORDER BY id LIMIT 10 OFFSET 20
-
-// Count modifier
-$query = pg_parse('SELECT * FROM users WHERE active = true ORDER BY name');
-$query->traverse(pg_count_modifier());
-echo $query->deparse(); // SELECT count(*) FROM (SELECT * FROM users WHERE active = true) _count_subq
-
-// Keyset pagination modifier
-$query = pg_parse('SELECT * FROM users ORDER BY created_at, id');
-$query->traverse(pg_keyset_pagination(
- limit: 10,
- columns: [
- pg_keyset_column('created_at', SortOrder::ASC),
- pg_keyset_column('id', SortOrder::ASC),
- ],
- cursor: ['2025-01-15', 42]
-));
-echo $query->deparse();
-// SELECT * FROM users WHERE created_at > $1 OR (created_at = $1 AND id > $2) ORDER BY created_at, id LIMIT 10
-```
-
-### Custom Modifiers
-
-Create custom modifiers by implementing the `NodeModifier` interface:
-
-```php
-isTopLevel()) {
- return null;
- }
-
- $node->setDistinctClause([new \Flow\PgQuery\Protobuf\AST\Node()]);
-
- return null;
- }
-}
-
-$query = pg_parse('SELECT id, name FROM users');
-$query->traverse(new AddDistinctModifier());
-echo pg_deparse($query); // SELECT DISTINCT id, name FROM users
-```
-
-### NodeModifier Interface
-
-```php
-interface NodeModifier
-{
- /** @return class-string */
- public static function nodeClass(): string;
-
- public function modify(object $node, ModificationContext $context): int|object|null;
-}
-```
-
-The `ModificationContext` provides:
-- `$context->depth` - current traversal depth
-- `$context->ancestors` - array of parent nodes
-- `$context->getParent()` - immediate parent node
-- `$context->isTopLevel()` - whether this is the top-level statement
-
-Return values:
-- `null` - continue traversal
-- `Traverser::DONT_TRAVERSE_CHILDREN` - skip children
-- `Traverser::STOP_TRAVERSAL` - stop entire traversal
-- `object` - replace current node with returned object
-
-## Raw AST Access
-
-For full control, access the protobuf AST directly:
-
-```php
-raw()->getStmts() as $stmt) {
- $select = $stmt->getStmt()->getSelectStmt();
-
- // Access FROM clause
- foreach ($select->getFromClause() as $from) {
- echo $from->getRangeVar()->getRelname();
- }
-
- // Access WHERE clause
- $where = $select->getWhereClause();
- // ...
-}
-```
-
-## Exception Handling
-
-```php
-getMessage();
-}
-
-try {
- // OFFSET without ORDER BY throws exception
- $query = pg_parse('SELECT * FROM users');
- $query->traverse(pg_pagination(10, 5));
-} catch (PaginationException $e) {
- echo "Pagination error: " . $e->getMessage();
- // "OFFSET without ORDER BY produces non-deterministic results"
-}
-```
-
-## Performance
-
-For optimal protobuf parsing performance, install the `ext-protobuf` PHP extension:
-
-```bash
-pecl install protobuf
-```
-
-The library works without it using the pure PHP implementation from `google/protobuf`, but the native extension provides significantly better performance.
diff --git a/documentation/components/libs/postgresql.md b/documentation/components/libs/postgresql.md
new file mode 100644
index 000000000..aa4512281
--- /dev/null
+++ b/documentation/components/libs/postgresql.md
@@ -0,0 +1,578 @@
+# PG Query
+
+- [⬅️️ Back](/documentation/introduction.md)
+- [📚API Reference](/documentation/api/lib/postgresql)
+- [📁Files](/documentation/api/lib/postgresql/indices/files.html)
+- [🗺DSL](/documentation/api/lib/postgresql/namespaces/flow-pgquery-dsl.html)
+
+[TOC]
+
+## Overview
+
+PG Query is a PostgreSQL query library with two main capabilities:
+
+1. **SQL Parser** - Parse, analyze, and modify existing PostgreSQL queries using the real PostgreSQL
+ parser ([libpg_query](https://github.com/pganalyze/libpg_query))
+2. **Query Builder** - Build new queries programmatically with a fluent, type-safe API
+
+Both features produce valid PostgreSQL syntax and can be combined - for example, parse an existing query, modify it, and
+convert it back to SQL.
+
+## Use Case Navigator
+
+| I want to... | Go to |
+|------------------------------------|-------------------------------------------|
+| Build SQL queries with type safety | [Query Builder](#query-builder) |
+| Parse and analyze existing SQL | [SQL Parser](#sql-parser) |
+| Add pagination to existing queries | [Query Modification](#query-modification) |
+| Traverse or modify AST directly | [Advanced Features](#advanced-features) |
+
+## Requirements
+
+This library requires the `pg_query` PHP extension.
+See [postgresql-ext documentation](/documentation/components/extensions/postgresql-ext.md) for installation instructions.
+
+## Installation
+
+```
+composer require flow-php/postgresql:~--FLOW_PHP_VERSION--
+```
+
+---
+
+## SQL Parser
+
+Parse, analyze, and transform existing PostgreSQL queries.
+
+### Quick Start
+
+```php
+all() as $table) {
+ echo $table->name(); // 'users', 'orders'
+ echo $table->alias(); // 'u', 'o'
+}
+
+// Get all columns
+foreach (sql_query_columns($query)->all() as $column) {
+ echo $column->name(); // 'id', 'name', 'id', 'user_id'
+ echo $column->table(); // 'u', 'u', 'u', 'o'
+}
+
+// Get columns for specific table
+$userColumns = sql_query_columns($query)->forTable('u');
+
+// Get all function calls
+foreach (sql_query_functions($query)->all() as $func) {
+ echo $func->name(); // function name
+ echo $func->schema(); // schema if qualified (e.g., 'pg_catalog')
+}
+```
+
+### Parsing Utilities
+
+```php
+indentSize(2) // 2 spaces per indent level
+ ->maxLineLength(60) // Wrap at 60 characters
+ ->trailingNewline() // Add newline at end
+ ->commasStartOfLine() // Place commas at line start
+);
+
+// Shorthand: parse and format in one step
+$formatted = sql_format('SELECT id,name FROM users WHERE active=true');
+```
+
+#### DeparseOptions
+
+| Method | Description | Default |
+|---------------------------|-------------------------------------|---------|
+| `prettyPrint(bool)` | Enable/disable pretty printing | `true` |
+| `indentSize(int)` | Spaces per indentation level | `4` |
+| `maxLineLength(int)` | Maximum line length before wrapping | `80` |
+| `trailingNewline(bool)` | Add trailing newline at end | `false` |
+| `commasStartOfLine(bool)` | Place commas at start of lines | `false` |
+
+---
+
+## Query Builder
+
+Build PostgreSQL queries programmatically with a fluent, type-safe API.
+
+### Quick Start
+
+```php
+from(table('users'))
+ ->where(eq(col('active'), literal(1)))
+ ->orderBy(asc(col('name')))
+ ->limit(10);
+
+// Convert to SQL string
+echo $query->toSQL();
+// SELECT id, name, email FROM users WHERE active = 1 ORDER BY name LIMIT 10
+```
+
+```php
+into('users')
+ ->columns('email', 'name')
+ ->values(param(1), param(2))
+ ->onConflictDoUpdate(
+ conflict_columns(['email']),
+ ['name' => col('excluded.name')]
+ )
+ ->returningAll();
+
+echo $query->toSQL();
+// INSERT INTO users (email, name) VALUES ($1, $2)
+// ON CONFLICT (email) DO UPDATE SET name = excluded.name RETURNING *
+```
+
+### Available Builders
+
+**Data Queries (DML)**
+
+- [Select Query Builder](/documentation/components/libs/postgresql/select-query-builder.md) - SELECT with JOINs, CTEs, window functions, subqueries
+- [Insert Query Builder](/documentation/components/libs/postgresql/insert-query-builder.md) - INSERT with ON CONFLICT (upsert), RETURNING
+- [Update Query Builder](/documentation/components/libs/postgresql/update-query-builder.md) - UPDATE with FROM clause, RETURNING
+- [Delete Query Builder](/documentation/components/libs/postgresql/delete-query-builder.md) - DELETE with USING clause, RETURNING
+- [Merge Query Builder](/documentation/components/libs/postgresql/merge-query-builder.md) - MERGE (SQL:2008 upsert)
+
+**Schema Management (DDL)**
+
+- [Table Query Builder](/documentation/components/libs/postgresql/table-query-builder.md) - CREATE/ALTER/DROP TABLE
+- [Index Query Builder](/documentation/components/libs/postgresql/index-query-builder.md) - CREATE/DROP INDEX
+- [View Query Builder](/documentation/components/libs/postgresql/view-query-builder.md) - CREATE/DROP VIEW, materialized views
+- [Sequence Query Builder](/documentation/components/libs/postgresql/sequence-query-builder.md) - CREATE/ALTER/DROP SEQUENCE
+- [Schema Query Builder](/documentation/components/libs/postgresql/schema-query-builder.md) - CREATE/DROP SCHEMA
+
+**Database Administration**
+
+- [Transaction Query Builder](/documentation/components/libs/postgresql/transaction-query-builder.md) - BEGIN, COMMIT, ROLLBACK, SAVEPOINT
+- [Role & Grant Query Builder](/documentation/components/libs/postgresql/role-grant-query-builder.md) - CREATE/ALTER ROLE, GRANT/REVOKE
+- [Utility Query Builder](/documentation/components/libs/postgresql/utility-query-builder.md) - VACUUM, ANALYZE, EXPLAIN, LOCK, CLUSTER
+
+**Extensions & Types**
+
+- [Copy Query Builder](/documentation/components/libs/postgresql/copy-query-builder.md) - COPY for bulk data import/export
+- [Trigger & Rule Query Builder](/documentation/components/libs/postgresql/trigger-rule-query-builder.md) - CREATE/DROP TRIGGER, RULE
+- [Function & Procedure Query Builder](/documentation/components/libs/postgresql/function-procedure-query-builder.md) - CREATE/DROP FUNCTION, PROCEDURE
+- [Extension Query Builder](/documentation/components/libs/postgresql/extension-query-builder.md) - CREATE/DROP EXTENSION
+- [Type Query Builder](/documentation/components/libs/postgresql/type-query-builder.md) - CREATE/DROP TYPE (enum, composite, range)
+- [Domain Query Builder](/documentation/components/libs/postgresql/domain-query-builder.md) - CREATE/DROP DOMAIN
+
+---
+
+## Query Modification
+
+Modify existing SQL queries programmatically - useful for adding pagination to queries.
+
+### Offset Pagination
+
+Add LIMIT/OFFSET pagination to any SELECT query:
+
+```php
+count++;
+ return null;
+ }
+
+ public function leave(object $node): ?int
+ {
+ return null;
+ }
+}
+
+$query = sql_parse('SELECT id, name, email FROM users');
+
+$counter = new ColumnCounter();
+$query->traverse($counter);
+
+echo $counter->count; // 3
+```
+
+#### NodeVisitor Interface
+
+```php
+interface NodeVisitor
+{
+ public const DONT_TRAVERSE_CHILDREN = 1;
+ public const STOP_TRAVERSAL = 2;
+
+ /** @return class-string */
+ public static function nodeClass(): string;
+
+ public function enter(object $node): ?int;
+ public function leave(object $node): ?int;
+}
+```
+
+Visitors declare which node type they handle via `nodeClass()`. Return values:
+
+- `null` - continue traversal
+- `DONT_TRAVERSE_CHILDREN` - skip children (from `enter()` only)
+- `STOP_TRAVERSAL` - stop entire traversal
+
+#### Built-in Visitors
+
+- `ColumnRefCollector` - collects all `ColumnRef` nodes
+- `FuncCallCollector` - collects all `FuncCall` nodes
+- `RangeVarCollector` - collects all `RangeVar` nodes
+
+### Custom Modifiers
+
+Create custom modifiers by implementing the `NodeModifier` interface:
+
+```php
+isTopLevel()) {
+ return null;
+ }
+
+ $node->setDistinctClause([new \Flow\PostgreSql\Protobuf\AST\Node()]);
+
+ return null;
+ }
+}
+
+$query = sql_parse('SELECT id, name FROM users');
+$query->traverse(new AddDistinctModifier());
+echo sql_deparse($query); // SELECT DISTINCT id, name FROM users
+```
+
+#### NodeModifier Interface
+
+```php
+interface NodeModifier
+{
+ /** @return class-string */
+ public static function nodeClass(): string;
+
+ public function modify(object $node, ModificationContext $context): int|object|null;
+}
+```
+
+The `ModificationContext` provides:
+
+- `$context->depth` - current traversal depth
+- `$context->ancestors` - array of parent nodes
+- `$context->getParent()` - immediate parent node
+- `$context->isTopLevel()` - whether this is the top-level statement
+
+Return values:
+
+- `null` - continue traversal
+- `Traverser::DONT_TRAVERSE_CHILDREN` - skip children
+- `Traverser::STOP_TRAVERSAL` - stop entire traversal
+- `object` - replace current node with returned object
+
+### Using Modifiers Directly
+
+For more control, you can use modifier objects directly with `traverse()`:
+
+```php
+traverse(new PaginationModifier(new PaginationConfig(limit: 10, offset: 20)));
+echo $query->deparse(); // SELECT * FROM users ORDER BY id LIMIT 10 OFFSET 20
+
+// Count modifier
+$query = sql_parse('SELECT * FROM users WHERE active = true ORDER BY name');
+$query->traverse(new CountModifier());
+echo $query->deparse(); // SELECT count(*) FROM (SELECT * FROM users WHERE active = true) _count_subq
+
+// Keyset pagination modifier
+$query = sql_parse('SELECT * FROM users ORDER BY created_at, id');
+$query->traverse(new KeysetPaginationModifier(new KeysetPaginationConfig(
+ limit: 10,
+ columns: [
+ new KeysetColumn('created_at', SortOrder::ASC),
+ new KeysetColumn('id', SortOrder::ASC),
+ ],
+ cursor: ['2025-01-15', 42]
+)));
+echo $query->deparse();
+// SELECT * FROM users WHERE created_at > $1 OR (created_at = $1 AND id > $2) ORDER BY created_at, id LIMIT 10
+```
+
+### Raw AST Access
+
+For full control, access the protobuf AST directly:
+
+```php
+raw()->getStmts() as $stmt) {
+ $select = $stmt->getStmt()->getSelectStmt();
+
+ // Access FROM clause
+ foreach ($select->getFromClause() as $from) {
+ echo $from->getRangeVar()->getRelname();
+ }
+
+ // Access WHERE clause
+ $where = $select->getWhereClause();
+ // ...
+}
+```
+
+---
+
+## Reference
+
+### Exception Handling
+
+```php
+getMessage();
+}
+
+try {
+ // OFFSET without ORDER BY throws exception
+ $query = sql_parse('SELECT * FROM users');
+ $query->traverse(new PaginationModifier(new PaginationConfig(limit: 10, offset: 5)));
+} catch (PaginationException $e) {
+ echo "Pagination error: " . $e->getMessage();
+ // "OFFSET without ORDER BY produces non-deterministic results"
+}
+```
+
+### Performance
+
+For optimal protobuf parsing performance, install the `ext-protobuf` PHP extension:
+
+```bash
+pecl install protobuf
+```
+
+The library works without it using the pure PHP implementation from `google/protobuf`, but the native extension provides
+significantly better performance.
diff --git a/documentation/components/libs/postgresql/copy-query-builder.md b/documentation/components/libs/postgresql/copy-query-builder.md
new file mode 100644
index 000000000..434ffb643
--- /dev/null
+++ b/documentation/components/libs/postgresql/copy-query-builder.md
@@ -0,0 +1,333 @@
+# Copy Query Builder
+
+- [⬅️ Back](/documentation/components/libs/postgresql.md)
+
+[TOC]
+
+The Copy Query Builder provides a fluent, type-safe interface for constructing PostgreSQL COPY statements. It supports both COPY TO (data export) and COPY FROM (data import) operations with files, programs, STDIN, and STDOUT.
+
+## COPY FROM (Data Import)
+
+### Basic COPY FROM
+
+```php
+from('users')
+ ->file('/tmp/users.csv');
+
+echo $query->toSQL();
+// COPY users FROM '/tmp/users.csv'
+```
+
+### COPY FROM with Columns
+
+```php
+from('users')
+ ->columns('id', 'name', 'email')
+ ->file('/tmp/users.csv');
+
+echo $query->toSQL();
+// COPY users(id, name, email) FROM '/tmp/users.csv'
+```
+
+### COPY FROM STDIN
+
+```php
+from('users')
+ ->stdin()
+ ->format(CopyFormat::CSV);
+
+echo $query->toSQL();
+// COPY users FROM STDIN WITH (format csv)
+```
+
+### COPY FROM PROGRAM
+
+```php
+from('logs')
+ ->program('gunzip -c /var/log/app.log.gz');
+
+echo $query->toSQL();
+// COPY logs FROM PROGRAM 'gunzip -c /var/log/app.log.gz'
+```
+
+### CSV Format with Options
+
+```php
+from('data')
+ ->file('/tmp/data.csv')
+ ->format(CopyFormat::CSV)
+ ->withHeader()
+ ->delimiter(';')
+ ->nullAs('NULL')
+ ->quote("'")
+ ->escape('\\')
+ ->encoding('UTF8');
+
+echo $query->toSQL();
+// COPY data FROM '/tmp/data.csv' WITH (format csv, delimiter ';', null 'NULL', header true, quote '''', escape '\\', encoding 'UTF8')
+```
+
+### Force Not Null
+
+Treat specified columns as non-nullable during import:
+
+```php
+from('users')
+ ->file('/tmp/users.csv')
+ ->format(CopyFormat::CSV)
+ ->forceNotNull('name', 'email');
+
+echo $query->toSQL();
+// COPY users FROM '/tmp/users.csv' WITH (format csv, force_not_null (name, email))
+```
+
+### Force Null
+
+Treat specified values as NULL for these columns:
+
+```php
+from('users')
+ ->file('/tmp/users.csv')
+ ->format(CopyFormat::CSV)
+ ->forceNull('description', 'notes');
+
+echo $query->toSQL();
+// COPY users FROM '/tmp/users.csv' WITH (format csv, force_null (description, notes))
+```
+
+### Error Handling
+
+Control behavior when encountering invalid data:
+
+```php
+from('events')
+ ->file('/tmp/events.csv')
+ ->onError(CopyOnError::IGNORE);
+
+echo $query->toSQL();
+// COPY events FROM '/tmp/events.csv' WITH (on_error 'ignore')
+```
+
+## COPY TO (Data Export)
+
+### Basic COPY TO
+
+```php
+to('users')
+ ->file('/tmp/users.csv');
+
+echo $query->toSQL();
+// COPY users TO '/tmp/users.csv'
+```
+
+### COPY TO with Columns
+
+```php
+to('users')
+ ->columns('id', 'name', 'email')
+ ->file('/tmp/users.csv');
+
+echo $query->toSQL();
+// COPY users(id, name, email) TO '/tmp/users.csv'
+```
+
+### COPY TO STDOUT
+
+```php
+to('users')
+ ->stdout()
+ ->format(CopyFormat::CSV);
+
+echo $query->toSQL();
+// COPY users TO STDOUT WITH (format csv)
+```
+
+### COPY TO PROGRAM
+
+```php
+to('logs')
+ ->program('gzip > /tmp/logs.csv.gz');
+
+echo $query->toSQL();
+// COPY logs TO PROGRAM 'gzip > /tmp/logs.csv.gz'
+```
+
+### COPY with SELECT Query
+
+Export results of a query instead of a table:
+
+```php
+select(col('id'), col('name'))
+ ->from(table('users'));
+
+$query = copy()
+ ->toQuery($selectQuery)
+ ->file('/tmp/active_users.csv')
+ ->format(CopyFormat::CSV);
+
+echo $query->toSQL();
+// COPY (SELECT id, name FROM users) TO '/tmp/active_users.csv' WITH (format csv)
+```
+
+### Binary Format
+
+```php
+to('data')
+ ->file('/tmp/data.bin')
+ ->format(CopyFormat::BINARY);
+
+echo $query->toSQL();
+// COPY data TO '/tmp/data.bin' WITH (format binary)
+```
+
+### Force Quote
+
+Quote specific columns or all columns in CSV output:
+
+```php
+to('products')
+ ->file('/tmp/products.csv')
+ ->format(CopyFormat::CSV)
+ ->forceQuote('name', 'description');
+
+echo $query->toSQL();
+// COPY products TO '/tmp/products.csv' WITH (format csv, force_quote (name, description))
+
+// Quote all columns
+$query = copy()
+ ->to('products')
+ ->file('/tmp/products.csv')
+ ->format(CopyFormat::CSV)
+ ->forceQuoteAll();
+
+echo $query->toSQL();
+// COPY products TO '/tmp/products.csv' WITH (format csv, force_quote *)
+```
+
+## Schema-Qualified Tables
+
+```php
+from('analytics.events')
+ ->file('/tmp/events.csv');
+
+echo $query->toSQL();
+// COPY analytics.events FROM '/tmp/events.csv'
+
+$query = copy()
+ ->to('analytics.events')
+ ->file('/tmp/events.csv');
+
+echo $query->toSQL();
+// COPY analytics.events TO '/tmp/events.csv'
+```
+
+## Copy Formats
+
+The `CopyFormat` enum provides three format options:
+
+| Format | Description |
+|--------|-------------|
+| `CopyFormat::TEXT` | Default PostgreSQL text format |
+| `CopyFormat::CSV` | Comma-separated values format |
+| `CopyFormat::BINARY` | PostgreSQL binary format |
+
+## Error Handling Options
+
+The `CopyOnError` enum (COPY FROM only) provides error handling options:
+
+| Option | Description |
+|--------|-------------|
+| `CopyOnError::STOP` | Stop on first error (default) |
+| `CopyOnError::IGNORE` | Skip rows with errors and continue |
+
+For a complete list of DSL functions, see the [DSL reference](/documentation/api/lib/postgresql/namespaces/flow-postgresql-dsl.html).
diff --git a/documentation/components/libs/postgresql/delete-query-builder.md b/documentation/components/libs/postgresql/delete-query-builder.md
new file mode 100644
index 000000000..0bc6046b2
--- /dev/null
+++ b/documentation/components/libs/postgresql/delete-query-builder.md
@@ -0,0 +1,145 @@
+# Delete Query Builder
+
+- [⬅️ Back](/documentation/components/libs/postgresql.md)
+
+[TOC]
+
+The Delete Query Builder provides a fluent, type-safe interface for constructing PostgreSQL DELETE queries. It supports simple deletes, deletes with USING clause (join-like behavior), complex WHERE conditions, and RETURNING clauses.
+
+## Simple Delete
+
+```php
+from('users')
+ ->where(eq(col('id'), literal(1)));
+
+echo $query->toSQL();
+// DELETE FROM users WHERE id = 1
+```
+
+## Delete with Parameters
+
+Use positional parameters for prepared statements:
+
+```php
+from('users')
+ ->where(eq(col('id'), param(1)));
+
+echo $query->toSQL();
+// DELETE FROM users WHERE id = $1
+```
+
+## Delete with Table Alias
+
+```php
+from('users', 'u')
+ ->where(eq(col('u.id'), literal(1)));
+
+echo $query->toSQL();
+// DELETE FROM users u WHERE u.id = 1
+```
+
+## Delete with USING Clause (Join-like)
+
+The USING clause allows you to reference other tables in your DELETE, similar to a JOIN:
+
+```php
+from('orders')
+ ->using(table('users'))
+ ->where(eq(col('orders.user_id'), col('users.id')));
+
+echo $query->toSQL();
+// DELETE FROM orders USING users WHERE orders.user_id = users.id
+```
+
+## Delete with Subquery in WHERE
+
+```php
+select(col('user_id'))
+ ->from(table('inactive_users'));
+
+$query = delete()
+ ->from('users')
+ ->where(any_sub_select(col('id'), ComparisonOperator::EQ, $subquery));
+
+echo $query->toSQL();
+// DELETE FROM users WHERE id = ANY (SELECT user_id FROM inactive_users)
+```
+
+## RETURNING Clause
+
+```php
+from('users')
+ ->where(eq(col('id'), literal(1)))
+ ->returning(col('id'), col('name'));
+
+echo $query->toSQL();
+// DELETE FROM users WHERE id = 1 RETURNING id, name
+
+// Return all columns
+$query = delete()
+ ->from('users')
+ ->where(eq(col('id'), literal(1)))
+ ->returningAll();
+
+echo $query->toSQL();
+// DELETE FROM users WHERE id = 1 RETURNING *
+```
+
+## Complex WHERE Conditions
+
+```php
+from('sessions')
+ ->where(
+ cond_and(
+ eq(col('active'), literal(false)),
+ lt(col('expires_at'), literal('2024-01-01'))
+ )
+ );
+
+echo $query->toSQL();
+// DELETE FROM sessions WHERE active = false AND expires_at < '2024-01-01'
+```
+
+For a complete list of DSL functions, see the [DSL reference](/documentation/api/lib/postgresql/namespaces/flow-postgresql-dsl.html).
diff --git a/documentation/components/libs/postgresql/domain-query-builder.md b/documentation/components/libs/postgresql/domain-query-builder.md
new file mode 100644
index 000000000..1e10ba357
--- /dev/null
+++ b/documentation/components/libs/postgresql/domain-query-builder.md
@@ -0,0 +1,379 @@
+# Domain Query Builder
+
+- [Back](/documentation/components/libs/postgresql.md)
+
+[TOC]
+
+The Domain Query Builder provides a fluent, type-safe interface for constructing PostgreSQL domain management statements:
+CREATE DOMAIN, ALTER DOMAIN, and DROP DOMAIN.
+
+Domains are user-defined data types with optional constraints. They are useful for defining reusable data types with specific validation rules.
+
+## CREATE DOMAIN
+
+### Basic Domain Creation
+
+```php
+domain('email')
+ ->as('text');
+
+echo $query->toSQL();
+// CREATE DOMAIN email AS text
+```
+
+### With Schema
+
+```php
+domain('public.email')
+ ->as('text');
+
+echo $query->toSQL();
+// CREATE DOMAIN public.email AS text
+```
+
+### NOT NULL
+
+```php
+domain('email')
+ ->as('text')
+ ->notNull();
+
+echo $query->toSQL();
+// CREATE DOMAIN email AS text NOT NULL
+```
+
+### NULL
+
+Explicitly allow NULL values:
+
+```php
+domain('email')
+ ->as('text')
+ ->null();
+
+echo $query->toSQL();
+// CREATE DOMAIN email AS text NULL
+```
+
+### DEFAULT
+
+Set a default value:
+
+```php
+domain('email')
+ ->as('text')
+ ->default("'default@example.com'");
+
+echo $query->toSQL();
+// CREATE DOMAIN email AS text DEFAULT 'default@example.com'
+```
+
+### CHECK Constraint
+
+Add a CHECK constraint:
+
+```php
+domain('positive_int')
+ ->as('int4')
+ ->check('VALUE > 0');
+
+echo $query->toSQL();
+// CREATE DOMAIN positive_int AS int4 CHECK (value > 0)
+```
+
+### Named Constraint
+
+Add a named CHECK constraint:
+
+```php
+domain('positive_int')
+ ->as('int4')
+ ->constraint('positive_check')
+ ->check('VALUE > 0');
+
+echo $query->toSQL();
+// CREATE DOMAIN positive_int AS int4 CONSTRAINT positive_check CHECK (value > 0)
+```
+
+### COLLATE
+
+Specify a collation:
+
+```php
+domain('email')
+ ->as('text')
+ ->collate('en_US');
+
+echo $query->toSQL();
+// CREATE DOMAIN email AS text COLLATE "en_US"
+```
+
+### Multiple Constraints
+
+```php
+domain('email')
+ ->as('text')
+ ->notNull()
+ ->check("VALUE ~ '^.+@.+$'");
+
+echo $query->toSQL();
+// CREATE DOMAIN email AS text NOT NULL CHECK (value ~ '^.+@.+$')
+```
+
+## ALTER DOMAIN
+
+### SET NOT NULL
+
+```php
+domain('email')
+ ->setNotNull();
+
+echo $query->toSQL();
+// ALTER DOMAIN email SET NOT NULL
+```
+
+### DROP NOT NULL
+
+```php
+domain('email')
+ ->dropNotNull();
+
+echo $query->toSQL();
+// ALTER DOMAIN email DROP NOT NULL
+```
+
+### SET DEFAULT
+
+```php
+domain('email')
+ ->setDefault("'default@example.com'");
+
+echo $query->toSQL();
+// ALTER DOMAIN email SET DEFAULT 'default@example.com'
+```
+
+### DROP DEFAULT
+
+```php
+domain('email')
+ ->dropDefault();
+
+echo $query->toSQL();
+// ALTER DOMAIN email DROP DEFAULT
+```
+
+### ADD CONSTRAINT
+
+```php
+domain('email')
+ ->addConstraint('valid_email', "VALUE ~ '^.+@.+$'");
+
+echo $query->toSQL();
+// ALTER DOMAIN email ADD CONSTRAINT valid_email CHECK (value ~ '^.+@.+$')
+```
+
+### DROP CONSTRAINT
+
+```php
+domain('email')
+ ->dropConstraint('valid_email');
+
+echo $query->toSQL();
+// ALTER DOMAIN email DROP CONSTRAINT valid_email
+```
+
+### DROP CONSTRAINT CASCADE
+
+```php
+domain('email')
+ ->dropConstraint('valid_email')
+ ->cascade();
+
+echo $query->toSQL();
+// ALTER DOMAIN email DROP CONSTRAINT valid_email CASCADE
+```
+
+### VALIDATE CONSTRAINT
+
+Validate an existing constraint:
+
+```php
+domain('email')
+ ->validateConstraint('valid_email');
+
+echo $query->toSQL();
+// ALTER DOMAIN email VALIDATE CONSTRAINT valid_email
+```
+
+### With Schema
+
+```php
+domain('public.email')
+ ->setNotNull();
+
+echo $query->toSQL();
+// ALTER DOMAIN public.email SET NOT NULL
+```
+
+## DROP DOMAIN
+
+### Simple Drop
+
+```php
+domain('email');
+
+echo $query->toSQL();
+// DROP DOMAIN email
+```
+
+### IF EXISTS
+
+```php
+domain('email')
+ ->ifExists();
+
+echo $query->toSQL();
+// DROP DOMAIN IF EXISTS email
+```
+
+### CASCADE
+
+Drop all objects that depend on the domain:
+
+```php
+domain('email')
+ ->cascade();
+
+echo $query->toSQL();
+// DROP DOMAIN email CASCADE
+```
+
+### RESTRICT
+
+Refuse to drop the domain if any objects depend on it (default behavior):
+
+```php
+domain('email')
+ ->restrict();
+
+echo $query->toSQL();
+// DROP DOMAIN email
+```
+
+### Multiple Domains
+
+```php
+domain('email', 'phone', 'url');
+
+echo $query->toSQL();
+// DROP DOMAIN email, phone, url
+```
+
+### Combined Options
+
+```php
+domain('email')
+ ->ifExists()
+ ->cascade();
+
+echo $query->toSQL();
+// DROP DOMAIN IF EXISTS email CASCADE
+```
+
+For a complete list of DSL functions, see the [DSL reference](/documentation/api/lib/postgresql/namespaces/flow-postgresql-dsl.html).
diff --git a/documentation/components/libs/postgresql/extension-query-builder.md b/documentation/components/libs/postgresql/extension-query-builder.md
new file mode 100644
index 000000000..f37ef339d
--- /dev/null
+++ b/documentation/components/libs/postgresql/extension-query-builder.md
@@ -0,0 +1,291 @@
+# Extension Query Builder
+
+- [Back](/documentation/components/libs/postgresql.md)
+
+[TOC]
+
+The Extension Query Builder provides a fluent, type-safe interface for constructing PostgreSQL extension management statements:
+CREATE EXTENSION, ALTER EXTENSION, and DROP EXTENSION.
+
+## CREATE EXTENSION
+
+### Basic Extension Creation
+
+```php
+extension('uuid-ossp');
+
+echo $query->toSQL();
+// CREATE EXTENSION "uuid-ossp"
+```
+
+### IF NOT EXISTS
+
+```php
+extension('uuid-ossp')
+ ->ifNotExists();
+
+echo $query->toSQL();
+// CREATE EXTENSION IF NOT EXISTS "uuid-ossp"
+```
+
+### With Schema
+
+Install the extension's objects in a specific schema:
+
+```php
+extension('uuid-ossp')
+ ->schema('public');
+
+echo $query->toSQL();
+// CREATE EXTENSION "uuid-ossp" SCHEMA public
+```
+
+### With Version
+
+Install a specific version of the extension:
+
+```php
+extension('postgis')
+ ->version('3.0');
+
+echo $query->toSQL();
+// CREATE EXTENSION postgis VERSION "3.0"
+```
+
+### CASCADE
+
+Automatically install any extensions that this extension depends on:
+
+```php
+extension('postgis_raster')
+ ->cascade();
+
+echo $query->toSQL();
+// CREATE EXTENSION postgis_raster CASCADE
+```
+
+### Complete Example
+
+```php
+extension('postgis')
+ ->ifNotExists()
+ ->schema('extensions')
+ ->version('3.0')
+ ->cascade();
+
+echo $query->toSQL();
+// CREATE EXTENSION IF NOT EXISTS postgis SCHEMA extensions VERSION "3.0" CASCADE
+```
+
+## ALTER EXTENSION
+
+### Update Extension
+
+Update to the latest version:
+
+```php
+extension('postgis')
+ ->update();
+
+echo $query->toSQL();
+// ALTER EXTENSION postgis UPDATE
+```
+
+### Update to Specific Version
+
+```php
+extension('postgis')
+ ->updateTo('3.0');
+
+echo $query->toSQL();
+// ALTER EXTENSION postgis UPDATE TO "3.0"
+```
+
+### Set Schema
+
+Move extension objects to a different schema:
+
+```php
+extension('uuid-ossp')
+ ->setSchema('public');
+
+echo $query->toSQL();
+// ALTER EXTENSION "uuid-ossp" SET SCHEMA public
+```
+
+### Add Objects to Extension
+
+Add a function to an extension:
+
+```php
+extension('my_extension')
+ ->addFunction('my_func', ['integer', 'text']);
+
+echo $query->toSQL();
+// ALTER EXTENSION my_extension ADD FUNCTION my_func("integer", text)
+```
+
+Add a table to an extension:
+
+```php
+extension('my_extension')
+ ->addTable('my_table');
+
+echo $query->toSQL();
+// ALTER EXTENSION my_extension ADD TABLE my_table
+```
+
+### Drop Objects from Extension
+
+```php
+extension('my_extension')
+ ->dropFunction('my_func', ['integer']);
+
+echo $query->toSQL();
+// ALTER EXTENSION my_extension DROP FUNCTION my_func("integer")
+
+$query = alter()->extension('my_extension')
+ ->dropTable('my_table');
+
+echo $query->toSQL();
+// ALTER EXTENSION my_extension DROP TABLE my_table
+```
+
+## DROP EXTENSION
+
+### Simple Drop
+
+```php
+extension('uuid-ossp');
+
+echo $query->toSQL();
+// DROP EXTENSION "uuid-ossp"
+```
+
+### IF EXISTS
+
+```php
+extension('uuid-ossp')
+ ->ifExists();
+
+echo $query->toSQL();
+// DROP EXTENSION IF EXISTS "uuid-ossp"
+```
+
+### CASCADE
+
+Drop all objects that depend on the extension:
+
+```php
+extension('postgis')
+ ->cascade();
+
+echo $query->toSQL();
+// DROP EXTENSION postgis CASCADE
+```
+
+### RESTRICT
+
+Refuse to drop the extension if any objects depend on it (default behavior):
+
+```php
+extension('uuid-ossp')
+ ->restrict();
+
+echo $query->toSQL();
+// DROP EXTENSION "uuid-ossp"
+```
+
+### Multiple Extensions
+
+```php
+extension('postgis', 'postgis_raster', 'postgis_topology');
+
+echo $query->toSQL();
+// DROP EXTENSION postgis, postgis_raster, postgis_topology
+```
+
+### Combined Options
+
+```php
+extension('postgis')
+ ->ifExists()
+ ->cascade();
+
+echo $query->toSQL();
+// DROP EXTENSION IF EXISTS postgis CASCADE
+```
+
+For a complete list of DSL functions, see the [DSL reference](/documentation/api/lib/postgresql/namespaces/flow-postgresql-dsl.html).
diff --git a/documentation/components/libs/postgresql/function-procedure-query-builder.md b/documentation/components/libs/postgresql/function-procedure-query-builder.md
new file mode 100644
index 000000000..ac5fa4e03
--- /dev/null
+++ b/documentation/components/libs/postgresql/function-procedure-query-builder.md
@@ -0,0 +1,689 @@
+# Function and Procedure Query Builder
+
+- [Back](/documentation/components/libs/postgresql.md)
+
+[TOC]
+
+The Function and Procedure Query Builder provides a fluent, type-safe interface for constructing PostgreSQL function and procedure management statements:
+CREATE FUNCTION, CREATE PROCEDURE, ALTER FUNCTION, ALTER PROCEDURE, DROP FUNCTION, DROP PROCEDURE, CALL, and DO.
+
+## CREATE FUNCTION
+
+### Basic Function Creation
+
+```php
+function('add_numbers')
+ ->arguments(func_arg('integer')->named('a'), func_arg('integer')->named('b'))
+ ->returns('integer')
+ ->language('sql')
+ ->as('SELECT a + b');
+
+echo $query->toSQL();
+// CREATE FUNCTION add_numbers(IN a "integer", IN b "integer") RETURNS "integer" LANGUAGE sql AS $$SELECT a + b$$
+```
+
+### PL/pgSQL Function
+
+```php
+function('increment')
+ ->arguments(func_arg('integer')->named('val'))
+ ->returns('integer')
+ ->language('plpgsql')
+ ->as('BEGIN RETURN val + 1; END;');
+
+echo $query->toSQL();
+// CREATE FUNCTION increment(IN val "integer") RETURNS "integer" LANGUAGE plpgsql AS $$BEGIN RETURN val + 1; END;$$
+```
+
+### OR REPLACE
+
+```php
+function('my_func')
+ ->orReplace()
+ ->returns('integer')
+ ->language('sql')
+ ->as('SELECT 1');
+
+echo $query->toSQL();
+// CREATE OR REPLACE FUNCTION my_func() RETURNS "integer" LANGUAGE sql AS $$SELECT 1$$
+```
+
+### RETURNS TABLE
+
+Create a function that returns a table:
+
+```php
+function('get_users')
+ ->returnsTable(['id' => 'integer', 'name' => 'text'])
+ ->language('sql')
+ ->as('SELECT id, name FROM users');
+
+echo $query->toSQL();
+// CREATE FUNCTION get_users() RETURNS TABLE (id "integer", name text) LANGUAGE sql AS $$SELECT id, name FROM users$$
+```
+
+### RETURNS SETOF
+
+Create a function that returns a set of values:
+
+```php
+function('get_user_ids')
+ ->returnsSetOf('integer')
+ ->language('sql')
+ ->as('SELECT id FROM users');
+
+echo $query->toSQL();
+// CREATE FUNCTION get_user_ids() RETURNS SETOF "integer" LANGUAGE sql AS $$SELECT id FROM users$$
+```
+
+### RETURNS VOID
+
+Create a function that returns nothing:
+
+```php
+function('log_event')
+ ->returnsVoid()
+ ->language('sql')
+ ->as('INSERT INTO logs (msg) VALUES (current_timestamp)');
+
+echo $query->toSQL();
+// CREATE FUNCTION log_event() RETURNS void LANGUAGE sql AS $$INSERT INTO logs (msg) VALUES (current_timestamp)$$
+```
+
+### Volatility (IMMUTABLE, STABLE, VOLATILE)
+
+```php
+function('double')
+ ->arguments(func_arg('integer')->named('x'))
+ ->returns('integer')
+ ->language('sql')
+ ->immutable()
+ ->as('SELECT x * 2');
+
+// STABLE - returns same result within a single statement
+$query = create()->function('get_config')
+ ->returns('text')
+ ->language('sql')
+ ->stable()
+ ->as('SELECT current_setting(\'app.name\')');
+
+// VOLATILE (default) - can return different results on successive calls
+$query = create()->function('get_time')
+ ->returns('timestamp')
+ ->language('sql')
+ ->volatile()
+ ->as('SELECT now()');
+```
+
+### PARALLEL Safety
+
+```php
+function('compute')
+ ->arguments(func_arg('integer')->named('x'))
+ ->returns('integer')
+ ->language('sql')
+ ->parallel(ParallelSafety::SAFE)
+ ->as('SELECT x * 2');
+
+// Available options:
+// ParallelSafety::UNSAFE - cannot be executed in parallel mode
+// ParallelSafety::RESTRICTED - can be executed in parallel but only in group leader
+// ParallelSafety::SAFE - can be executed in parallel in any process
+```
+
+### STRICT (RETURNS NULL ON NULL INPUT)
+
+```php
+function('safe_add')
+ ->arguments(func_arg('integer')->named('a'), func_arg('integer')->named('b'))
+ ->returns('integer')
+ ->language('sql')
+ ->strict() // Returns NULL if any input is NULL
+ ->as('SELECT a + b');
+
+// Or explicitly call on NULL input
+$query = create()->function('nullable_add')
+ ->arguments(func_arg('integer')->named('a'), func_arg('integer')->named('b'))
+ ->returns('integer')
+ ->language('sql')
+ ->calledOnNullInput() // Function is called even with NULL inputs
+ ->as('SELECT COALESCE(a, 0) + COALESCE(b, 0)');
+```
+
+### SECURITY DEFINER / SECURITY INVOKER
+
+```php
+function('admin_only')
+ ->returns('void')
+ ->language('sql')
+ ->securityDefiner()
+ ->as('SELECT 1');
+
+// Function runs with the privileges of the caller (default)
+$query = create()->function('normal_func')
+ ->returns('void')
+ ->language('sql')
+ ->securityInvoker()
+ ->as('SELECT 1');
+```
+
+### COST and ROWS
+
+```php
+function('expensive_func')
+ ->returns('integer')
+ ->language('sql')
+ ->cost(1000) // Estimated execution cost
+ ->as('SELECT 1');
+
+$query = create()->function('many_rows')
+ ->returnsSetOf('integer')
+ ->language('sql')
+ ->rows(10000) // Estimated number of rows returned
+ ->as('SELECT generate_series(1, 10000)');
+```
+
+### LEAKPROOF
+
+```php
+function('no_side_effects')
+ ->returns('boolean')
+ ->language('sql')
+ ->leakproof() // Function has no side effects
+ ->as('SELECT true');
+```
+
+### SET Configuration
+
+```php
+function('my_func')
+ ->returns('void')
+ ->language('sql')
+ ->set('search_path', 'public')
+ ->as('SELECT 1');
+```
+
+### Function Arguments
+
+The `func_arg()` DSL function creates function arguments with various options:
+
+```php
+named('user_id');
+
+// With default value
+$arg = func_arg('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
+```
+
+### Complete Example
+
+```php
+function('calculate_discount')
+ ->orReplace()
+ ->arguments(
+ func_arg('numeric')->named('price'),
+ func_arg('numeric')->named('discount_percent')->default('10')
+ )
+ ->returns('numeric')
+ ->language('sql')
+ ->immutable()
+ ->parallel(ParallelSafety::SAFE)
+ ->strict()
+ ->as('SELECT price - (price * discount_percent / 100)');
+```
+
+## CREATE PROCEDURE
+
+### Basic Procedure Creation
+
+```php
+procedure('update_stats')
+ ->arguments(func_arg('integer')->named('user_id'))
+ ->language('plpgsql')
+ ->as('BEGIN UPDATE stats SET count = count + 1 WHERE id = user_id; END;');
+
+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;$$
+```
+
+### OR REPLACE
+
+```php
+procedure('my_proc')
+ ->orReplace()
+ ->language('sql')
+ ->as('SELECT 1');
+
+echo $query->toSQL();
+// CREATE OR REPLACE PROCEDURE my_proc() LANGUAGE sql AS $$SELECT 1$$
+```
+
+### SECURITY DEFINER / SECURITY INVOKER
+
+```php
+procedure('admin_proc')
+ ->language('sql')
+ ->securityDefiner()
+ ->as('DELETE FROM temp_data');
+```
+
+### SET Configuration
+
+```php
+procedure('my_proc')
+ ->language('sql')
+ ->set('work_mem', '1GB')
+ ->as('SELECT 1');
+```
+
+## ALTER FUNCTION
+
+### Change Volatility
+
+```php
+function('my_func')
+ ->arguments(func_arg('integer'))
+ ->immutable();
+
+echo $query->toSQL();
+// ALTER FUNCTION my_func("integer") IMMUTABLE
+```
+
+### Change Parallel Safety
+
+```php
+function('my_func')
+ ->arguments(func_arg('integer'))
+ ->parallel(ParallelSafety::SAFE);
+
+echo $query->toSQL();
+// ALTER FUNCTION my_func("integer") PARALLEL safe
+```
+
+### RENAME TO
+
+```php
+function('old_name')
+ ->arguments(func_arg('text'))
+ ->renameTo('new_name');
+
+echo $query->toSQL();
+// ALTER FUNCTION old_name(text) RENAME TO new_name
+```
+
+### Change COST and ROWS
+
+```php
+function('my_func')
+ ->arguments(func_arg('integer'))
+ ->cost(500);
+
+$query = alter()->function('set_returning_func')
+ ->rows(1000);
+```
+
+### SET and RESET Configuration
+
+```php
+function('my_func')
+ ->set('search_path', 'public');
+
+// Reset a configuration parameter
+$query = alter()->function('my_func')
+ ->reset('search_path');
+
+// Reset all configuration parameters
+$query = alter()->function('my_func')
+ ->resetAll();
+```
+
+## ALTER PROCEDURE
+
+### RENAME TO
+
+```php
+procedure('old_proc')
+ ->arguments(func_arg('integer'))
+ ->renameTo('new_proc');
+
+echo $query->toSQL();
+// ALTER PROCEDURE old_proc("integer") RENAME TO new_proc
+```
+
+### SECURITY DEFINER / SECURITY INVOKER
+
+```php
+procedure('my_proc')
+ ->securityDefiner();
+
+echo $query->toSQL();
+// ALTER PROCEDURE my_proc SECURITY DEFINER
+```
+
+### SET and RESET Configuration
+
+```php
+procedure('my_proc')
+ ->set('work_mem', '2GB');
+
+$query = alter()->procedure('my_proc')
+ ->reset('work_mem');
+
+$query = alter()->procedure('my_proc')
+ ->resetAll();
+```
+
+## DROP FUNCTION
+
+### Simple Drop
+
+```php
+function('my_func');
+
+echo $query->toSQL();
+// DROP FUNCTION my_func
+```
+
+### With Argument Types
+
+```php
+function('my_func')
+ ->arguments(func_arg('integer'), func_arg('text'));
+
+echo $query->toSQL();
+// DROP FUNCTION my_func("integer", text)
+```
+
+### IF EXISTS
+
+```php
+function('my_func')
+ ->ifExists()
+ ->arguments(func_arg('integer'));
+
+echo $query->toSQL();
+// DROP FUNCTION IF EXISTS my_func("integer")
+```
+
+### CASCADE
+
+```php
+function('my_func')
+ ->ifExists()
+ ->arguments(func_arg('integer'), func_arg('text'))
+ ->cascade();
+
+echo $query->toSQL();
+// DROP FUNCTION IF EXISTS my_func("integer", text) CASCADE
+```
+
+### RESTRICT
+
+```php
+function('my_func')
+ ->restrict();
+
+echo $query->toSQL();
+// DROP FUNCTION my_func RESTRICT
+```
+
+## DROP PROCEDURE
+
+### Simple Drop
+
+```php
+procedure('my_proc');
+
+echo $query->toSQL();
+// DROP PROCEDURE my_proc
+```
+
+### With Options
+
+```php
+procedure('my_proc')
+ ->ifExists()
+ ->arguments(func_arg('integer'))
+ ->cascade();
+
+echo $query->toSQL();
+// DROP PROCEDURE IF EXISTS my_proc("integer") CASCADE
+```
+
+## CALL (Procedure Invocation)
+
+### Simple Call
+
+```php
+toSQL();
+// CALL update_stats()
+```
+
+### With Arguments
+
+```php
+with(123, 'test');
+
+echo $query->toSQL();
+// CALL update_stats(123, 'test')
+```
+
+Arguments can be integers, strings, floats, booleans, or null:
+
+```php
+with(42, 'hello', 3.14, true, null);
+
+echo $query->toSQL();
+// CALL process_data(42, 'hello', 3.14, true, NULL)
+```
+
+## DO (Anonymous Code Block)
+
+### Basic DO Block
+
+```php
+toSQL();
+// DO $outer$BEGIN RAISE NOTICE $$Hello$$; END;$outer$ LANGUAGE plpgsql
+```
+
+### With Language
+
+```php
+language('sql');
+
+echo $query->toSQL();
+// DO $$SELECT 1$$ LANGUAGE sql
+```
+
+## DSL Functions Reference
+
+| Function | Description |
+|----------|-------------|
+| `func_arg(string $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 |
+| `alter()->procedure(string $name)` | Alter an existing procedure |
+| `drop()->function(string $name)` | Drop a function |
+| `drop()->procedure(string $name)` | Drop a procedure |
+| `call(string $procedure)` | Call a procedure |
+| `do_block(string $code)` | Execute an anonymous code block |
+
+For a complete list of DSL functions, see the [DSL reference](/documentation/api/lib/postgresql/namespaces/flow-postgresql-dsl.html).
diff --git a/documentation/components/libs/postgresql/index-query-builder.md b/documentation/components/libs/postgresql/index-query-builder.md
new file mode 100644
index 000000000..f88bd718c
--- /dev/null
+++ b/documentation/components/libs/postgresql/index-query-builder.md
@@ -0,0 +1,642 @@
+# Index Query Builder
+
+- [⬅️ Back](/documentation/components/libs/postgresql.md)
+
+[TOC]
+
+The Index Query Builder provides a fluent, type-safe interface for constructing PostgreSQL index management statements:
+CREATE INDEX, DROP INDEX, REINDEX, and ALTER INDEX.
+
+## CREATE INDEX
+
+### Basic Index Creation
+
+```php
+index('idx_users_email')
+ ->on('users')
+ ->columns('email');
+
+echo $query->toSQL();
+// CREATE INDEX idx_users_email ON users (email)
+```
+
+### Unique Index
+
+```php
+index('idx_users_email')
+ ->unique()
+ ->on('users')
+ ->columns('email');
+
+echo $query->toSQL();
+// CREATE UNIQUE INDEX idx_users_email ON users (email)
+```
+
+### IF NOT EXISTS
+
+```php
+index('idx_users_email')
+ ->ifNotExists()
+ ->on('users')
+ ->columns('email');
+
+echo $query->toSQL();
+// CREATE INDEX IF NOT EXISTS idx_users_email ON users (email)
+```
+
+### CONCURRENTLY
+
+Create an index without locking out concurrent inserts, updates, or deletes:
+
+```php
+index('idx_users_email')
+ ->concurrently()
+ ->on('users')
+ ->columns('email');
+
+echo $query->toSQL();
+// CREATE INDEX CONCURRENTLY idx_users_email ON users (email)
+```
+
+### Combined Modifiers
+
+```php
+index('idx_users_email')
+ ->unique()
+ ->concurrently()
+ ->ifNotExists()
+ ->on('users')
+ ->columns('email');
+
+echo $query->toSQL();
+// CREATE UNIQUE INDEX CONCURRENTLY IF NOT EXISTS idx_users_email ON users (email)
+```
+
+### Index with Schema
+
+```php
+index('idx_users_email')
+ ->on('users', 'public')
+ ->columns('email');
+
+echo $query->toSQL();
+// CREATE INDEX idx_users_email ON public.users (email)
+```
+
+### Index Access Methods
+
+PostgreSQL supports different index access methods. Use the `using()` method with an `IndexMethod`:
+
+```php
+index('idx_users_email')
+ ->on('users')
+ ->using(index_method_btree())
+ ->columns('email');
+
+// Hash (good for equality comparisons only)
+$query = create()->index('idx_users_email')
+ ->on('users')
+ ->using(index_method_hash())
+ ->columns('email');
+
+// GIN (good for array values, full-text search, jsonb)
+$query = create()->index('idx_documents_content')
+ ->on('documents')
+ ->using(index_method_gin())
+ ->columns('content');
+
+// GiST (good for geometric data, full-text search)
+$query = create()->index('idx_locations_point')
+ ->on('locations')
+ ->using(index_method_gist())
+ ->columns('point');
+
+// SP-GiST (good for non-balanced data like phone numbers)
+$query = create()->index('idx_users_phone')
+ ->on('users')
+ ->using(index_method_spgist())
+ ->columns('phone');
+
+// BRIN (good for large tables with naturally ordered data)
+$query = create()->index('idx_events_timestamp')
+ ->on('events')
+ ->using(index_method_brin())
+ ->columns('created_at');
+```
+
+### Multiple Columns
+
+```php
+index('idx_users_name_email')
+ ->on('users')
+ ->columns('name', 'email');
+
+echo $query->toSQL();
+// CREATE INDEX idx_users_name_email ON users (name, email)
+```
+
+### Column Sort Order
+
+Use `index_col()` to customize column ordering:
+
+```php
+index('idx_users_created_at')
+ ->on('users')
+ ->columns(index_col('created_at')->desc());
+
+echo $query->toSQL();
+// CREATE INDEX idx_users_created_at ON users (created_at DESC)
+
+// With NULLS ordering
+$query = create()->index('idx_users_created_at')
+ ->on('users')
+ ->columns(index_col('created_at')->desc()->nullsFirst());
+
+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();
+// CREATE INDEX idx_users_created_at ON users (created_at NULLS LAST)
+```
+
+### Operator Class
+
+Specify an operator class for index columns:
+
+```php
+index('idx_users_name_pattern')
+ ->on('users')
+ ->columns(index_col('name')->opclass('text_pattern_ops'));
+
+echo $query->toSQL();
+// CREATE INDEX idx_users_name_pattern ON users (name text_pattern_ops)
+```
+
+### Collation
+
+Specify a collation for index columns:
+
+```php
+index('idx_users_name')
+ ->on('users')
+ ->columns(index_col('name')->collate('en_US'));
+```
+
+### Expression Index
+
+Create an index on an expression:
+
+```php
+index('idx_users_lower_email')
+ ->on('users')
+ ->columns(index_expr(new RawExpression('lower(email)')));
+
+echo $query->toSQL();
+// CREATE INDEX idx_users_lower_email ON users ((lower(email)))
+```
+
+### Covering Index (INCLUDE)
+
+Include additional columns in the index for index-only scans:
+
+```php
+index('idx_users_email')
+ ->on('users')
+ ->columns('email')
+ ->include('name', 'created_at');
+
+echo $query->toSQL();
+// CREATE INDEX idx_users_email ON users (email) INCLUDE (name, created_at)
+```
+
+### Partial Index (WHERE)
+
+Create an index on a subset of rows:
+
+```php
+index('idx_users_active_email')
+ ->on('users')
+ ->columns('email')
+ ->where(eq(col('active'), literal(true)));
+
+echo $query->toSQL();
+// CREATE INDEX idx_users_active_email ON users (email) WHERE active = true
+```
+
+### Tablespace
+
+Specify a tablespace for the index:
+
+```php
+index('idx_users_email')
+ ->on('users')
+ ->columns('email')
+ ->tablespace('fast_storage');
+
+echo $query->toSQL();
+// CREATE INDEX idx_users_email ON users (email) TABLESPACE fast_storage
+```
+
+### NULLS NOT DISTINCT
+
+For unique indexes, treat NULL values as not distinct:
+
+```php
+index('idx_users_email')
+ ->unique()
+ ->on('users')
+ ->columns('email')
+ ->nullsNotDistinct();
+
+echo $query->toSQL();
+// CREATE UNIQUE INDEX idx_users_email ON users (email) NULLS NOT DISTINCT
+```
+
+### ON ONLY (Partitioned Tables)
+
+Create an index on only the specified table, not including child partitions:
+
+```php
+index('idx_users_email')
+ ->onOnly('users')
+ ->columns('email');
+
+echo $query->toSQL();
+// CREATE INDEX idx_users_email ON ONLY users (email)
+```
+
+## DROP INDEX
+
+### Simple Drop
+
+```php
+index('idx_users_email');
+
+echo $query->toSQL();
+// DROP INDEX idx_users_email
+```
+
+### IF EXISTS
+
+```php
+index('idx_users_email')
+ ->ifExists();
+
+echo $query->toSQL();
+// DROP INDEX IF EXISTS idx_users_email
+```
+
+### CONCURRENTLY
+
+Drop an index without locking out concurrent selects, inserts, updates, or deletes:
+
+```php
+index('idx_users_email')
+ ->concurrently();
+
+echo $query->toSQL();
+// DROP INDEX CONCURRENTLY idx_users_email
+```
+
+### CASCADE
+
+Drop objects that depend on the index:
+
+```php
+index('idx_users_email')
+ ->cascade();
+
+echo $query->toSQL();
+// DROP INDEX idx_users_email CASCADE
+```
+
+### Combined Options
+
+```php
+index('idx_users_email')
+ ->ifExists()
+ ->cascade();
+
+echo $query->toSQL();
+// DROP INDEX IF EXISTS idx_users_email CASCADE
+```
+
+### Multiple Indexes
+
+```php
+index('idx_users_email', 'idx_users_name', 'idx_orders_date');
+
+echo $query->toSQL();
+// DROP INDEX idx_users_email, idx_users_name, idx_orders_date
+```
+
+### With Schema
+
+```php
+index('public.idx_users_email');
+
+echo $query->toSQL();
+// DROP INDEX public.idx_users_email
+```
+
+## REINDEX
+
+### Reindex an Index
+
+```php
+toSQL();
+// REINDEX INDEX idx_users_email
+```
+
+### Reindex a Table
+
+Rebuild all indexes on a table:
+
+```php
+toSQL();
+// REINDEX TABLE users
+```
+
+### Reindex a Schema
+
+Rebuild all indexes in a schema:
+
+```php
+toSQL();
+// REINDEX SCHEMA public
+```
+
+### Reindex a Database
+
+Rebuild all indexes in the current database:
+
+```php
+toSQL();
+// REINDEX DATABASE mydb
+```
+
+### CONCURRENTLY
+
+Rebuild an index without locking out writes:
+
+```php
+concurrently();
+
+echo $query->toSQL();
+// REINDEX (CONCURRENTLY) INDEX idx_users_email
+```
+
+### VERBOSE
+
+Print progress reports:
+
+```php
+verbose();
+
+echo $query->toSQL();
+// REINDEX (VERBOSE) TABLE users
+```
+
+### TABLESPACE
+
+Rebuild the index in a different tablespace:
+
+```php
+tablespace('fast_storage');
+
+echo $query->toSQL();
+// REINDEX (TABLESPACE fast_storage) INDEX idx_users_email
+```
+
+### With Schema
+
+```php
+toSQL();
+// REINDEX TABLE public.users
+```
+
+## ALTER INDEX
+
+### Rename Index
+
+```php
+index('idx_old')
+ ->renameTo('idx_new');
+
+echo $query->toSQL();
+// ALTER INDEX idx_old RENAME TO idx_new
+```
+
+### Rename with IF EXISTS
+
+```php
+index('idx_old')
+ ->ifExists()
+ ->renameTo('idx_new');
+
+echo $query->toSQL();
+// ALTER INDEX IF EXISTS idx_old RENAME TO idx_new
+```
+
+### Rename with Schema
+
+```php
+index('idx_old', 'public')
+ ->renameTo('idx_new');
+
+echo $query->toSQL();
+// ALTER INDEX public.idx_old RENAME TO idx_new
+```
+
+### Set Tablespace
+
+Move an index to a different tablespace:
+
+```php
+index('idx_users_email')
+ ->setTablespace('fast_storage');
+
+echo $query->toSQL();
+// ALTER INDEX idx_users_email SET TABLESPACE fast_storage
+```
+
+### Set Tablespace with IF EXISTS
+
+```php
+index('idx_users_email')
+ ->ifExists()
+ ->setTablespace('fast_storage');
+
+echo $query->toSQL();
+// ALTER INDEX IF EXISTS idx_users_email SET TABLESPACE fast_storage
+```
+
+For a complete list of DSL functions, see the [DSL reference](/documentation/api/lib/postgresql/namespaces/flow-postgresql-dsl.html).
diff --git a/documentation/components/libs/postgresql/insert-query-builder.md b/documentation/components/libs/postgresql/insert-query-builder.md
new file mode 100644
index 000000000..9a9ddb7de
--- /dev/null
+++ b/documentation/components/libs/postgresql/insert-query-builder.md
@@ -0,0 +1,258 @@
+# Insert Query Builder
+
+- [⬅️ Back](/documentation/components/libs/postgresql.md)
+
+[TOC]
+
+The Insert Query Builder provides a fluent, type-safe interface for constructing PostgreSQL INSERT queries. It supports simple inserts, multi-row inserts, INSERT ... SELECT, upserts (ON CONFLICT), and RETURNING clauses.
+
+## Simple Insert
+
+```php
+into('users')
+ ->columns('name', 'email')
+ ->values(literal('John'), literal('john@example.com'));
+
+echo $query->toSQL();
+// INSERT INTO users (name, email) VALUES ('John', 'john@example.com')
+```
+
+## Insert with Parameters
+
+Use positional parameters for prepared statements:
+
+```php
+into('users')
+ ->columns('name', 'email')
+ ->values(param(1), param(2));
+
+echo $query->toSQL();
+// INSERT INTO users (name, email) VALUES ($1, $2)
+```
+
+## Multi-Row Insert
+
+```php
+into('users')
+ ->columns('name', 'email')
+ ->values(literal('John'), literal('john@example.com'))
+ ->values(literal('Jane'), literal('jane@example.com'));
+
+echo $query->toSQL();
+// INSERT INTO users (name, email) VALUES ('John', 'john@example.com'), ('Jane', 'jane@example.com')
+```
+
+## Insert with Default Values
+
+```php
+into('users')
+ ->defaultValues();
+
+echo $query->toSQL();
+// INSERT INTO users DEFAULT VALUES
+```
+
+## INSERT ... SELECT
+
+```php
+select(col('name'), col('email'))
+ ->from(table('archived_users'));
+
+$query = insert()
+ ->into('users')
+ ->columns('name', 'email')
+ ->select($selectQuery);
+
+echo $query->toSQL();
+// INSERT INTO users (name, email) SELECT name, email FROM archived_users
+```
+
+## Upsert (ON CONFLICT)
+
+### ON CONFLICT DO NOTHING
+
+```php
+into('users')
+ ->columns('name', 'email')
+ ->values(literal('John'), literal('john@example.com'))
+ ->onConflictDoNothing();
+
+echo $query->toSQL();
+// INSERT INTO users (name, email) VALUES ('John', 'john@example.com') ON CONFLICT DO NOTHING
+```
+
+### ON CONFLICT (columns) DO NOTHING
+
+```php
+into('users')
+ ->columns('name', 'email')
+ ->values(literal('John'), literal('john@example.com'))
+ ->onConflictDoNothing(conflict_columns(['email']));
+
+echo $query->toSQL();
+// INSERT INTO users (name, email) VALUES ('John', 'john@example.com') ON CONFLICT (email) DO NOTHING
+```
+
+### ON CONFLICT ON CONSTRAINT DO NOTHING
+
+```php
+into('users')
+ ->columns('name', 'email')
+ ->values(literal('John'), literal('john@example.com'))
+ ->onConflictDoNothing(conflict_constraint('users_pkey'));
+
+echo $query->toSQL();
+// INSERT INTO users (name, email) VALUES ('John', 'john@example.com') ON CONFLICT ON CONSTRAINT users_pkey DO NOTHING
+```
+
+### ON CONFLICT DO UPDATE
+
+```php
+into('users')
+ ->columns('email', 'name')
+ ->values(literal('john@example.com'), literal('John'))
+ ->onConflictDoUpdate(
+ conflict_columns(['email']),
+ ['name' => literal('Updated John')]
+ );
+
+echo $query->toSQL();
+// INSERT INTO users (email, name) VALUES ('john@example.com', 'John') ON CONFLICT (email) DO UPDATE SET name = 'Updated John'
+```
+
+### ON CONFLICT DO UPDATE with EXCLUDED
+
+Reference the values that would have been inserted using the `excluded` pseudo-table:
+
+```php
+into('users')
+ ->columns('email', 'name')
+ ->values(param(1), param(2))
+ ->onConflictDoUpdate(
+ conflict_columns(['email']),
+ ['name' => col('excluded.name')]
+ );
+
+echo $query->toSQL();
+// INSERT INTO users (email, name) VALUES ($1, $2) ON CONFLICT (email) DO UPDATE SET name = excluded.name
+```
+
+### ON CONFLICT DO UPDATE with WHERE
+
+```php
+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)));
+
+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
+```
+
+## RETURNING Clause
+
+```php
+into('users')
+ ->columns('name')
+ ->values(literal('John'))
+ ->returning(col('id'));
+
+echo $query->toSQL();
+// INSERT INTO users (name) VALUES ('John') RETURNING id
+
+// Return all columns
+$query = insert()
+ ->into('users')
+ ->columns('name')
+ ->values(literal('John'))
+ ->returningAll();
+
+echo $query->toSQL();
+// INSERT INTO users (name) VALUES ('John') RETURNING *
+```
+
+## Schema-Qualified Tables
+
+```php
+into('public.users')
+ ->columns('name')
+ ->values(literal('John'));
+
+echo $query->toSQL();
+// INSERT INTO public.users (name) VALUES ('John')
+```
+
+For a complete list of DSL functions, see the [DSL reference](/documentation/api/lib/postgresql/namespaces/flow-postgresql-dsl.html).
diff --git a/documentation/components/libs/postgresql/merge-query-builder.md b/documentation/components/libs/postgresql/merge-query-builder.md
new file mode 100644
index 000000000..3d985f51b
--- /dev/null
+++ b/documentation/components/libs/postgresql/merge-query-builder.md
@@ -0,0 +1,264 @@
+# Merge Query Builder
+
+- [⬅️ Back](/documentation/components/libs/postgresql.md)
+
+[TOC]
+
+The Merge Query Builder provides a fluent, type-safe interface for constructing PostgreSQL MERGE queries. MERGE (also known as "upsert" in some contexts) allows you to perform INSERT, UPDATE, or DELETE operations in a single statement based on whether rows match between a source and target table.
+
+## Simple Merge with Update
+
+```php
+using('source_table', 's')
+ ->on(eq(col('t.id'), col('s.id')))
+ ->whenMatched()
+ ->thenUpdate([
+ 'name' => col('s.name'),
+ 'value' => col('s.value'),
+ ]);
+
+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
+```
+
+## Merge with Delete
+
+```php
+using('source_table', 's')
+ ->on(eq(col('t.id'), col('s.id')))
+ ->whenMatched()
+ ->thenDelete();
+
+echo $query->toSQL();
+// MERGE INTO target_table t USING source_table s ON t.id = s.id WHEN MATCHED THEN DELETE
+```
+
+## Merge with Insert
+
+```php
+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')]
+ );
+
+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)
+```
+
+## Merge with Insert Values
+
+Alternative syntax using column => value pairs:
+
+```php
+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'),
+ ]);
+
+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')
+```
+
+## Multiple WHEN Clauses
+
+Combine different actions based on matching conditions:
+
+```php
+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')]
+ );
+
+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)
+```
+
+## Conditional WHEN Clauses
+
+Add conditions to WHEN MATCHED and WHEN NOT MATCHED clauses:
+
+```php
+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'),
+ ]);
+
+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
+```
+
+## DO NOTHING Action
+
+```php
+using('updates', 'u')
+ ->on(eq(col('products.id'), col('u.id')))
+ ->whenMatched()
+ ->thenDoNothing();
+
+echo $query->toSQL();
+// MERGE INTO products USING updates u ON products.id = u.id WHEN MATCHED THEN DO NOTHING
+```
+
+## Merge Using Subquery
+
+Use a subquery as the source:
+
+```php
+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'),
+ ]);
+
+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
+```
+
+## Merge with CTE (WITH Clause)
+
+```php
+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'),
+ ]);
+
+echo $query->toSql();
+// 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
+```
+
+## Merge with Parameters
+
+Use positional parameters for prepared statements:
+
+```php
+using('transactions', 't')
+ ->on(eq(col('accounts.id'), col('t.account_id')))
+ ->whenMatched()
+ ->thenUpdate([
+ 'balance' => param(1),
+ ]);
+
+echo $query->toSQL();
+// MERGE INTO accounts USING transactions t ON accounts.id = t.account_id WHEN MATCHED THEN UPDATE SET balance = $1
+```
+
+## WHEN NOT MATCHED BY SOURCE
+
+Handle rows in the target that don't have matching rows in the source:
+
+```php
+using('source', 's')
+ ->on(eq(col('t.id'), col('s.id')))
+ ->whenNotMatchedBySource()
+ ->thenDelete();
+
+echo $query->toSQL();
+// MERGE INTO target t USING source s ON t.id = s.id WHEN NOT MATCHED BY SOURCE THEN DELETE
+```
+
+## Schema-Qualified Tables
+
+```php
+using('public.updates', 's')
+ ->on(eq(col('u.id'), col('s.id')))
+ ->whenMatched()
+ ->thenDoNothing();
+
+echo $query->toSQL();
+// MERGE INTO myschema.users u USING public.updates s ON u.id = s.id WHEN MATCHED THEN DO NOTHING
+```
+
+## DSL Functions
+
+For a complete list of DSL functions, see the [DSL reference](/documentation/api/lib/postgresql/namespaces/flow-postgresql-dsl.html).
diff --git a/documentation/components/libs/postgresql/role-grant-query-builder.md b/documentation/components/libs/postgresql/role-grant-query-builder.md
new file mode 100644
index 000000000..a2d8eb5fe
--- /dev/null
+++ b/documentation/components/libs/postgresql/role-grant-query-builder.md
@@ -0,0 +1,309 @@
+# Role and Grant Query Builder
+
+The PostgreSQL library provides fluent builders for managing PostgreSQL roles, users, and their privileges.
+
+## Role Management
+
+### CREATE ROLE
+
+Create database roles with various options:
+
+```php
+use function Flow\PostgreSql\DSL\create;
+
+// Simple role
+create()->role('admin')->toSql();
+// CREATE ROLE admin
+
+// Role with login (equivalent to CREATE USER)
+create()->role('app_user')
+ ->login()
+ ->withPassword('secret')
+ ->toSql();
+// CREATE ROLE app_user LOGIN PASSWORD 'secret'
+
+// Superuser with multiple options
+create()->role('admin')
+ ->superuser()
+ ->login()
+ ->createDb()
+ ->createRole()
+ ->connectionLimit(10)
+ ->validUntil('2025-12-31')
+ ->toSql();
+// CREATE ROLE admin SUPERUSER LOGIN CREATEDB CREATEROLE CONNECTION LIMIT 10 VALID UNTIL '2025-12-31'
+
+// Role that inherits from another role
+create()->role('developer')
+ ->login()
+ ->inRole('team_lead')
+ ->toSql();
+// CREATE ROLE developer LOGIN IN ROLE team_lead
+```
+
+Available options:
+- `superuser()` / `noSuperuser()` - Superuser privileges
+- `createDb()` / `noCreateDb()` - Database creation privileges
+- `createRole()` / `noCreateRole()` - Role creation privileges
+- `login()` / `noLogin()` - Connection privileges (login makes it a "user")
+- `inherit()` / `noInherit()` - Privilege inheritance
+- `replication()` / `noReplication()` - Replication privileges
+- `bypassRls()` / `noBypassRls()` - Row-level security bypass
+- `withPassword(string)` - Set password
+- `connectionLimit(int)` - Maximum concurrent connections
+- `validUntil(string)` - Password expiration date
+- `inRole(string)` - Member of another role
+
+### ALTER ROLE
+
+Modify existing roles:
+
+```php
+use function Flow\PostgreSql\DSL\alter;
+
+// Change options
+alter()->role('admin')
+ ->superuser()
+ ->toSql();
+// ALTER ROLE admin SUPERUSER
+
+alter()->role('user')
+ ->noLogin()
+ ->connectionLimit(5)
+ ->toSql();
+// ALTER ROLE user NOLOGIN CONNECTION LIMIT 5
+
+// Rename role
+alter()->role('old_name')
+ ->renameTo('new_name')
+ ->toSql();
+// ALTER ROLE old_name RENAME TO new_name
+```
+
+### DROP ROLE
+
+Remove roles from the database:
+
+```php
+use function Flow\PostgreSql\DSL\drop;
+
+// Simple drop
+drop()->role('admin')->toSql();
+// DROP ROLE admin
+
+// Drop if exists
+drop()->role('admin')
+ ->ifExists()
+ ->toSql();
+// DROP ROLE IF EXISTS admin
+
+// Drop multiple roles
+drop()->role('role1', 'role2', 'role3')
+ ->ifExists()
+ ->toSql();
+// DROP ROLE IF EXISTS role1, role2, role3
+```
+
+## Privilege Management
+
+### GRANT Privileges
+
+Grant object privileges to roles:
+
+```php
+use function Flow\PostgreSql\DSL\grant;
+use Flow\PostgreSql\QueryBuilder\Schema\Grant\TablePrivilege;
+
+// Grant SELECT on a table
+grant(TablePrivilege::SELECT)
+ ->onTable('users')
+ ->to('app_user')
+ ->toSql();
+// GRANT SELECT ON users TO app_user
+
+// Grant multiple privileges
+grant(TablePrivilege::SELECT, TablePrivilege::INSERT, TablePrivilege::UPDATE)
+ ->onTable('orders')
+ ->to('order_processor')
+ ->toSql();
+// GRANT SELECT, INSERT, UPDATE ON orders TO order_processor
+
+// Grant ALL privileges
+grant(TablePrivilege::ALL)
+ ->onTable('products')
+ ->to('admin')
+ ->toSql();
+// GRANT ALL ON products TO admin
+
+// Grant on all tables in schema
+grant(TablePrivilege::SELECT)
+ ->onAllTablesInSchema('public')
+ ->to('reader')
+ ->toSql();
+// GRANT SELECT ON ALL TABLES IN SCHEMA public TO reader
+
+// Grant to PUBLIC
+grant(TablePrivilege::SELECT)
+ ->onTable('public_data')
+ ->toPublic()
+ ->toSql();
+// GRANT SELECT ON public_data TO PUBLIC
+
+// Grant with GRANT OPTION
+grant(TablePrivilege::SELECT)
+ ->onTable('shared_data')
+ ->to('team_lead')
+ ->withGrantOption()
+ ->toSql();
+// GRANT SELECT ON shared_data TO team_lead WITH GRANT OPTION
+```
+
+Available privileges:
+- `TablePrivilege::SELECT`
+- `TablePrivilege::INSERT`
+- `TablePrivilege::UPDATE`
+- `TablePrivilege::DELETE`
+- `TablePrivilege::TRUNCATE`
+- `TablePrivilege::REFERENCES`
+- `TablePrivilege::TRIGGER`
+- `TablePrivilege::ALL`
+
+### GRANT Role Membership
+
+Grant role membership to other roles:
+
+```php
+use function Flow\PostgreSql\DSL\grant_role;
+
+// Grant role to user
+grant_role('admin')
+ ->to('user1')
+ ->toSql();
+// GRANT admin TO user1
+
+// Grant multiple roles
+grant_role('admin', 'developer')
+ ->to('team_lead')
+ ->toSql();
+// GRANT admin, developer TO team_lead
+
+// Grant with admin option
+grant_role('admin')
+ ->to('super_admin')
+ ->withAdminOption()
+ ->toSql();
+// GRANT admin TO super_admin WITH ADMIN OPTION
+```
+
+### REVOKE Privileges
+
+Revoke object privileges from roles:
+
+```php
+use function Flow\PostgreSql\DSL\revoke;
+use Flow\PostgreSql\QueryBuilder\Schema\Grant\TablePrivilege;
+
+// Revoke SELECT
+revoke(TablePrivilege::SELECT)
+ ->onTable('users')
+ ->from('app_user')
+ ->toSql();
+// REVOKE SELECT ON users FROM app_user
+
+// Revoke with CASCADE
+revoke(TablePrivilege::ALL)
+ ->onTable('sensitive_data')
+ ->from('former_employee')
+ ->cascade()
+ ->toSql();
+// REVOKE ALL ON sensitive_data FROM former_employee CASCADE
+
+// Revoke from PUBLIC
+revoke(TablePrivilege::SELECT)
+ ->onTable('public_data')
+ ->fromPublic()
+ ->toSql();
+// REVOKE SELECT ON public_data FROM PUBLIC
+```
+
+### REVOKE Role Membership
+
+Revoke role membership:
+
+```php
+use function Flow\PostgreSql\DSL\revoke_role;
+
+// Simple revoke
+revoke_role('admin')
+ ->from('user1')
+ ->toSql();
+// REVOKE admin FROM user1
+
+// Revoke with CASCADE
+revoke_role('admin')
+ ->from('user1')
+ ->cascade()
+ ->toSql();
+// REVOKE admin FROM user1 CASCADE
+```
+
+## Session Management
+
+### SET ROLE
+
+Change the current session role:
+
+```php
+use function Flow\PostgreSql\DSL\set_role;
+
+set_role('admin')->toSql();
+// SET ROLE admin
+```
+
+### RESET ROLE
+
+Reset to the original role:
+
+```php
+use function Flow\PostgreSql\DSL\reset_role;
+
+reset_role()->toSql();
+// RESET ROLE
+```
+
+## Ownership Management
+
+### REASSIGN OWNED
+
+Reassign ownership of database objects:
+
+```php
+use function Flow\PostgreSql\DSL\reassign_owned;
+
+reassign_owned('old_role')
+ ->to('new_role')
+ ->toSql();
+// REASSIGN OWNED BY old_role TO new_role
+
+// Multiple source roles
+reassign_owned('role1', 'role2')
+ ->to('new_owner')
+ ->toSql();
+// REASSIGN OWNED BY role1, role2 TO new_owner
+```
+
+### DROP OWNED
+
+Drop objects owned by roles:
+
+```php
+use function Flow\PostgreSql\DSL\drop_owned;
+
+drop_owned('old_role')->toSql();
+// DROP OWNED BY old_role
+
+drop_owned('role1', 'role2')
+ ->cascade()
+ ->toSql();
+// DROP OWNED BY role1, role2 CASCADE
+```
diff --git a/documentation/components/libs/postgresql/schema-query-builder.md b/documentation/components/libs/postgresql/schema-query-builder.md
new file mode 100644
index 000000000..252c520d6
--- /dev/null
+++ b/documentation/components/libs/postgresql/schema-query-builder.md
@@ -0,0 +1,147 @@
+# Schema Query Builder
+
+- [⬅️ Back](/documentation/components/libs/postgresql.md)
+
+[TOC]
+
+The Schema Query Builder provides a fluent interface for building PostgreSQL schema management statements.
+
+## CREATE SCHEMA
+
+Create a new schema in the database.
+
+```php
+schema('my_schema');
+
+echo $query->toSQL();
+// CREATE SCHEMA my_schema
+
+// With IF NOT EXISTS
+$query = create()->schema('my_schema')
+ ->ifNotExists();
+
+echo $query->toSQL();
+// CREATE SCHEMA IF NOT EXISTS my_schema
+
+// With authorization
+$query = create()->schema('my_schema')
+ ->authorization('admin_user');
+
+echo $query->toSQL();
+// CREATE SCHEMA my_schema AUTHORIZATION admin_user
+
+// Combined options
+$query = create()->schema('my_schema')
+ ->ifNotExists()
+ ->authorization('admin_user');
+
+echo $query->toSQL();
+// CREATE SCHEMA IF NOT EXISTS my_schema AUTHORIZATION admin_user
+```
+
+### Available Methods
+
+| Method | Description |
+|--------|-------------|
+| `ifNotExists()` | Add IF NOT EXISTS clause |
+| `authorization(string $role)` | Specify schema owner |
+
+## ALTER SCHEMA
+
+Modify an existing schema.
+
+### Rename Schema
+
+```php
+schema('old_schema')
+ ->renameTo('new_schema');
+
+echo $query->toSQL();
+// ALTER SCHEMA old_schema RENAME TO new_schema
+```
+
+### Change Owner
+
+```php
+schema('my_schema')
+ ->ownerTo('new_owner');
+
+echo $query->toSQL();
+// ALTER SCHEMA my_schema OWNER TO new_owner
+```
+
+## DROP SCHEMA
+
+Remove one or more schemas from the database.
+
+```php
+schema('my_schema');
+
+echo $query->toSQL();
+// DROP SCHEMA my_schema
+
+// With IF EXISTS
+$query = drop()->schema('my_schema')
+ ->ifExists();
+
+echo $query->toSQL();
+// DROP SCHEMA IF EXISTS my_schema
+
+// With CASCADE
+$query = drop()->schema('my_schema')
+ ->cascade();
+
+echo $query->toSQL();
+// DROP SCHEMA my_schema CASCADE
+
+// Combined options
+$query = drop()->schema('my_schema')
+ ->ifExists()
+ ->cascade();
+
+echo $query->toSQL();
+// DROP SCHEMA IF EXISTS my_schema CASCADE
+
+// Drop multiple schemas
+$query = drop()->schema('schema1', 'schema2', 'schema3')
+ ->cascade();
+
+echo $query->toSQL();
+// DROP SCHEMA schema1, schema2, schema3 CASCADE
+```
+
+### Available Methods
+
+| Method | Description |
+|--------|-------------|
+| `ifExists()` | Add IF EXISTS clause |
+| `cascade()` | Drop dependent objects |
+| `restrict()` | Refuse to drop if dependent objects exist (default) |
+
+## DSL Functions
+
+| Function | Returns | Description |
+|----------|---------|-------------|
+| `create()->schema(string $name)` | `CreateSchemaOptionsStep` | Start building a CREATE SCHEMA statement |
+| `alter()->schema(string $name)` | `AlterSchemaActionStep` | Start building an ALTER SCHEMA statement |
+| `drop()->schema(string ...$names)` | `DropSchemaFinalStep` | Start building a DROP SCHEMA statement |
+
+For a complete list of DSL functions, see the [DSL reference](/documentation/api/lib/postgresql/namespaces/flow-postgresql-dsl.html).
diff --git a/documentation/components/libs/postgresql/select-query-builder.md b/documentation/components/libs/postgresql/select-query-builder.md
new file mode 100644
index 000000000..ad46ac4b7
--- /dev/null
+++ b/documentation/components/libs/postgresql/select-query-builder.md
@@ -0,0 +1,733 @@
+# Select Query Builder
+
+- [⬅️ Back](/documentation/components/libs/postgresql.md)
+
+[TOC]
+
+The Select Query Builder provides a fluent, type-safe interface for constructing PostgreSQL SELECT queries. It guides you through building valid queries step-by-step, from simple selects to complex queries with JOINs, CTEs, and window functions.
+
+## Simple Select
+
+```php
+from(table('users'));
+
+echo $query->toSQL();
+// SELECT id, name FROM users
+
+// Select all columns
+$query = select(star())
+ ->from(table('users'));
+
+echo $query->toSQL();
+// SELECT * FROM users
+```
+
+## WHERE Clause
+
+```php
+from(table('users'))
+ ->where(eq(col('active'), literal(true)));
+
+echo $query->toSQL();
+// SELECT * FROM users WHERE active = true
+
+// Multiple conditions with AND
+$query = select(star())
+ ->from(table('products'))
+ ->where(
+ cond_and(
+ gt(col('price'), literal(10)),
+ lt(col('price'), literal(100)),
+ eq(col('in_stock'), literal(true))
+ )
+ );
+
+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(
+ eq(col('status'), literal('active')),
+ cond_or(
+ gte(col('age'), literal(18)),
+ eq(col('guardian_approved'), literal(true))
+ )
+ )
+ );
+
+echo $query->toSQL();
+// SELECT * FROM users WHERE status = 'active' AND (age >= 18 OR guardian_approved = true)
+
+// BETWEEN condition
+$query = select(star())
+ ->from(table('products'))
+ ->where(between(col('price'), literal(10), literal(100)));
+
+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'), [
+ literal('active'),
+ literal('pending'),
+ literal('verified')
+ ]));
+
+echo $query->toSQL();
+// SELECT * FROM users WHERE status IN ('active', 'pending', 'verified')
+
+// LIKE condition
+$query = select(star())
+ ->from(table('users'))
+ ->where(like(col('email'), literal('%@example.com')));
+
+echo $query->toSQL();
+// SELECT * FROM users WHERE email LIKE '%@example.com'
+```
+
+## JOINs
+
+```php
+from(table('users')->as('u'))
+ ->join(
+ table('orders')->as('o'),
+ eq(col('u.id'), col('o.user_id'))
+ );
+
+echo $query->toSQL();
+// SELECT u.name, o.total FROM users u JOIN orders o ON u.id = o.user_id
+
+// LEFT JOIN
+$query = 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'))
+ );
+
+echo $query->toSQL();
+// SELECT u.name, o.total FROM users u LEFT JOIN orders o ON u.id = o.user_id
+
+// RIGHT JOIN
+$query = select(star())
+ ->from(table('orders')->as('o'))
+ ->rightJoin(
+ table('users')->as('u'),
+ eq(col('o.user_id'), col('u.id'))
+ );
+
+echo $query->toSQL();
+// SELECT * FROM orders o RIGHT JOIN users u ON o.user_id = u.id
+
+// FULL JOIN
+$query = select(star())
+ ->from(table('table_a')->as('a'))
+ ->fullJoin(
+ table('table_b')->as('b'),
+ eq(col('a.key'), col('b.key'))
+ );
+
+echo $query->toSQL();
+// SELECT * FROM table_a a FULL JOIN table_b b ON a.key = b.key
+
+// CROSS JOIN
+$query = select(star())
+ ->from(table('colors'))
+ ->crossJoin(table('sizes'));
+
+echo $query->toSQL();
+// SELECT * FROM colors CROSS JOIN sizes
+```
+
+## ORDER BY Clause
+
+```php
+from(table('users'))
+ ->orderBy(asc(col('name')));
+
+echo $query->toSQL();
+// SELECT * FROM users ORDER BY name ASC
+
+// Multiple columns
+$query = select(star())
+ ->from(table('users'))
+ ->orderBy(
+ asc(col('last_name')),
+ desc(col('first_name'))
+ );
+
+echo $query->toSQL();
+// SELECT * FROM users ORDER BY last_name ASC, first_name DESC
+
+// NULLS FIRST / NULLS LAST
+$query = select(star())
+ ->from(table('products'))
+ ->orderBy(
+ order_by(col('price'), SortDirection::ASC, NullsPosition::FIRST),
+ order_by(col('name'), SortDirection::DESC, NullsPosition::LAST)
+ );
+
+echo $query->toSQL();
+// SELECT * FROM products ORDER BY price ASC NULLS FIRST, name DESC NULLS LAST
+```
+
+## LIMIT and OFFSET
+
+```php
+from(table('users'))
+ ->orderBy(asc(col('id')))
+ ->limit(10)
+ ->offset(20);
+
+echo $query->toSQL();
+// SELECT * FROM users ORDER BY id ASC LIMIT 10 OFFSET 20
+```
+
+## Common Table Expressions (CTE)
+
+```php
+from(table('users'))
+ ->where(eq(col('active'), literal(true)))
+ )
+)
+ ->select(star())
+ ->from(table('active_users'));
+
+echo $query->toSQL();
+// WITH active_users AS (SELECT id, name FROM users WHERE active = true) SELECT * FROM active_users
+
+// Multiple CTEs
+$query = with(
+ cte('users_cte', select(col('id'), col('name'))->from(table('users'))),
+ cte('orders_cte', select(col('id'), col('user_id'))->from(table('orders')))
+)
+ ->select(star())
+ ->from(table('users_cte'));
+
+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
+$query = with(cte('tree', $recursiveQuery))
+ ->recursive()
+ ->select(star())
+ ->from(table('tree'));
+
+echo $query->toSQL();
+// WITH RECURSIVE tree AS (...) SELECT * FROM tree
+
+// Materialized CTE
+$query = with(
+ cte(
+ 'active_users',
+ select(col('id'), col('name'))
+ ->from(table('users'))
+ ->where(eq(col('active'), literal(true))),
+ [],
+ CTEMaterialization::MATERIALIZED
+ )
+)
+ ->select(star())
+ ->from(table('active_users'));
+
+echo $query->toSQL();
+// WITH active_users AS MATERIALIZED (SELECT id, name FROM users WHERE active = true) SELECT * FROM active_users
+```
+
+## Derived Tables (Subqueries in FROM)
+
+```php
+as('total'))
+ ->from(table('orders'))
+ ->groupBy(col('user_id'));
+
+$query = select(col('u.name'), col('o.total'))
+ ->from(table('users')->as('u'))
+ ->leftJoin(
+ derived($subquery, 'o'),
+ eq(col('u.id'), col('o.user_id'))
+ );
+
+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
+```
+
+## LATERAL Join
+
+```php
+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')
+ );
+
+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
+```
+
+## JSONB Operators
+
+The query builder provides native support for PostgreSQL JSONB operators:
+
+```php
+)
+$query = select(star())
+ ->from(table('products'))
+ ->where(json_contains(col('metadata'), literal('{"category": "electronics"}')));
+
+echo $query->toSQL();
+// SELECT * FROM products WHERE metadata @> '{"category": "electronics"}'
+
+// JSONB is contained by (<@)
+$query = select(star())
+ ->from(table('products'))
+ ->where(json_contained_by(col('metadata'), literal('{"category": "electronics", "price": 100}')));
+
+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();
+// 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();
+// 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();
+// 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();
+// SELECT metadata #>> '{category,name}' AS nested_text FROM products
+
+// Key exists (?)
+$query = select(star())
+ ->from(table('products'))
+ ->where(json_exists(col('metadata'), literal('category')));
+
+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']")));
+
+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']")));
+
+echo $query->toSQL();
+// SELECT * FROM products WHERE metadata ?& array['category', 'name']
+```
+
+## Array Operators
+
+PostgreSQL array operators are also supported:
+
+```php
+)
+$query = select(star())
+ ->from(table('products'))
+ ->where(array_contains(col('tags'), raw_expr("ARRAY['sale']")));
+
+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']")));
+
+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']")));
+
+echo $query->toSQL();
+// SELECT * FROM products WHERE tags && ARRAY['sale', 'featured']
+```
+
+## Pattern Matching (Regex)
+
+POSIX regex operators for pattern matching:
+
+```php
+from(table('users'))
+ ->where(regex_match(col('email'), literal('.*@gmail\\.com')));
+
+echo $query->toSQL();
+// SELECT * FROM users WHERE email ~ '.*@gmail\.com'
+
+// Case-insensitive regex match (~*)
+$query = select(star())
+ ->from(table('users'))
+ ->where(regex_imatch(col('email'), literal('.*@gmail\\.com')));
+
+echo $query->toSQL();
+// SELECT * FROM users WHERE email ~* '.*@gmail\.com'
+
+// Does not match (!~)
+$query = select(star())
+ ->from(table('users'))
+ ->where(not_regex_match(col('email'), literal('.*@spam\\.com')));
+
+echo $query->toSQL();
+// SELECT * FROM users WHERE email !~ '.*@spam\.com'
+
+// Does not match case-insensitive (!~*)
+$query = select(star())
+ ->from(table('users'))
+ ->where(not_regex_imatch(col('email'), literal('.*@spam\\.com')));
+
+echo $query->toSQL();
+// SELECT * FROM users WHERE email !~* '.*@spam\.com'
+```
+
+## Full-Text Search
+
+PostgreSQL full-text search operator:
+
+```php
+from(table('documents'))
+ ->where(text_search_match(col('content'), raw_expr("to_tsquery('english', 'hello & world')")));
+
+echo $query->toSQL();
+// SELECT * FROM documents WHERE content @@ to_tsquery('english', 'hello & world')
+```
+
+## Aggregates and GROUP BY
+
+```php
+from(table('orders'))
+ ->groupBy(col('category'));
+
+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
+$query = select(col('category'), agg_count()->as('cnt'))
+ ->from(table('products'))
+ ->groupBy(col('category'))
+ ->having(gt(agg_count(), literal(5)));
+
+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();
+// SELECT count(DISTINCT user_id) AS unique_users FROM orders
+```
+
+## UNION, INTERSECT, EXCEPT
+
+```php
+from(table('users'));
+
+$query2 = select(col('name'))
+ ->from(table('admins'));
+
+// UNION
+$query = $query1->union($query2);
+
+echo $query->toSQL();
+// SELECT name FROM users UNION SELECT name FROM admins
+
+// UNION ALL
+$query = $query1->unionAll($query2);
+
+echo $query->toSQL();
+// SELECT name FROM users UNION ALL SELECT name FROM admins
+
+// INTERSECT
+$query = $query1->intersect($query2);
+
+echo $query->toSQL();
+// SELECT name FROM users INTERSECT SELECT name FROM admins
+
+// EXCEPT
+$query = $query1->except($query2);
+
+echo $query->toSQL();
+// SELECT name FROM users EXCEPT SELECT name FROM admins
+```
+
+## Subqueries
+
+```php
+from(table('orders'))
+ ->where(eq(col('orders.user_id'), col('users.id')));
+
+$query = select(
+ col('name'),
+ sub_select($subquery)->as('order_count')
+ )
+ ->from(table('users'));
+
+echo $query->toSQL();
+// SELECT name, (SELECT count(*) FROM orders WHERE orders.user_id = users.id) AS order_count FROM users
+
+// EXISTS subquery
+$subquery = select(literal(1))
+ ->from(table('orders'))
+ ->where(eq(col('orders.user_id'), col('users.id')));
+
+$query = select(star())
+ ->from(table('users'))
+ ->where(exists($subquery));
+
+echo $query->toSQL();
+// SELECT * FROM users WHERE EXISTS (SELECT 1 FROM orders WHERE orders.user_id = users.id)
+```
+
+## Parameters
+
+Use positional parameters for prepared statements:
+
+```php
+from(table('users'))
+ ->where(eq(col('id'), param(1)));
+
+echo $query->toSQL();
+// SELECT * FROM users WHERE id = $1
+```
+
+## FOR UPDATE / FOR SHARE
+
+```php
+from(table('accounts'))
+ ->where(eq(col('id'), literal(1)))
+ ->forUpdate();
+
+echo $query->toSQL();
+// SELECT * FROM accounts WHERE id = 1 FOR UPDATE
+
+$query = select(star())
+ ->from(table('accounts'))
+ ->where(eq(col('id'), literal(1)))
+ ->forShare();
+
+echo $query->toSQL();
+// SELECT * FROM accounts WHERE id = 1 FOR SHARE
+```
+
+## Column Aliases
+
+```php
+as('fname'),
+ col('last_name')->as('lname')
+ )
+ ->from(table('users'));
+
+echo $query->toSQL();
+// SELECT first_name AS fname, last_name AS lname FROM users
+```
+
+## DISTINCT
+
+```php
+selectDistinct(col('city'))
+ ->from(table('users'));
+
+echo $query->toSQL();
+// SELECT DISTINCT city FROM users
+
+// DISTINCT ON
+$query = select()
+ ->selectDistinctOn(
+ [col('department')],
+ col('name'),
+ col('salary')
+ )
+ ->from(table('employees'))
+ ->orderBy(asc(col('department')), desc(col('salary')));
+
+echo $query->toSQL();
+// SELECT DISTINCT ON (department) name, salary FROM employees ORDER BY department ASC, salary DESC
+```
+
+For a complete list of DSL functions, see the [DSL reference](/documentation/api/lib/postgresql/namespaces/flow-postgresql-dsl.html).
diff --git a/documentation/components/libs/postgresql/sequence-query-builder.md b/documentation/components/libs/postgresql/sequence-query-builder.md
new file mode 100644
index 000000000..b8ab96e56
--- /dev/null
+++ b/documentation/components/libs/postgresql/sequence-query-builder.md
@@ -0,0 +1,517 @@
+# Sequence Query Builder
+
+- [Back](/documentation/components/libs/postgresql.md)
+
+[TOC]
+
+The Sequence Query Builder provides a fluent, type-safe interface for constructing PostgreSQL sequence management statements:
+CREATE SEQUENCE, ALTER SEQUENCE, and DROP SEQUENCE.
+
+## CREATE SEQUENCE
+
+### Basic Sequence Creation
+
+```php
+sequence('user_id_seq');
+
+echo $query->toSQL();
+// CREATE SEQUENCE user_id_seq
+```
+
+### With Schema
+
+```php
+sequence('user_id_seq', 'public');
+
+echo $query->toSQL();
+// CREATE SEQUENCE public.user_id_seq
+```
+
+### IF NOT EXISTS
+
+```php
+sequence('user_id_seq')->ifNotExists();
+
+echo $query->toSQL();
+// CREATE SEQUENCE IF NOT EXISTS user_id_seq
+```
+
+### Temporary Sequence
+
+Create a temporary sequence that is automatically dropped at the end of the session:
+
+```php
+sequence('temp_seq')->temporary();
+
+echo $query->toSQL();
+// CREATE TEMPORARY SEQUENCE temp_seq
+```
+
+### Unlogged Sequence
+
+Create an unlogged sequence for better performance (data not written to WAL):
+
+```php
+sequence('fast_seq')->unlogged();
+
+echo $query->toSQL();
+// CREATE UNLOGGED SEQUENCE fast_seq
+```
+
+### START WITH
+
+Specify the starting value of the sequence:
+
+```php
+sequence('user_id_seq')
+ ->startWith(100);
+
+echo $query->toSQL();
+// CREATE SEQUENCE user_id_seq START 100
+```
+
+### INCREMENT BY
+
+Specify the increment value (positive for ascending, negative for descending):
+
+```php
+sequence('user_id_seq')
+ ->incrementBy(10);
+
+echo $query->toSQL();
+// CREATE SEQUENCE user_id_seq INCREMENT 10
+```
+
+### MINVALUE / NO MINVALUE
+
+Set the minimum value or remove the minimum bound:
+
+```php
+sequence('user_id_seq')
+ ->minValue(1);
+
+echo $query->toSQL();
+// CREATE SEQUENCE user_id_seq MINVALUE 1
+
+// Remove minimum bound
+$query = create()->sequence('user_id_seq')
+ ->noMinValue();
+
+echo $query->toSQL();
+// CREATE SEQUENCE user_id_seq NO MINVALUE
+```
+
+### MAXVALUE / NO MAXVALUE
+
+Set the maximum value or remove the maximum bound:
+
+```php
+sequence('user_id_seq')
+ ->maxValue(9999999);
+
+echo $query->toSQL();
+// CREATE SEQUENCE user_id_seq MAXVALUE 9999999
+
+// Remove maximum bound
+$query = create()->sequence('user_id_seq')
+ ->noMaxValue();
+
+echo $query->toSQL();
+// CREATE SEQUENCE user_id_seq NO MAXVALUE
+```
+
+### CACHE
+
+Specify how many sequence numbers are preallocated and stored in memory:
+
+```php
+sequence('user_id_seq')
+ ->cache(20);
+
+echo $query->toSQL();
+// CREATE SEQUENCE user_id_seq CACHE 20
+```
+
+### CYCLE / NO CYCLE
+
+Enable or disable cycling when the sequence reaches its bounds:
+
+```php
+sequence('user_id_seq')
+ ->cycle();
+
+echo $query->toSQL();
+// CREATE SEQUENCE user_id_seq CYCLE
+
+// Disable cycling (explicit)
+$query = create()->sequence('user_id_seq')
+ ->noCycle();
+
+echo $query->toSQL();
+// CREATE SEQUENCE user_id_seq NO CYCLE
+```
+
+### AS (Data Type)
+
+Specify the data type of the sequence (smallint, integer, or bigint):
+
+```php
+sequence('user_id_seq')
+ ->asType('bigint');
+
+echo $query->toSQL();
+// CREATE SEQUENCE user_id_seq AS bigint
+```
+
+### OWNED BY
+
+Associate the sequence with a table column (dropped automatically when the column is dropped):
+
+```php
+sequence('user_id_seq')
+ ->ownedBy('users', 'id');
+
+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();
+// CREATE SEQUENCE user_id_seq OWNED BY public.users.id
+
+// Remove ownership
+$query = create()->sequence('user_id_seq')
+ ->ownedByNone();
+
+echo $query->toSQL();
+// CREATE SEQUENCE user_id_seq OWNED BY "none"
+```
+
+### Complete Example
+
+```php
+sequence('user_id_seq')
+ ->asType('bigint')
+ ->startWith(1)
+ ->incrementBy(1)
+ ->minValue(1)
+ ->maxValue(1000000)
+ ->cache(1)
+ ->noCycle();
+
+echo $query->toSQL();
+// CREATE SEQUENCE user_id_seq AS bigint START 1 INCREMENT 1 MINVALUE 1 MAXVALUE 1000000 CACHE 1 NO CYCLE
+```
+
+## ALTER SEQUENCE
+
+### RESTART
+
+Restart the sequence at its start value or at a specific value:
+
+```php
+sequence('user_id_seq')
+ ->restart();
+
+echo $query->toSQL();
+// ALTER SEQUENCE user_id_seq RESTART
+
+// Restart at specific value
+$query = alter()->sequence('user_id_seq')
+ ->restartWith(1000);
+
+echo $query->toSQL();
+// ALTER SEQUENCE user_id_seq RESTART 1000
+```
+
+### IF EXISTS
+
+Only alter the sequence if it exists:
+
+```php
+sequence('user_id_seq')
+ ->ifExists()
+ ->incrementBy(10);
+
+echo $query->toSQL();
+// ALTER SEQUENCE IF EXISTS user_id_seq INCREMENT 10
+```
+
+### With Schema
+
+```php
+sequence('user_id_seq', 'public')
+ ->incrementBy(10);
+
+echo $query->toSQL();
+// ALTER SEQUENCE public.user_id_seq INCREMENT 10
+```
+
+### Modify Options
+
+All CREATE SEQUENCE options can also be modified with ALTER SEQUENCE:
+
+```php
+sequence('user_id_seq')
+ ->incrementBy(10)
+ ->minValue(1)
+ ->maxValue(1000000)
+ ->cache(5);
+
+echo $query->toSQL();
+// ALTER SEQUENCE user_id_seq INCREMENT 10 MINVALUE 1 MAXVALUE 1000000 CACHE 5
+```
+
+### RENAME TO
+
+Rename a sequence:
+
+```php
+sequence('old_seq')
+ ->renameTo('new_seq');
+
+echo $query->toSQL();
+// ALTER SEQUENCE old_seq RENAME TO new_seq
+```
+
+### SET SCHEMA
+
+Move a sequence to a different schema:
+
+```php
+sequence('user_id_seq')
+ ->setSchema('new_schema');
+
+echo $query->toSQL();
+// ALTER SEQUENCE user_id_seq SET SCHEMA new_schema
+```
+
+### OWNER TO
+
+Change the owner of a sequence:
+
+```php
+sequence('user_id_seq')
+ ->ownerTo('new_owner');
+
+echo $query->toSQL();
+// ALTER SEQUENCE user_id_seq OWNER TO new_owner
+```
+
+### SET LOGGED / SET UNLOGGED
+
+Change the logging behavior of a sequence:
+
+```php
+sequence('user_id_seq')
+ ->setLogged();
+
+echo $query->toSQL();
+// ALTER SEQUENCE user_id_seq SET LOGGED
+
+// Make the sequence unlogged
+$query = alter()->sequence('user_id_seq')
+ ->setUnlogged();
+
+echo $query->toSQL();
+// ALTER SEQUENCE user_id_seq SET UNLOGGED
+```
+
+## DROP SEQUENCE
+
+### Simple Drop
+
+```php
+sequence('user_id_seq');
+
+echo $query->toSQL();
+// DROP SEQUENCE user_id_seq
+```
+
+### With Schema
+
+```php
+sequence('public.user_id_seq');
+
+echo $query->toSQL();
+// DROP SEQUENCE public.user_id_seq
+```
+
+### IF EXISTS
+
+```php
+sequence('user_id_seq')->ifExists();
+
+echo $query->toSQL();
+// DROP SEQUENCE IF EXISTS user_id_seq
+```
+
+### Multiple Sequences
+
+```php
+sequence('user_id_seq', 'order_id_seq', 'product_id_seq');
+
+echo $query->toSQL();
+// DROP SEQUENCE user_id_seq, order_id_seq, product_id_seq
+```
+
+### CASCADE
+
+Drop objects that depend on the sequence:
+
+```php
+sequence('user_id_seq')
+ ->cascade();
+
+echo $query->toSQL();
+// DROP SEQUENCE user_id_seq CASCADE
+```
+
+### RESTRICT
+
+Refuse to drop the sequence if any objects depend on it (default behavior):
+
+```php
+sequence('user_id_seq')
+ ->restrict();
+
+echo $query->toSQL();
+// DROP SEQUENCE user_id_seq
+```
+
+### Combined Options
+
+```php
+sequence('user_id_seq')
+ ->ifExists()
+ ->cascade();
+
+echo $query->toSQL();
+// DROP SEQUENCE IF EXISTS user_id_seq CASCADE
+```
+
+For a complete list of DSL functions, see the [DSL reference](/documentation/api/lib/postgresql/namespaces/flow-postgresql-dsl.html).
diff --git a/documentation/components/libs/postgresql/table-query-builder.md b/documentation/components/libs/postgresql/table-query-builder.md
new file mode 100644
index 000000000..2773cfc46
--- /dev/null
+++ b/documentation/components/libs/postgresql/table-query-builder.md
@@ -0,0 +1,709 @@
+# Table Query Builder
+
+- [⬅️ Back](/documentation/components/libs/postgresql.md)
+
+[TOC]
+
+The Table Query Builder provides a fluent, type-safe interface for constructing PostgreSQL DDL statements: CREATE TABLE, ALTER TABLE, DROP TABLE, TRUNCATE, and CREATE TABLE AS.
+
+## CREATE TABLE
+
+### Basic Table Creation
+
+```php
+table('users')
+ ->column(column('id', sql_type_serial())->primaryKey())
+ ->column(column('name', sql_type_varchar(100))->notNull());
+
+echo $query->toSQL();
+// CREATE TABLE users (id serial PRIMARY KEY, name varchar(100) NOT NULL)
+```
+
+### Table with Schema
+
+```php
+table('users', 'public')
+ ->column(column('id', sql_type_serial())->primaryKey());
+
+echo $query->toSQL();
+// CREATE TABLE public.users (id serial PRIMARY KEY)
+```
+
+### IF NOT EXISTS
+
+```php
+table('users')
+ ->ifNotExists()
+ ->column(column('id', sql_type_serial())->primaryKey());
+
+echo $query->toSQL();
+// CREATE TABLE IF NOT EXISTS users (id serial PRIMARY KEY)
+```
+
+### Column Definitions
+
+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'));
+
+echo $query->toSQL();
+// CREATE TABLE users (
+// id int GENERATED ALWAYS AS IDENTITY,
+// email varchar(255) NOT NULL UNIQUE,
+// active boolean DEFAULT true,
+// created_at timestamp DEFAULT CURRENT_TIMESTAMP
+// )
+```
+
+### Column with Foreign Key Reference
+
+```php
+table('orders')
+ ->column(column('id', sql_type_serial())->primaryKey())
+ ->column(column('user_id', sql_type_integer())->notNull()->references('users', 'id'));
+
+echo $query->toSQL();
+// CREATE TABLE orders (id serial PRIMARY KEY, user_id int NOT NULL REFERENCES users(id))
+```
+
+### Generated Columns
+
+```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"));
+
+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)
+```
+
+### Table-Level Constraints
+
+#### Primary Key
+
+```php
+table('order_items')
+ ->column(column('order_id', sql_type_integer())->notNull())
+ ->column(column('product_id', sql_type_integer())->notNull())
+ ->constraint(primary_key('order_id', 'product_id'));
+
+echo $query->toSQL();
+// CREATE TABLE order_items (order_id int NOT NULL, product_id int NOT NULL, PRIMARY KEY (order_id, product_id))
+```
+
+#### Unique Constraint
+
+```php
+table('users')
+ ->column(column('id', sql_type_serial())->primaryKey())
+ ->column(column('email', sql_type_varchar(255))->notNull())
+ ->constraint(unique_constraint('email'));
+
+echo $query->toSQL();
+// CREATE TABLE users (id serial PRIMARY KEY, email varchar(255) NOT NULL, UNIQUE (email))
+```
+
+#### Check Constraint
+
+```php
+table('products')
+ ->column(column('id', sql_type_serial())->primaryKey())
+ ->column(column('price', sql_type_integer()))
+ ->constraint(check_constraint('price > 0')->name('positive_price'));
+
+echo $query->toSQL();
+// CREATE TABLE products (id serial PRIMARY KEY, price int, CONSTRAINT positive_price CHECK (price > 0))
+```
+
+#### Foreign Key Constraint
+
+```php
+table('orders')
+ ->column(column('id', sql_type_serial())->primaryKey())
+ ->column(column('user_id', sql_type_integer())->notNull())
+ ->constraint(
+ foreign_key(['user_id'], 'users', ['id'])
+ ->onDelete(ref_action_cascade())
+ ->onUpdate(ref_action_restrict())
+ );
+
+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)
+```
+
+### Temporary Tables
+
+```php
+table('temp_results')
+ ->temporary()
+ ->column(column('id', sql_type_integer()));
+
+echo $query->toSQL();
+// CREATE TEMPORARY TABLE temp_results (id int) ON COMMIT DROP
+```
+
+### Unlogged Tables
+
+```php
+table('cache_data')
+ ->unlogged()
+ ->column(column('id', sql_type_integer()));
+
+echo $query->toSQL();
+// CREATE UNLOGGED TABLE cache_data (id int)
+```
+
+### Table Inheritance
+
+```php
+table('employees')
+ ->column(column('department', sql_type_varchar(100)))
+ ->inherits('persons');
+
+echo $query->toSQL();
+// CREATE TABLE employees (department varchar(100)) INHERITS (persons)
+```
+
+### Partitioned Tables
+
+```php
+table('logs')
+ ->column(column('id', sql_type_integer()))
+ ->column(column('created_at', sql_type_timestamp()))
+ ->partitionByRange('created_at');
+
+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)))
+ ->partitionByList('region');
+
+// Hash partitioning
+$query = create()->table('data')
+ ->column(column('id', sql_type_integer()))
+ ->partitionByHash('id');
+```
+
+## CREATE TABLE AS
+
+### Basic CREATE TABLE AS
+
+```php
+select(col('id'), col('name'))
+ ->from(table('users'));
+
+$query = create()->tableAs('users_backup', $selectQuery);
+
+echo $query->toSQL();
+// CREATE TABLE users_backup AS SELECT id, name FROM users
+```
+
+### With IF NOT EXISTS
+
+```php
+select(col('id'), col('name'))
+ ->from(table('users'));
+
+$query = create()->tableAs('users_backup', $selectQuery)
+ ->ifNotExists();
+
+echo $query->toSQL();
+// CREATE TABLE IF NOT EXISTS users_backup AS SELECT id, name FROM users
+```
+
+### With Column Names
+
+```php
+select(col('id'), col('name'))
+ ->from(table('users'));
+
+$query = create()->tableAs('users_backup', $selectQuery)
+ ->columnNames('user_id', 'user_name');
+
+echo $query->toSQL();
+// CREATE TABLE users_backup(user_id, user_name) AS SELECT id, name FROM users
+```
+
+### Structure Only (No Data)
+
+```php
+select(col('id'), col('name'))
+ ->from(table('users'));
+
+$query = create()->tableAs('users_backup', $selectQuery)
+ ->withNoData();
+
+echo $query->toSQL();
+// CREATE TABLE users_backup AS SELECT id, name FROM users WITH NO DATA
+```
+
+## ALTER TABLE
+
+### Add Column
+
+```php
+table('users')
+ ->addColumn(column('email', sql_type_varchar(255))->notNull());
+
+echo $query->toSQL();
+// ALTER TABLE users ADD COLUMN email varchar(255) NOT NULL
+```
+
+### Drop Column
+
+```php
+table('users')
+ ->dropColumn('temp_column');
+
+echo $query->toSQL();
+// ALTER TABLE users DROP temp_column
+
+// With CASCADE
+$query = alter()->table('users')
+ ->dropColumn('temp_column', cascade: true);
+
+echo $query->toSQL();
+// ALTER TABLE users DROP temp_column CASCADE
+```
+
+### Alter Column Type
+
+```php
+table('users')
+ ->alterColumnType('name', sql_type_text());
+
+echo $query->toSQL();
+// ALTER TABLE users ALTER COLUMN name TYPE pg_catalog.text
+```
+
+### Set/Drop NOT NULL
+
+```php
+table('users')
+ ->alterColumnSetNotNull('email');
+
+echo $query->toSQL();
+// ALTER TABLE users ALTER COLUMN email SET NOT NULL
+
+// Drop NOT NULL
+$query = alter()->table('users')
+ ->alterColumnDropNotNull('email');
+
+echo $query->toSQL();
+// ALTER TABLE users ALTER COLUMN email DROP NOT NULL
+```
+
+### Set/Drop Default
+
+```php
+table('users')
+ ->alterColumnSetDefault('status', "'active'");
+
+echo $query->toSQL();
+// ALTER TABLE users ALTER COLUMN status SET DEFAULT 'active'
+
+// Drop default
+$query = alter()->table('users')
+ ->alterColumnDropDefault('status');
+
+echo $query->toSQL();
+// ALTER TABLE users ALTER COLUMN status DROP DEFAULT
+```
+
+### Add Constraint
+
+```php
+table('users')
+ ->addConstraint(unique_constraint('email')->name('users_email_unique'));
+
+echo $query->toSQL();
+// ALTER TABLE users ADD CONSTRAINT users_email_unique UNIQUE (email)
+```
+
+### Drop Constraint
+
+```php
+table('users')
+ ->dropConstraint('users_email_unique');
+
+echo $query->toSQL();
+// ALTER TABLE users DROP CONSTRAINT users_email_unique
+```
+
+### Multiple Operations
+
+```php
+table('users')
+ ->addColumn(column('phone', sql_type_varchar(20)))
+ ->dropColumn('fax')
+ ->alterColumnSetNotNull('email');
+
+echo $query->toSQL();
+// ALTER TABLE users ADD COLUMN phone varchar(20), DROP fax, ALTER COLUMN email SET NOT NULL
+```
+
+### IF EXISTS
+
+```php
+table('users')
+ ->ifExists()
+ ->addColumn(column('email', sql_type_varchar(255)));
+
+echo $query->toSQL();
+// ALTER TABLE IF EXISTS users ADD COLUMN email varchar(255)
+```
+
+### Rename Column
+
+```php
+table('users')
+ ->renameColumn('old_name', 'new_name');
+
+echo $query->toSQL();
+// ALTER TABLE users RENAME COLUMN old_name TO new_name
+```
+
+### Rename Constraint
+
+```php
+table('users')
+ ->renameConstraint('old_constraint', 'new_constraint');
+
+echo $query->toSQL();
+// ALTER TABLE users RENAME CONSTRAINT old_constraint TO new_constraint
+```
+
+### Rename Table
+
+```php
+table('users')
+ ->renameTo('users_archive');
+
+echo $query->toSQL();
+// ALTER TABLE users RENAME TO users_archive
+```
+
+### Set Schema
+
+```php
+table('users')
+ ->setSchema('archive');
+
+echo $query->toSQL();
+// ALTER TABLE users SET SCHEMA archive
+```
+
+## DROP TABLE
+
+### Simple Drop
+
+```php
+table('users');
+
+echo $query->toSQL();
+// DROP TABLE users
+```
+
+### IF EXISTS
+
+```php
+table('users')
+ ->ifExists();
+
+echo $query->toSQL();
+// DROP TABLE IF EXISTS users
+```
+
+### CASCADE
+
+```php
+table('users')
+ ->cascade();
+
+echo $query->toSQL();
+// DROP TABLE users CASCADE
+```
+
+### Multiple Tables
+
+```php
+table('users', 'orders', 'products');
+
+echo $query->toSQL();
+// DROP TABLE users, orders, products
+```
+
+## TRUNCATE
+
+### Simple Truncate
+
+```php
+toSQL();
+// TRUNCATE users
+```
+
+### Multiple Tables
+
+```php
+toSQL();
+// TRUNCATE users, orders, products
+```
+
+### Restart Identity
+
+```php
+restartIdentity();
+
+echo $query->toSQL();
+// TRUNCATE users RESTART IDENTITY
+```
+
+### CASCADE
+
+```php
+cascade();
+
+echo $query->toSQL();
+// TRUNCATE users CASCADE
+```
+
+## Data Types
+
+The following SQL type functions are available:
+
+### Numeric Types
+
+| 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 |
+
+### String Types
+
+| Function | PostgreSQL Type |
+|----------|-----------------|
+| `sql_type_text()` | text |
+| `sql_type_varchar($length)` | varchar(n) |
+| `sql_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 |
+
+### 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[] |
+
+## Referential Actions
+
+The following referential action functions are available for foreign key constraints:
+
+| Function | Action |
+|----------|--------|
+| `ref_action_cascade()` | CASCADE |
+| `ref_action_restrict()` | RESTRICT |
+| `ref_action_no_action()` | NO ACTION |
+| `ref_action_set_null()` | SET NULL |
+| `ref_action_set_default()` | SET DEFAULT |
+
+For a complete list of DSL functions, see the [DSL reference](/documentation/api/lib/postgresql/namespaces/flow-postgresql-dsl.html).
diff --git a/documentation/components/libs/postgresql/transaction-query-builder.md b/documentation/components/libs/postgresql/transaction-query-builder.md
new file mode 100644
index 000000000..61102841a
--- /dev/null
+++ b/documentation/components/libs/postgresql/transaction-query-builder.md
@@ -0,0 +1,320 @@
+# Transaction Query Builder
+
+- [⬅️ Back](/documentation/components/libs/postgresql.md)
+
+[TOC]
+
+The Transaction Query Builder provides a fluent, type-safe interface for constructing PostgreSQL transaction control statements. It supports BEGIN, COMMIT, ROLLBACK, SAVEPOINT, SET TRANSACTION, and two-phase commit operations.
+
+## BEGIN
+
+### Basic BEGIN
+
+```php
+toSQL();
+// BEGIN
+```
+
+### BEGIN with Isolation Level
+
+```php
+isolationLevel(IsolationLevel::SERIALIZABLE);
+
+echo $query->toSQL();
+// BEGIN ISOLATION LEVEL SERIALIZABLE
+```
+
+### BEGIN with Read Mode
+
+```php
+readOnly();
+
+echo $query->toSQL();
+// BEGIN READ ONLY
+
+// Read-write transaction (explicit)
+$query = begin()
+ ->readWrite();
+
+echo $query->toSQL();
+// BEGIN READ WRITE
+```
+
+### BEGIN with Deferrable
+
+Deferrable transactions are useful for long-running read-only queries that need SERIALIZABLE isolation:
+
+```php
+isolationLevel(IsolationLevel::SERIALIZABLE)
+ ->readOnly()
+ ->deferrable();
+
+echo $query->toSQL();
+// BEGIN ISOLATION LEVEL SERIALIZABLE, READ ONLY, DEFERRABLE
+```
+
+## COMMIT
+
+### Basic COMMIT
+
+```php
+toSQL();
+// COMMIT
+```
+
+### COMMIT AND CHAIN
+
+Start a new transaction with the same characteristics immediately after committing:
+
+```php
+andChain();
+
+echo $query->toSQL();
+// COMMIT AND CHAIN
+```
+
+## ROLLBACK
+
+### Basic ROLLBACK
+
+```php
+toSQL();
+// ROLLBACK
+```
+
+### ROLLBACK TO SAVEPOINT
+
+Roll back to a specific savepoint:
+
+```php
+toSavepoint('my_savepoint');
+
+echo $query->toSQL();
+// ROLLBACK TO SAVEPOINT my_savepoint
+```
+
+### ROLLBACK AND CHAIN
+
+```php
+andChain();
+
+echo $query->toSQL();
+// ROLLBACK AND CHAIN
+```
+
+## SAVEPOINT
+
+### Create a Savepoint
+
+```php
+toSQL();
+// SAVEPOINT my_savepoint
+```
+
+### Release a Savepoint
+
+```php
+toSQL();
+// RELEASE my_savepoint
+```
+
+## SET TRANSACTION
+
+### Set Transaction Isolation Level
+
+```php
+isolationLevel(IsolationLevel::SERIALIZABLE);
+
+echo $query->toSQL();
+// SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
+```
+
+### Set Transaction Read Mode
+
+```php
+readOnly();
+
+echo $query->toSQL();
+// SET TRANSACTION READ ONLY
+```
+
+### Set Multiple Transaction Options
+
+```php
+isolationLevel(IsolationLevel::SERIALIZABLE)
+ ->readOnly()
+ ->deferrable();
+
+echo $query->toSQL();
+// SET TRANSACTION ISOLATION LEVEL SERIALIZABLE, READ ONLY, DEFERRABLE
+```
+
+### Set Session Transaction Defaults
+
+Set default transaction characteristics for the session:
+
+```php
+isolationLevel(IsolationLevel::SERIALIZABLE);
+
+echo $query->toSQL();
+// SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE
+```
+
+### Transaction Snapshot
+
+Import a snapshot from another session (for parallel queries):
+
+```php
+toSQL();
+// SET TRANSACTION SNAPSHOT '00000003-0000001A-1'
+```
+
+## Two-Phase Commit (Prepared Transactions)
+
+Two-phase commit is useful for distributed transactions across multiple databases.
+
+### Prepare Transaction
+
+```php
+toSQL();
+// PREPARE TRANSACTION 'my_transaction'
+```
+
+### Commit Prepared
+
+```php
+toSQL();
+// COMMIT PREPARED 'my_transaction'
+```
+
+### Rollback Prepared
+
+```php
+toSQL();
+// ROLLBACK PREPARED 'my_transaction'
+```
+
+## Isolation Levels
+
+The `IsolationLevel` enum provides four standard SQL isolation levels:
+
+| Level | Description |
+|-------|-------------|
+| `IsolationLevel::READ_UNCOMMITTED` | Allows dirty reads (treated as READ COMMITTED in PostgreSQL) |
+| `IsolationLevel::READ_COMMITTED` | Default level. Only sees committed data |
+| `IsolationLevel::REPEATABLE_READ` | Sees a snapshot from transaction start |
+| `IsolationLevel::SERIALIZABLE` | Strictest level. Transactions appear to execute serially |
+
+## DSL Functions Reference
+
+For a complete list of DSL functions, see the [DSL reference](/documentation/api/lib/postgresql/namespaces/flow-postgresql-dsl.html).
diff --git a/documentation/components/libs/postgresql/trigger-rule-query-builder.md b/documentation/components/libs/postgresql/trigger-rule-query-builder.md
new file mode 100644
index 000000000..b78b850df
--- /dev/null
+++ b/documentation/components/libs/postgresql/trigger-rule-query-builder.md
@@ -0,0 +1,323 @@
+# Trigger and Rule Query Builder
+
+This document describes the PostgreSQL Trigger and Rule Query Builder components.
+
+## Trigger Commands
+
+### CREATE TRIGGER
+
+Create triggers using the `create_trigger()` DSL function:
+
+```php
+use function Flow\PostgreSql\DSL\create;
+use Flow\PostgreSql\QueryBuilder\Schema\Trigger\TriggerEvent;
+
+// Basic AFTER INSERT trigger
+$builder = create()->trigger('audit_trigger')
+ ->after(TriggerEvent::INSERT)
+ ->on('users')
+ ->execute('audit_function');
+// CREATE TRIGGER audit_trigger AFTER INSERT ON users EXECUTE FUNCTION audit_function()
+
+// Multiple events with FOR EACH ROW
+$builder = create()->trigger('changes_trigger')
+ ->after(TriggerEvent::INSERT, TriggerEvent::UPDATE, TriggerEvent::DELETE)
+ ->on('orders')
+ ->forEachRow()
+ ->execute('track_changes');
+// CREATE TRIGGER changes_trigger AFTER INSERT OR UPDATE OR DELETE ON orders FOR EACH ROW EXECUTE FUNCTION track_changes()
+
+// BEFORE trigger on specific columns
+$builder = create()->trigger('track_status')
+ ->beforeUpdateOf('status', 'priority')
+ ->on('tickets')
+ ->forEachRow()
+ ->execute('log_status_change');
+// CREATE TRIGGER track_status BEFORE UPDATE OF status, priority ON tickets FOR EACH ROW EXECUTE FUNCTION log_status_change()
+
+// INSTEAD OF trigger (for views)
+$builder = create()->trigger('view_insert')
+ ->insteadOf(TriggerEvent::INSERT)
+ ->on('users_view')
+ ->forEachRow()
+ ->execute('handle_insert');
+// CREATE TRIGGER view_insert INSTEAD OF INSERT ON users_view FOR EACH ROW EXECUTE FUNCTION handle_insert()
+
+// With WHEN condition
+$builder = create()->trigger('protect_admin')
+ ->before(TriggerEvent::DELETE)
+ ->on('users')
+ ->forEachRow()
+ ->when(raw_cond('OLD.role = \'admin\''))
+ ->execute('raise_error');
+// CREATE TRIGGER protect_admin BEFORE DELETE ON users FOR EACH ROW WHEN (old.role = 'admin') EXECUTE FUNCTION raise_error()
+
+// OR REPLACE
+$builder = create()->trigger('my_trigger')
+ ->orReplace()
+ ->after(TriggerEvent::INSERT)
+ ->on('users')
+ ->execute('my_function');
+// CREATE OR REPLACE TRIGGER my_trigger AFTER INSERT ON users EXECUTE FUNCTION my_function()
+
+// Constraint trigger with deferrable
+$builder = create()->trigger('fk_check')
+ ->constraint()
+ ->after(TriggerEvent::INSERT)
+ ->on('orders')
+ ->from('users')
+ ->deferrable()
+ ->initiallyDeferred()
+ ->forEachRow()
+ ->execute('check_foreign_key');
+// CREATE CONSTRAINT TRIGGER fk_check AFTER INSERT ON orders FROM users DEFERRABLE INITIALLY DEFERRED FOR EACH ROW EXECUTE FUNCTION check_foreign_key()
+
+// With REFERENCING (transition tables)
+$builder = create()->trigger('batch_process')
+ ->after(TriggerEvent::INSERT)
+ ->on('events')
+ ->referencingNewTableAs('new_events')
+ ->referencingOldTableAs('old_events')
+ ->forEachStatement()
+ ->execute('process_batch');
+// CREATE TRIGGER batch_process AFTER INSERT ON events REFERENCING NEW TABLE new_events OLD TABLE old_events EXECUTE FUNCTION process_batch()
+```
+
+### ALTER TRIGGER
+
+Rename triggers or manage extension dependencies:
+
+```php
+use function Flow\PostgreSql\DSL\alter;
+
+// Rename trigger
+$builder = alter()->trigger('old_name')
+ ->on('users')
+ ->renameTo('new_name');
+// ALTER TRIGGER old_name ON users RENAME TO new_name
+
+// Depends on extension
+$builder = alter()->trigger('my_trigger')
+ ->on('users')
+ ->dependsOnExtension('my_extension');
+// ALTER TRIGGER my_trigger ON users DEPENDS ON EXTENSION my_extension
+
+// Remove dependency on extension
+$builder = alter()->trigger('my_trigger')
+ ->on('users')
+ ->noDependsOnExtension('my_extension');
+// ALTER TRIGGER my_trigger ON users NO DEPENDS ON EXTENSION my_extension
+```
+
+### DROP TRIGGER
+
+Drop triggers with optional IF EXISTS and CASCADE/RESTRICT:
+
+```php
+use function Flow\PostgreSql\DSL\drop;
+
+// Basic drop
+$builder = drop()->trigger('audit_trigger')->on('users');
+// DROP TRIGGER audit_trigger ON users
+
+// With IF EXISTS
+$builder = drop()->trigger('audit_trigger')
+ ->ifExists()
+ ->on('users');
+// DROP TRIGGER IF EXISTS audit_trigger ON users
+
+// With CASCADE
+$builder = drop()->trigger('audit_trigger')
+ ->on('users')
+ ->cascade();
+// DROP TRIGGER audit_trigger ON users CASCADE
+
+// With schema
+$builder = drop()->trigger('audit_trigger')
+ ->on('public.users')
+ ->restrict();
+// DROP TRIGGER audit_trigger ON public.users
+```
+
+### ENABLE/DISABLE TRIGGER
+
+Use `alter()->table()` to enable or disable triggers:
+
+```php
+use function Flow\PostgreSql\DSL\alter;
+
+// Enable trigger
+$builder = alter()->table('users')->enableTrigger('audit_trigger');
+// ALTER TABLE users ENABLE TRIGGER audit_trigger
+
+// Enable all triggers
+$builder = alter()->table('users')->enableTriggerAll();
+// ALTER TABLE users ENABLE TRIGGER ALL
+
+// Enable user triggers only
+$builder = alter()->table('users')->enableTriggerUser();
+// ALTER TABLE users ENABLE TRIGGER USER
+
+// Enable always (fires even during replication)
+$builder = alter()->table('users')->enableTriggerAlways('critical_trigger');
+// ALTER TABLE users ENABLE ALWAYS TRIGGER critical_trigger
+
+// Enable replica (fires only during replication)
+$builder = alter()->table('users')->enableTriggerReplica('sync_trigger');
+// ALTER TABLE users ENABLE REPLICA TRIGGER sync_trigger
+
+// Disable trigger
+$builder = alter()->table('users')->disableTrigger('audit_trigger');
+// ALTER TABLE users DISABLE TRIGGER audit_trigger
+
+// Disable all triggers
+$builder = alter()->table('users')->disableTriggerAll();
+// ALTER TABLE users DISABLE TRIGGER ALL
+
+// Disable user triggers only
+$builder = alter()->table('users')->disableTriggerUser();
+// ALTER TABLE users DISABLE TRIGGER USER
+```
+
+## Rule Commands
+
+### CREATE RULE
+
+Create rules using the `create_rule()` DSL function:
+
+```php
+use function Flow\PostgreSql\DSL\create;
+
+// DO NOTHING rule
+$builder = create()->rule('prevent_delete')
+ ->asOnDelete()
+ ->to('users')
+ ->doNothing();
+// CREATE RULE prevent_delete AS ON DELETE TO users DO NOTHING
+
+// DO INSTEAD rule
+$builder = create()->rule('soft_delete')
+ ->asOnDelete()
+ ->to('users')
+ ->doInstead("UPDATE users SET deleted = true WHERE id = OLD.id");
+// CREATE RULE soft_delete AS ON DELETE TO users DO INSTEAD UPDATE users SET deleted = true WHERE id = old.id
+
+// DO ALSO rule (additional action)
+$builder = create()->rule('audit_insert')
+ ->asOnInsert()
+ ->to('orders')
+ ->doAlso("INSERT INTO audit_log (action) VALUES ('insert')");
+// CREATE RULE audit_insert AS ON INSERT TO orders DO INSERT INTO audit_log (action) VALUES ('insert')
+
+// With WHERE condition
+$builder = create()->rule('protect_admin')
+ ->asOnDelete()
+ ->to('users')
+ ->where('OLD.role = \'admin\'')
+ ->doNothing();
+// CREATE RULE protect_admin AS ON DELETE TO users WHERE old.role = 'admin' DO NOTHING
+
+// OR REPLACE
+$builder = create()->rule('my_rule')
+ ->orReplace()
+ ->asOnUpdate()
+ ->to('users')
+ ->doNothing();
+// CREATE OR REPLACE RULE my_rule AS ON UPDATE TO users DO NOTHING
+
+// On SELECT (for views)
+$builder = create()->rule('redirect_select')
+ ->asOnSelect()
+ ->to('old_view')
+ ->doInstead('SELECT * FROM new_table');
+// CREATE RULE redirect_select AS ON SELECT TO old_view DO INSTEAD SELECT * FROM new_table
+
+// With schema
+$builder = create()->rule('audit_rule')
+ ->asOnInsert()
+ ->to('public.users')
+ ->doAlso("INSERT INTO audit VALUES ('insert')");
+// CREATE RULE audit_rule AS ON INSERT TO public.users DO INSERT INTO audit VALUES ('insert')
+```
+
+### DROP RULE
+
+Drop rules with optional IF EXISTS and CASCADE/RESTRICT:
+
+```php
+use function Flow\PostgreSql\DSL\drop;
+
+// Basic drop
+$builder = drop()->rule('prevent_delete')->on('users');
+// DROP RULE prevent_delete ON users
+
+// With IF EXISTS
+$builder = drop()->rule('prevent_delete')
+ ->ifExists()
+ ->on('users');
+// DROP RULE IF EXISTS prevent_delete ON users
+
+// With CASCADE
+$builder = drop()->rule('prevent_delete')
+ ->on('users')
+ ->cascade();
+// DROP RULE prevent_delete ON users CASCADE
+
+// With schema
+$builder = drop()->rule('audit_rule')
+ ->on('public.users')
+ ->restrict();
+// DROP RULE audit_rule ON public.users
+```
+
+## Enums
+
+### TriggerTiming
+
+```php
+use Flow\PostgreSql\QueryBuilder\Schema\Trigger\TriggerTiming;
+
+TriggerTiming::BEFORE; // BEFORE timing
+TriggerTiming::AFTER; // AFTER timing
+TriggerTiming::INSTEAD_OF; // INSTEAD OF timing (for views)
+```
+
+### TriggerEvent
+
+```php
+use Flow\PostgreSql\QueryBuilder\Schema\Trigger\TriggerEvent;
+
+TriggerEvent::INSERT; // INSERT event
+TriggerEvent::UPDATE; // UPDATE event
+TriggerEvent::DELETE; // DELETE event
+TriggerEvent::TRUNCATE; // TRUNCATE event
+```
+
+### TriggerLevel
+
+```php
+use Flow\PostgreSql\QueryBuilder\Schema\Trigger\TriggerLevel;
+
+TriggerLevel::ROW; // FOR EACH ROW
+TriggerLevel::STATEMENT; // FOR EACH STATEMENT (default)
+```
+
+### RuleEvent
+
+```php
+use Flow\PostgreSql\QueryBuilder\Schema\Rule\RuleEvent;
+
+RuleEvent::SELECT; // ON SELECT
+RuleEvent::INSERT; // ON INSERT
+RuleEvent::UPDATE; // ON UPDATE
+RuleEvent::DELETE; // ON DELETE
+```
+
+### RuleAction
+
+```php
+use Flow\PostgreSql\QueryBuilder\Schema\Rule\RuleAction;
+
+RuleAction::ALSO; // DO ALSO
+RuleAction::INSTEAD; // DO INSTEAD
+```
diff --git a/documentation/components/libs/postgresql/type-query-builder.md b/documentation/components/libs/postgresql/type-query-builder.md
new file mode 100644
index 000000000..e1f02cf42
--- /dev/null
+++ b/documentation/components/libs/postgresql/type-query-builder.md
@@ -0,0 +1,344 @@
+# Type Query Builder
+
+- [Back](/documentation/components/libs/postgresql.md)
+
+[TOC]
+
+The Type Query Builder provides a fluent, type-safe interface for constructing PostgreSQL type management statements:
+CREATE TYPE (composite, enum, range), ALTER TYPE, and DROP TYPE.
+
+## CREATE TYPE (Composite)
+
+### Basic Composite Type
+
+```php
+compositeType('address')
+ ->attributes(
+ type_attr('street', 'text'),
+ type_attr('city', 'text'),
+ type_attr('zip', 'text')
+ );
+
+echo $query->toSQL();
+// CREATE TYPE address AS (street text, city text, zip text)
+```
+
+### With Schema
+
+```php
+compositeType('public.address')
+ ->attributes(
+ type_attr('street', 'text')
+ );
+
+echo $query->toSQL();
+// CREATE TYPE public.address AS (street text)
+```
+
+### With Collation
+
+```php
+compositeType('person')
+ ->attributes(
+ type_attr('name', 'text')->collate('en_US')
+ );
+
+echo $query->toSQL();
+// CREATE TYPE person AS (name text COLLATE "en_US")
+```
+
+## CREATE TYPE (Enum)
+
+### Basic Enum Type
+
+```php
+enumType('status')
+ ->labels('pending', 'active', 'closed');
+
+echo $query->toSQL();
+// CREATE TYPE status AS ENUM ('pending', 'active', 'closed')
+```
+
+### With Schema
+
+```php
+enumType('public.status')
+ ->labels('pending', 'active');
+
+echo $query->toSQL();
+// CREATE TYPE public.status AS ENUM ('pending', 'active')
+```
+
+## CREATE TYPE (Range)
+
+### Basic Range Type
+
+```php
+rangeType('floatrange')
+ ->subtype('float8');
+
+echo $query->toSQL();
+// CREATE TYPE floatrange AS RANGE (subtype = float8)
+```
+
+### With Schema
+
+```php
+rangeType('public.floatrange')
+ ->subtype('float8');
+
+echo $query->toSQL();
+// CREATE TYPE public.floatrange AS RANGE (subtype = float8)
+```
+
+### With Subtype Operator Class
+
+```php
+rangeType('floatrange')
+ ->subtype('float8')
+ ->subtypeOpclass('float8_ops');
+
+echo $query->toSQL();
+// CREATE TYPE floatrange AS RANGE (subtype = float8, subtype_opclass = 'float8_ops')
+```
+
+### With Collation
+
+```php
+rangeType('textrange')
+ ->subtype('text')
+ ->collation('en_US');
+
+echo $query->toSQL();
+// CREATE TYPE textrange AS RANGE (subtype = text, "collation" = 'en_US')
+```
+
+### With Canonical Function
+
+```php
+rangeType('daterange')
+ ->subtype('date')
+ ->canonical('daterange_canonical');
+
+echo $query->toSQL();
+// CREATE TYPE daterange AS RANGE (subtype = date, canonical = 'daterange_canonical')
+```
+
+### With Subtype Diff Function
+
+```php
+rangeType('floatrange')
+ ->subtype('float8')
+ ->subtypeDiff('float8mi');
+
+echo $query->toSQL();
+// CREATE TYPE floatrange AS RANGE (subtype = float8, subtype_diff = 'float8mi')
+```
+
+## ALTER TYPE (Enum)
+
+### Add Value
+
+```php
+enumType('status')
+ ->addValue('archived');
+
+echo $query->toSQL();
+// ALTER TYPE status ADD VALUE 'archived'
+```
+
+### Add Value IF NOT EXISTS
+
+```php
+enumType('status')
+ ->addValue('archived')
+ ->ifNotExists();
+
+echo $query->toSQL();
+// ALTER TYPE status ADD VALUE IF NOT EXISTS 'archived'
+```
+
+### Add Value BEFORE
+
+```php
+enumType('status')
+ ->addValueBefore('pending', 'active');
+
+echo $query->toSQL();
+// ALTER TYPE status ADD VALUE 'pending' BEFORE 'active'
+```
+
+### Add Value AFTER
+
+```php
+enumType('status')
+ ->addValueAfter('archived', 'closed');
+
+echo $query->toSQL();
+// ALTER TYPE status ADD VALUE 'archived' AFTER 'closed'
+```
+
+### Rename Value
+
+```php
+enumType('status')
+ ->renameValue('old_name', 'new_name');
+
+echo $query->toSQL();
+// ALTER TYPE status RENAME VALUE 'old_name' TO 'new_name'
+```
+
+## DROP TYPE
+
+### Simple Drop
+
+```php
+type('address');
+
+echo $query->toSQL();
+// DROP TYPE address
+```
+
+### IF EXISTS
+
+```php
+type('address')
+ ->ifExists();
+
+echo $query->toSQL();
+// DROP TYPE IF EXISTS address
+```
+
+### CASCADE
+
+Drop all objects that depend on the type:
+
+```php
+type('address')
+ ->cascade();
+
+echo $query->toSQL();
+// DROP TYPE address CASCADE
+```
+
+### RESTRICT
+
+Refuse to drop the type if any objects depend on it (default behavior):
+
+```php
+type('address')
+ ->restrict();
+
+echo $query->toSQL();
+// DROP TYPE address
+```
+
+### Multiple Types
+
+```php
+type('address', 'status', 'floatrange');
+
+echo $query->toSQL();
+// DROP TYPE address, status, floatrange
+```
+
+### Combined Options
+
+```php
+type('address')
+ ->ifExists()
+ ->cascade();
+
+echo $query->toSQL();
+// DROP TYPE IF EXISTS address CASCADE
+```
+
+For a complete list of DSL functions, see the [DSL reference](/documentation/api/lib/postgresql/namespaces/flow-postgresql-dsl.html).
diff --git a/documentation/components/libs/postgresql/update-query-builder.md b/documentation/components/libs/postgresql/update-query-builder.md
new file mode 100644
index 000000000..d3ca6055c
--- /dev/null
+++ b/documentation/components/libs/postgresql/update-query-builder.md
@@ -0,0 +1,199 @@
+# Update Query Builder
+
+- [⬅️ Back](/documentation/components/libs/postgresql.md)
+
+[TOC]
+
+The Update Query Builder provides a fluent, type-safe interface for constructing PostgreSQL UPDATE queries. It supports simple updates, updates with FROM clause (join-like behavior), complex WHERE conditions, and RETURNING clauses.
+
+## Simple Update
+
+```php
+update('users')
+ ->set('name', literal('John'))
+ ->where(eq(col('id'), literal(1)));
+
+echo $query->toSQL();
+// UPDATE users SET name = 'John' WHERE id = 1
+```
+
+## Update with Parameters
+
+Use positional parameters for prepared statements:
+
+```php
+update('users')
+ ->set('name', param(1))
+ ->where(eq(col('id'), param(2)));
+
+echo $query->toSQL();
+// UPDATE users SET name = $1 WHERE id = $2
+```
+
+## Multiple SET Clauses
+
+```php
+update('users')
+ ->set('name', literal('John'))
+ ->set('email', literal('john@example.com'))
+ ->where(eq(col('id'), literal(1)));
+
+echo $query->toSQL();
+// UPDATE users SET name = 'John', email = 'john@example.com' WHERE id = 1
+
+// Or use setAll() for multiple columns at once
+$query = update()
+ ->update('users')
+ ->setAll([
+ 'name' => literal('John'),
+ 'email' => literal('john@example.com'),
+ ])
+ ->where(eq(col('id'), literal(1)));
+
+echo $query->toSQL();
+// UPDATE users SET name = 'John', email = 'john@example.com' WHERE id = 1
+```
+
+## Update with Table Alias
+
+```php
+update('users', 'u')
+ ->set('name', literal('John'))
+ ->where(eq(col('u.id'), literal(1)));
+
+echo $query->toSQL();
+// UPDATE users u SET name = 'John' WHERE u.id = 1
+```
+
+## Update with FROM Clause (Join-like)
+
+The FROM clause allows you to reference other tables in your UPDATE, similar to a JOIN:
+
+```php
+update('orders')
+ ->set('status', literal('completed'))
+ ->from(table('users'))
+ ->where(eq(col('orders.user_id'), col('users.id')));
+
+echo $query->toSQL();
+// UPDATE orders SET status = 'completed' FROM users WHERE orders.user_id = users.id
+```
+
+## Update with Subquery in SET
+
+```php
+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)));
+
+echo $query->toSQL();
+// UPDATE products SET price = (SELECT avg_price FROM price_stats WHERE category = products.category) WHERE id = 1
+```
+
+## Update Column with Another Column
+
+```php
+update('products')
+ ->set('price', col('original_price'))
+ ->where(eq(col('id'), literal(1)));
+
+echo $query->toSQL();
+// UPDATE products SET price = original_price WHERE id = 1
+```
+
+## RETURNING Clause
+
+```php
+update('users')
+ ->set('name', literal('John'))
+ ->where(eq(col('id'), literal(1)))
+ ->returning(col('id'), col('name'));
+
+echo $query->toSQL();
+// UPDATE users SET name = 'John' WHERE id = 1 RETURNING id, name
+
+// Return all columns
+$query = update()
+ ->update('users')
+ ->set('name', literal('John'))
+ ->where(eq(col('id'), literal(1)))
+ ->returningAll();
+
+echo $query->toSQL();
+// UPDATE users SET name = 'John' WHERE id = 1 RETURNING *
+```
+
+## Complex WHERE Conditions
+
+```php
+update('users')
+ ->set('status', literal('premium'))
+ ->where(
+ cond_and(
+ eq(col('active'), literal(true)),
+ gt(col('orders_count'), literal(100))
+ )
+ );
+
+echo $query->toSQL();
+// UPDATE users SET status = 'premium' WHERE active = true AND orders_count > 100
+```
+
+For a complete list of DSL functions, see the [DSL reference](/documentation/api/lib/postgresql/namespaces/flow-postgresql-dsl.html).
diff --git a/documentation/components/libs/postgresql/utility-query-builder.md b/documentation/components/libs/postgresql/utility-query-builder.md
new file mode 100644
index 000000000..a4fd6e021
--- /dev/null
+++ b/documentation/components/libs/postgresql/utility-query-builder.md
@@ -0,0 +1,731 @@
+# Utility Query Builder
+
+- [⬅️ Back](/documentation/components/libs/postgresql.md)
+
+[TOC]
+
+The Utility Query Builder provides a fluent, type-safe interface for constructing PostgreSQL utility statements. It supports VACUUM, ANALYZE, EXPLAIN, LOCK TABLE, COMMENT, CLUSTER, and DISCARD operations.
+
+## VACUUM
+
+VACUUM reclaims storage occupied by dead tuples and optionally updates planner statistics.
+
+### Basic VACUUM
+
+```php
+toSQL();
+// VACUUM
+```
+
+### VACUUM Single Table
+
+```php
+table('users');
+
+echo $query->toSQL();
+// VACUUM users
+```
+
+### VACUUM Multiple Tables
+
+```php
+tables('users', 'orders', 'products');
+
+echo $query->toSQL();
+// VACUUM users, orders, products
+```
+
+### VACUUM with Schema
+
+```php
+table('public.users');
+
+echo $query->toSQL();
+// VACUUM public.users
+```
+
+### VACUUM Specific Columns
+
+```php
+table('users', 'email', 'name');
+
+echo $query->toSQL();
+// VACUUM users (email, name)
+```
+
+### VACUUM FULL
+
+VACUUM FULL rewrites the entire table to reclaim maximum space:
+
+```php
+full()->tables('users');
+
+echo $query->toSQL();
+// VACUUM (FULL) users
+```
+
+### VACUUM ANALYZE
+
+VACUUM ANALYZE updates planner statistics after vacuuming:
+
+```php
+analyze()->tables('users');
+
+echo $query->toSQL();
+// VACUUM (ANALYZE) users
+```
+
+### VACUUM with Options
+
+```php
+full()
+ ->analyze()
+ ->verbose()
+ ->table('users');
+
+echo $query->toSQL();
+// VACUUM (FULL, FREEZE, VERBOSE, ANALYZE) users
+
+// Skip locked tables
+$query = vacuum()
+ ->skipLocked()
+ ->table('users');
+
+echo $query->toSQL();
+// VACUUM (SKIP_LOCKED) users
+
+// Parallel vacuum
+$query = vacuum()
+ ->parallel(4)
+ ->table('users');
+
+echo $query->toSQL();
+// VACUUM (PARALLEL 4) users
+
+// Index cleanup options
+$query = vacuum()
+ ->indexCleanup(IndexCleanup::OFF)
+ ->table('users');
+
+echo $query->toSQL();
+// VACUUM (INDEX_CLEANUP off) users
+
+// Process options
+$query = vacuum()
+ ->processMain(true)
+ ->processToast(false)
+ ->table('users');
+
+echo $query->toSQL();
+// VACUUM (PROCESS_MAIN true, PROCESS_TOAST false) users
+
+// Truncate option
+$query = vacuum()
+ ->truncate(true)
+ ->table('users');
+
+echo $query->toSQL();
+// VACUUM (TRUNCATE true) users
+
+// Freeze option
+$query = vacuum()
+ ->freeze()
+ ->table('users');
+
+echo $query->toSQL();
+// VACUUM (FREEZE) users
+
+// Disable page skipping
+$query = vacuum()
+ ->disablePageSkipping()
+ ->table('users');
+
+echo $query->toSQL();
+// VACUUM (DISABLE_PAGE_SKIPPING) users
+```
+
+## ANALYZE
+
+ANALYZE collects statistics about table contents for the query planner.
+
+### Basic ANALYZE
+
+```php
+toSQL();
+// ANALYZE
+```
+
+### ANALYZE Single Table
+
+```php
+table('users');
+
+echo $query->toSQL();
+// ANALYZE users
+```
+
+### ANALYZE with Columns
+
+```php
+table('users', 'email', 'name');
+
+echo $query->toSQL();
+// ANALYZE users (email, name)
+```
+
+### ANALYZE Multiple Tables
+
+```php
+tables('users', 'orders', 'products');
+
+echo $query->toSQL();
+// ANALYZE users, orders, products
+```
+
+### ANALYZE with Options
+
+```php
+verbose()
+ ->table('users');
+
+echo $query->toSQL();
+// ANALYZE (VERBOSE) users
+
+// Skip locked tables
+$query = analyze()
+ ->skipLocked()
+ ->table('users');
+
+echo $query->toSQL();
+// ANALYZE (SKIP_LOCKED) users
+```
+
+## EXPLAIN
+
+EXPLAIN shows the execution plan for a statement.
+
+### Basic EXPLAIN
+
+```php
+from('users'));
+
+echo $query->toSQL();
+// EXPLAIN SELECT * FROM users
+```
+
+### EXPLAIN ANALYZE
+
+EXPLAIN ANALYZE actually executes the query and shows real timing:
+
+```php
+from('users'))->analyze();
+
+echo $query->toSQL();
+// EXPLAIN (ANALYZE) SELECT * FROM users
+```
+
+### EXPLAIN with Verbose
+
+```php
+from('users'))
+ ->verbose();
+
+echo $query->toSQL();
+// EXPLAIN (VERBOSE) SELECT * FROM users
+```
+
+### EXPLAIN with Format
+
+```php
+from('users'))
+ ->format(ExplainFormat::JSON);
+
+echo $query->toSQL();
+// EXPLAIN (FORMAT json) SELECT * FROM users
+
+// XML format
+$query = explain(select()->from('users'))
+ ->format(ExplainFormat::XML);
+
+echo $query->toSQL();
+// EXPLAIN (FORMAT xml) SELECT * FROM users
+
+// YAML format
+$query = explain(select()->from('users'))
+ ->format(ExplainFormat::YAML);
+
+echo $query->toSQL();
+// EXPLAIN (FORMAT yaml) SELECT * FROM users
+```
+
+### EXPLAIN with Full Options
+
+```php
+from('users'))
+ ->analyze()
+ ->verbose()
+ ->buffers(true)
+ ->timing(true)
+ ->costs(true)
+ ->format(ExplainFormat::JSON);
+
+echo $query->toSQL();
+// EXPLAIN (ANALYZE, VERBOSE, BUFFERS true, TIMING true, COSTS true, FORMAT json) SELECT * FROM users
+```
+
+### EXPLAIN with Costs
+
+```php
+from('users'))
+ ->costs(true);
+
+echo $query->toSQL();
+// EXPLAIN (COSTS true) SELECT * FROM users
+
+// Without costs
+$query = explain(select()->from('users'))
+ ->costs(false);
+
+echo $query->toSQL();
+// EXPLAIN (COSTS false) SELECT * FROM users
+```
+
+## LOCK TABLE
+
+LOCK TABLE obtains a table-level lock for the current transaction.
+
+### Basic LOCK
+
+```php
+toSQL();
+// LOCK TABLE users
+```
+
+### LOCK with Mode
+
+```php
+accessShare();
+echo $query->toSQL();
+// LOCK TABLE users IN ACCESS SHARE MODE
+
+$query = lock_table('users')->rowShare();
+echo $query->toSQL();
+// LOCK TABLE users IN ROW SHARE MODE
+
+$query = lock_table('users')->rowExclusive();
+echo $query->toSQL();
+// LOCK TABLE users IN ROW EXCLUSIVE MODE
+
+$query = lock_table('users')->shareUpdateExclusive();
+echo $query->toSQL();
+// LOCK TABLE users IN SHARE UPDATE EXCLUSIVE MODE
+
+$query = lock_table('users')->share();
+echo $query->toSQL();
+// LOCK TABLE users IN SHARE MODE
+
+$query = lock_table('users')->shareRowExclusive();
+echo $query->toSQL();
+// LOCK TABLE users IN SHARE ROW EXCLUSIVE MODE
+
+$query = lock_table('users')->exclusive();
+echo $query->toSQL();
+// LOCK TABLE users IN EXCLUSIVE MODE
+
+$query = lock_table('users')->accessExclusive();
+echo $query->toSQL();
+// LOCK TABLE users IN ACCESS EXCLUSIVE MODE
+
+// Using enum
+$query = lock_table('users')->inMode(LockMode::EXCLUSIVE);
+echo $query->toSQL();
+// LOCK TABLE users IN EXCLUSIVE MODE
+```
+
+### LOCK Multiple Tables
+
+```php
+exclusive();
+
+echo $query->toSQL();
+// LOCK TABLE users, orders IN EXCLUSIVE MODE
+```
+
+### LOCK with NOWAIT
+
+```php
+exclusive()
+ ->nowait();
+
+echo $query->toSQL();
+// LOCK TABLE users IN EXCLUSIVE MODE NOWAIT
+```
+
+## Lock Modes
+
+| Mode | Conflicts With |
+|------|----------------|
+| `ACCESS SHARE` | ACCESS EXCLUSIVE |
+| `ROW SHARE` | EXCLUSIVE, ACCESS EXCLUSIVE |
+| `ROW EXCLUSIVE` | SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE, ACCESS EXCLUSIVE |
+| `SHARE UPDATE EXCLUSIVE` | SHARE UPDATE EXCLUSIVE, SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE, ACCESS EXCLUSIVE |
+| `SHARE` | ROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE, SHARE ROW EXCLUSIVE, EXCLUSIVE, ACCESS EXCLUSIVE |
+| `SHARE ROW EXCLUSIVE` | ROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE, SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE, ACCESS EXCLUSIVE |
+| `EXCLUSIVE` | ROW SHARE, ROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE, SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE, ACCESS EXCLUSIVE |
+| `ACCESS EXCLUSIVE` | All modes |
+
+## COMMENT
+
+COMMENT sets or removes a comment on a database object.
+
+### Comment on Table
+
+```php
+is('User accounts table');
+
+echo $query->toSQL();
+// COMMENT ON TABLE users IS 'User accounts table'
+```
+
+### Comment on Column
+
+```php
+is('User email address');
+
+echo $query->toSQL();
+// COMMENT ON COLUMN users.email IS 'User email address'
+```
+
+### Comment on Index
+
+```php
+is('Email lookup index');
+
+echo $query->toSQL();
+// COMMENT ON INDEX idx_users_email IS 'Email lookup index'
+```
+
+### Comment on Schema
+
+```php
+is('Default schema');
+
+echo $query->toSQL();
+// COMMENT ON SCHEMA public IS 'Default schema'
+```
+
+### Remove Comment
+
+```php
+isNull();
+
+echo $query->toSQL();
+// COMMENT ON TABLE users IS NULL
+```
+
+### Comment Targets
+
+The `CommentTarget` enum supports:
+
+| Target | Description |
+|--------|-------------|
+| `CommentTarget::TABLE` | Table |
+| `CommentTarget::COLUMN` | Table column (use dot notation: `table.column`) |
+| `CommentTarget::INDEX` | Index |
+| `CommentTarget::SCHEMA` | Schema |
+| `CommentTarget::SEQUENCE` | Sequence |
+| `CommentTarget::VIEW` | View |
+| `CommentTarget::MATVIEW` | Materialized view |
+| `CommentTarget::FUNCTION` | Function |
+| `CommentTarget::PROCEDURE` | Procedure |
+| `CommentTarget::TRIGGER` | Trigger |
+| `CommentTarget::TYPE` | Type |
+| `CommentTarget::EXTENSION` | Extension |
+| `CommentTarget::ROLE` | Role |
+| `CommentTarget::DATABASE` | Database |
+
+## CLUSTER
+
+CLUSTER physically reorders a table based on an index.
+
+### CLUSTER All Tables
+
+```php
+toSQL();
+// CLUSTER
+```
+
+### CLUSTER Single Table
+
+```php
+table('users');
+
+echo $query->toSQL();
+// CLUSTER users
+```
+
+### CLUSTER with Index
+
+```php
+table('users')
+ ->using('idx_users_pkey');
+
+echo $query->toSQL();
+// CLUSTER users USING idx_users_pkey
+```
+
+### CLUSTER with Schema
+
+```php
+table('public.users');
+
+echo $query->toSQL();
+// CLUSTER public.users
+```
+
+### CLUSTER with Verbose
+
+```php
+verbose()
+ ->table('users');
+
+echo $query->toSQL();
+// CLUSTER (VERBOSE) users
+```
+
+## DISCARD
+
+DISCARD releases session resources.
+
+### DISCARD ALL
+
+```php
+toSQL();
+// DISCARD ALL
+```
+
+### DISCARD PLANS
+
+```php
+toSQL();
+// DISCARD PLANS
+```
+
+### DISCARD SEQUENCES
+
+```php
+toSQL();
+// DISCARD SEQUENCES
+```
+
+### DISCARD TEMP
+
+```php
+toSQL();
+// DISCARD TEMP
+```
+
+## Discard Types
+
+| Type | Description |
+|------|-------------|
+| `DiscardType::ALL` | Release all temporary resources |
+| `DiscardType::PLANS` | Release all cached query plans |
+| `DiscardType::SEQUENCES` | Reset all sequence-related state |
+| `DiscardType::TEMP` | Drop all temporary tables |
+
+## DSL Functions Reference
+
+For a complete list of DSL functions, see the [DSL reference](/documentation/api/lib/postgresql/namespaces/flow-postgresql-dsl.html).
diff --git a/documentation/components/libs/postgresql/view-query-builder.md b/documentation/components/libs/postgresql/view-query-builder.md
new file mode 100644
index 000000000..91b96d062
--- /dev/null
+++ b/documentation/components/libs/postgresql/view-query-builder.md
@@ -0,0 +1,615 @@
+# View Query Builder
+
+- [Back](/documentation/components/libs/postgresql.md)
+
+[TOC]
+
+The View Query Builder provides a fluent, type-safe interface for constructing PostgreSQL view management statements:
+CREATE VIEW, CREATE MATERIALIZED VIEW, ALTER VIEW, ALTER MATERIALIZED VIEW, DROP VIEW, DROP MATERIALIZED VIEW, and REFRESH MATERIALIZED VIEW.
+
+## CREATE VIEW
+
+### Basic View Creation
+
+```php
+view('active_users')
+ ->as(select()->from('users'));
+
+echo $query->toSQL();
+// CREATE VIEW active_users AS SELECT * FROM users
+```
+
+### With Schema
+
+Schema can be specified as a separate parameter or as part of the name:
+
+```php
+view('public.active_users')
+ ->as(select()->from('users'));
+
+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();
+// CREATE VIEW public.active_users AS SELECT * FROM users
+```
+
+### OR REPLACE
+
+Create or replace an existing view:
+
+```php
+view('active_users')
+ ->orReplace()
+ ->as(select()->from('users'));
+
+echo $query->toSQL();
+// CREATE OR REPLACE VIEW active_users AS SELECT * FROM users
+```
+
+### TEMPORARY
+
+Create a temporary view that is automatically dropped at the end of the session:
+
+```php
+view('temp_users')
+ ->temporary()
+ ->as(select()->from('users'));
+
+echo $query->toSQL();
+// CREATE TEMPORARY VIEW temp_users AS SELECT * FROM users
+```
+
+### RECURSIVE
+
+Create a recursive view (typically used with CTEs):
+
+```php
+view('subordinates')
+ ->recursive()
+ ->columns('id', 'name', 'manager_id')
+ ->as(select('id', 'name', 'manager_id')->from('employees'));
+
+echo $query->toSQL();
+// CREATE RECURSIVE VIEW subordinates (id, name, manager_id) AS SELECT id, name, manager_id FROM employees
+```
+
+### Column Aliases
+
+Define column aliases for the view:
+
+```php
+view('user_info')
+ ->columns('user_id', 'user_name', 'email_address')
+ ->as(select('id', 'name', 'email')->from('users'));
+
+echo $query->toSQL();
+// CREATE VIEW user_info (user_id, user_name, email_address) AS SELECT id, name, email FROM users
+```
+
+### WITH CHECK OPTION
+
+Add check options for updatable views:
+
+```php
+view('active_users')
+ ->as(select()->from('users')->where(eq(col('active'), literal(true))))
+ ->withCheckOption();
+
+echo $query->toSQL();
+// CREATE VIEW active_users AS SELECT * FROM users WHERE active = true WITH CHECK OPTION
+
+// WITH CASCADED CHECK OPTION
+$query = create()->view('active_users')
+ ->as(select()->from('users'))
+ ->withCascadedCheckOption();
+
+echo $query->toSQL();
+// CREATE VIEW active_users AS SELECT * FROM users WITH CASCADED CHECK OPTION
+
+// WITH LOCAL CHECK OPTION
+$query = create()->view('active_users')
+ ->as(select()->from('users'))
+ ->withLocalCheckOption();
+
+echo $query->toSQL();
+// CREATE VIEW active_users AS SELECT * FROM users WITH LOCAL CHECK OPTION
+```
+
+## CREATE MATERIALIZED VIEW
+
+### Basic Materialized View Creation
+
+```php
+materializedView('user_stats')
+ ->as(select()->from('users'));
+
+echo $query->toSQL();
+// CREATE MATERIALIZED VIEW user_stats AS SELECT * FROM users
+```
+
+### IF NOT EXISTS
+
+```php
+materializedView('user_stats')
+ ->ifNotExists()
+ ->as(select()->from('users'));
+
+echo $query->toSQL();
+// CREATE MATERIALIZED VIEW IF NOT EXISTS user_stats AS SELECT * FROM users
+```
+
+### Column Aliases
+
+```php
+materializedView('user_stats')
+ ->columns('user_id', 'order_count')
+ ->as(select('id', 'count(*)')->from('users'));
+
+echo $query->toSQL();
+// CREATE MATERIALIZED VIEW user_stats (user_id, order_count) AS SELECT id, count(*) FROM users
+```
+
+### USING (Access Method)
+
+Specify a storage access method:
+
+```php
+materializedView('user_stats')
+ ->using('heap')
+ ->as(select()->from('users'));
+
+echo $query->toSQL();
+// CREATE MATERIALIZED VIEW user_stats USING heap AS SELECT * FROM users
+```
+
+### TABLESPACE
+
+Specify the tablespace for the materialized view:
+
+```php
+materializedView('user_stats')
+ ->as(select()->from('users'))
+ ->tablespace('fast_storage');
+
+echo $query->toSQL();
+// CREATE MATERIALIZED VIEW user_stats TABLESPACE fast_storage AS SELECT * FROM users
+```
+
+### WITH DATA / WITH NO DATA
+
+Control whether to populate the materialized view immediately:
+
+```php
+materializedView('user_stats')
+ ->as(select()->from('users'))
+ ->withData();
+
+echo $query->toSQL();
+// CREATE MATERIALIZED VIEW user_stats AS SELECT * FROM users WITH DATA
+
+// Create empty, populate later with REFRESH
+$query = create()->materializedView('user_stats')
+ ->as(select()->from('users'))
+ ->withNoData();
+
+echo $query->toSQL();
+// CREATE MATERIALIZED VIEW user_stats AS SELECT * FROM users WITH NO DATA
+```
+
+### Complete Example
+
+```php
+materializedView('analytics.user_stats')
+ ->ifNotExists()
+ ->columns('user_id', 'order_count', 'total_spent')
+ ->using('heap')
+ ->as(select('id', 'count(*)', 'sum(total)')->from('users'))
+ ->tablespace('analytics_ts')
+ ->withNoData();
+
+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
+```
+
+## ALTER VIEW
+
+### RENAME TO
+
+Rename a view:
+
+```php
+view('old_view')
+ ->renameTo('new_view');
+
+echo $query->toSQL();
+// ALTER VIEW old_view RENAME TO new_view
+```
+
+### IF EXISTS
+
+Only alter the view if it exists:
+
+```php
+view('old_view')
+ ->ifExists()
+ ->renameTo('new_view');
+
+echo $query->toSQL();
+// ALTER VIEW IF EXISTS old_view RENAME TO new_view
+```
+
+### SET SCHEMA
+
+Move a view to a different schema:
+
+```php
+view('my_view')
+ ->setSchema('archive');
+
+echo $query->toSQL();
+// ALTER VIEW my_view SET SCHEMA archive
+```
+
+### OWNER TO
+
+Change the owner of a view:
+
+```php
+view('my_view')
+ ->ownerTo('new_owner');
+
+echo $query->toSQL();
+// ALTER VIEW my_view OWNER TO new_owner
+```
+
+## ALTER MATERIALIZED VIEW
+
+### RENAME TO
+
+```php
+materializedView('old_matview')
+ ->renameTo('new_matview');
+
+echo $query->toSQL();
+// ALTER MATERIALIZED VIEW old_matview RENAME TO new_matview
+```
+
+### IF EXISTS
+
+```php
+materializedView('old_matview')
+ ->ifExists()
+ ->renameTo('new_matview');
+
+echo $query->toSQL();
+// ALTER MATERIALIZED VIEW IF EXISTS old_matview RENAME TO new_matview
+```
+
+### SET SCHEMA
+
+```php
+materializedView('my_matview')
+ ->setSchema('archive');
+
+echo $query->toSQL();
+// ALTER MATERIALIZED VIEW my_matview SET SCHEMA archive
+```
+
+### OWNER TO
+
+```php
+materializedView('my_matview')
+ ->ownerTo('new_owner');
+
+echo $query->toSQL();
+// ALTER MATERIALIZED VIEW my_matview OWNER TO new_owner
+```
+
+### SET TABLESPACE
+
+Move a materialized view to a different tablespace:
+
+```php
+materializedView('my_matview')
+ ->setTablespace('fast_storage');
+
+echo $query->toSQL();
+// ALTER MATERIALIZED VIEW my_matview SET TABLESPACE fast_storage
+
+// With IF EXISTS
+$query = alter()->materializedView('my_matview')
+ ->ifExists()
+ ->setTablespace('fast_storage');
+
+echo $query->toSQL();
+// ALTER MATERIALIZED VIEW IF EXISTS my_matview SET TABLESPACE fast_storage
+```
+
+## DROP VIEW
+
+### Simple Drop
+
+```php
+view('active_users');
+
+echo $query->toSQL();
+// DROP VIEW active_users
+```
+
+### Multiple Views
+
+```php
+view('view1', 'view2', 'view3');
+
+echo $query->toSQL();
+// DROP VIEW view1, view2, view3
+```
+
+### IF EXISTS
+
+```php
+view('active_users')
+ ->ifExists();
+
+echo $query->toSQL();
+// DROP VIEW IF EXISTS active_users
+```
+
+### CASCADE
+
+Drop objects that depend on the view:
+
+```php
+view('active_users')
+ ->cascade();
+
+echo $query->toSQL();
+// DROP VIEW active_users CASCADE
+```
+
+### Combined Options
+
+```php
+view('active_users')
+ ->ifExists()
+ ->cascade();
+
+echo $query->toSQL();
+// DROP VIEW IF EXISTS active_users CASCADE
+```
+
+## DROP MATERIALIZED VIEW
+
+### Simple Drop
+
+```php
+materializedView('user_stats');
+
+echo $query->toSQL();
+// DROP MATERIALIZED VIEW user_stats
+```
+
+### With Options
+
+```php
+materializedView('user_stats')
+ ->ifExists()
+ ->cascade();
+
+echo $query->toSQL();
+// DROP MATERIALIZED VIEW IF EXISTS user_stats CASCADE
+```
+
+## REFRESH MATERIALIZED VIEW
+
+### Simple Refresh
+
+Repopulate a materialized view with current data:
+
+```php
+toSQL();
+// REFRESH MATERIALIZED VIEW user_stats
+```
+
+### With Schema
+
+```php
+toSQL();
+// REFRESH MATERIALIZED VIEW analytics.user_stats
+```
+
+### CONCURRENTLY
+
+Refresh without locking out concurrent selects (requires a unique index on the view):
+
+```php
+concurrently();
+
+echo $query->toSQL();
+// REFRESH MATERIALIZED VIEW CONCURRENTLY user_stats
+```
+
+### WITH DATA / WITH NO DATA
+
+```php
+withData();
+
+echo $query->toSQL();
+// REFRESH MATERIALIZED VIEW user_stats WITH DATA
+
+// Empty the view
+$query = refresh_materialized_view('user_stats')
+ ->withNoData();
+
+echo $query->toSQL();
+// REFRESH MATERIALIZED VIEW user_stats WITH NO DATA
+```
+
+### Complete Example
+
+```php
+concurrently()
+ ->withData();
+
+echo $query->toSQL();
+// REFRESH MATERIALIZED VIEW CONCURRENTLY user_stats WITH DATA
+```
+
+For a complete list of DSL functions, see the [DSL reference](/documentation/api/lib/postgresql/namespaces/flow-postgresql-dsl.html).
diff --git a/documentation/components/libs/types.md b/documentation/components/libs/types.md
index e82d425b7..b6cc05841 100644
--- a/documentation/components/libs/types.md
+++ b/documentation/components/libs/types.md
@@ -1,7 +1,5 @@
# Types
-[TOC]
-
Flow Types is a small library that provides a set of type classes for PHP.
It's designed to work together with static analysis tools like PHPStan and Psalm.
@@ -10,7 +8,9 @@ The main goal of this library is to simplify common type-related tasks, such as
- [⬅️️ Back](/documentation/introduction.md)
- [📖Architecture](/documentation/components/libs/types/architecture.md)
- [📚API Reference](/documentation/api/lib/types)
- - [⚙️List of all Types](/api/lib/types/namespaces/flow-types-dsl.html)
+- [🗺DSL](/documentation/api/lib/types/namespaces/flow-types-dsl.html)
+
+[TOC]
## Installation
diff --git a/phpdoc/lib.pg-query.xml b/phpdoc/lib.postgresql.xml
similarity index 100%
rename from phpdoc/lib.pg-query.xml
rename to phpdoc/lib.postgresql.xml
diff --git a/phpstan.neon b/phpstan.neon
index b5f8b33f8..22884b348 100644
--- a/phpstan.neon
+++ b/phpstan.neon
@@ -6,7 +6,7 @@ parameters:
- tools/phpbench/vendor/autoload.php
- vendor/autoload.php
scanFiles:
- - src/lib/pg-query/src/stubs.php
+ - src/lib/postgresql/src/stubs.php
paths:
- src/core/etl/src
- src/cli/src
@@ -37,7 +37,7 @@ parameters:
- src/lib/parquet-viewer/src
- src/lib/snappy/src
- src/lib/types/src
- - src/lib/pg-query/src
+ - src/lib/postgresql/src
- src/tools/documentation/src
- src/core/etl/tests
- src/cli/tests
@@ -73,7 +73,7 @@ parameters:
- src/lib/parquet/src/Flow/Parquet/ThriftModel/*
- src/lib/parquet/src/Flow/Parquet/BinaryReader/*
- src/lib/parquet/src/Flow/Parquet/Dremel/ColumnData/DefinitionConverter.php
- - src/lib/pg-query/src/Flow/PgQuery/Protobuf/*
+ - src/lib/postgresql/src/Flow/PostgreSql/Protobuf/*
tmpDir: var/phpstan/cache
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index cd1f266bc..dd3a77be0 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -80,6 +80,12 @@
src/lib/types/tests/Flow/Types/Tests/Unit
+
+ src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit
+
+
+ src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration
+
src/bridge/filesystem/azure/tests/Flow/Filesystem/Bridge/Azure/Tests/Unit
@@ -187,7 +193,7 @@
src/lib/parquet/src/Flow/Parquet/Thrift
- src/lib/pg-query/src/Flow/PgQuery/Protobuf
+ src/lib/postgresql/src/Flow/PostgreSql/Protobuf
src/core/etl/src/Flow/ETL/DSL/functions.php
diff --git a/src/cli/composer.json b/src/cli/composer.json
index a50cbecd4..c80d394bf 100644
--- a/src/cli/composer.json
+++ b/src/cli/composer.json
@@ -22,7 +22,7 @@
"flow-php/etl-adapter-chartjs": "self.version",
"flow-php/openapi-specification-bridge": "self.version",
"flow-php/parquet-viewer": "self.version",
- "flow-php/pg-query": "self.version"
+ "flow-php/postgresql": "self.version"
},
"config": {
"optimize-autoloader": true,
diff --git a/src/core/etl/composer.json b/src/core/etl/composer.json
index 602eb8478..a750b49c3 100644
--- a/src/core/etl/composer.json
+++ b/src/core/etl/composer.json
@@ -17,7 +17,6 @@
"flow-php/types": "self.version",
"flow-php/array-dot": "self.version",
"flow-php/filesystem": "self.version",
- "flow-php/pg-query": "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"
diff --git a/src/lib/pg-query/README.md b/src/lib/pg-query/README.md
deleted file mode 100644
index 9559316f0..000000000
--- a/src/lib/pg-query/README.md
+++ /dev/null
@@ -1,59 +0,0 @@
-# PostgreSQL Query Parser
-
-Flow PHP's PostgreSQL Query Parser library provides strongly-typed AST (Abstract Syntax Tree) parsing
-for PostgreSQL SQL queries using the [libpg_query](https://github.com/pganalyze/libpg_query) library
-through a PHP extension.
-
-## Installation
-
-This library requires the `pg_query` PHP extension. Install it via PIE:
-
-```bash
-pie install flow-php/pg-query-ext
-```
-
-Then install the library via Composer:
-
-```bash
-composer require flow-php/pg-query
-```
-
-## Usage
-
-```php
-parse('SELECT id, name FROM users WHERE active = true');
-
-// Access the AST
-foreach ($result->getStmts() as $stmt) {
- $node = $stmt->getStmt();
- // Work with the parsed statement...
-}
-
-// Or use DSL functions for convenience
-$result = pg_parse('SELECT 1');
-
-// Other utilities
-$fingerprint = $parser->fingerprint('SELECT id FROM users WHERE id = 1');
-$normalized = $parser->normalize('SELECT * FROM users WHERE id = 1'); // Returns: SELECT * FROM users WHERE id = $1
-$statements = $parser->split('SELECT 1; SELECT 2;'); // Returns: ['SELECT 1', 'SELECT 2']
-```
-
-## Features
-
-- **Full PostgreSQL SQL parsing** - Uses the actual PostgreSQL parser
-- **Strongly-typed AST nodes** - Generated from protobuf definitions
-- **Query fingerprinting** - Generate unique fingerprints for queries
-- **Query normalization** - Replace literals with parameter placeholders
-- **Statement splitting** - Split multiple SQL statements
-
-## Documentation
-
-- [Official Documentation](https://flow-php.com)
-- [GitHub Repository](https://github.com/flow-php/flow)
diff --git a/src/lib/pg-query/src/Flow/PgQuery/DSL/functions.php b/src/lib/pg-query/src/Flow/PgQuery/DSL/functions.php
deleted file mode 100644
index 894cd2dcf..000000000
--- a/src/lib/pg-query/src/Flow/PgQuery/DSL/functions.php
+++ /dev/null
@@ -1,277 +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 pg_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 pg_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 pg_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 pg_split(string $sql) : array
-{
- return (new Parser())->split($sql);
-}
-
-/**
- * Create DeparseOptions for configuring SQL formatting.
- */
-#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)]
-function pg_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 pg_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 pg_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 pg_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 pg_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 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 pg_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.
- *
- * @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 pg_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 PaginationConfig for offset-based pagination.
- *
- * @param int $limit Maximum number of rows to return
- * @param int $offset Number of rows to skip (requires ORDER BY in query)
- */
-#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)]
-function pg_pagination_config(int $limit, int $offset = 0) : PaginationConfig
-{
- return new PaginationConfig($limit, $offset);
-}
-
-/**
- * Create a PaginationModifier for offset-based pagination.
- *
- * Applies LIMIT and OFFSET to the query. OFFSET without ORDER BY will throw an exception.
- *
- * @param int $limit Maximum number of rows to return
- * @param int $offset Number of rows to skip (requires ORDER BY in query)
- */
-#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)]
-function pg_pagination(int $limit, int $offset = 0) : PaginationModifier
-{
- return new PaginationModifier(new PaginationConfig($limit, $offset));
-}
-
-/**
- * Create a CountModifier that transforms a SELECT query into a COUNT query.
- *
- * The original query is wrapped in: SELECT COUNT(*) FROM (...) AS _count_subq
- * ORDER BY and LIMIT/OFFSET are removed from the inner query.
- */
-#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)]
-function pg_count_modifier() : CountModifier
-{
- return new CountModifier();
-}
-
-/**
- * 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 pg_keyset_column(string $column, SortOrder $order = SortOrder::ASC) : KeysetColumn
-{
- return new KeysetColumn($column, $order);
-}
-
-/**
- * Create a KeysetPaginationConfig for cursor-based pagination.
- *
- * @param int $limit Maximum number of rows to return
- * @param list $columns Columns to use for keyset pagination (must match ORDER BY)
- * @param null|list $cursor Cursor values from the last row of previous page (null for first page)
- */
-#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)]
-function pg_keyset_pagination_config(int $limit, array $columns, ?array $cursor = null) : KeysetPaginationConfig
-{
- return new KeysetPaginationConfig($limit, $columns, $cursor);
-}
-
-/**
- * Create a KeysetPaginationModifier for cursor-based pagination.
- *
- * Keyset pagination is more efficient than OFFSET for large datasets because it uses
- * indexed WHERE conditions instead of scanning and skipping rows.
- *
- * @param int $limit Maximum number of rows to return
- * @param list $columns Columns to use for keyset pagination (must match ORDER BY)
- * @param null|list $cursor Cursor values from the last row of previous page (null for first page)
- */
-#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)]
-function pg_keyset_pagination(int $limit, array $columns, ?array $cursor = null) : KeysetPaginationModifier
-{
- return new KeysetPaginationModifier(new KeysetPaginationConfig($limit, $columns, $cursor));
-}
-
-/**
- * Extract columns from a parsed SQL query.
- */
-#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)]
-function pg_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 pg_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 pg_query_functions(ParsedQuery $query) : Functions
-{
- return new Functions($query);
-}
diff --git a/src/lib/pg-query/src/Flow/PgQuery/ParsedQuery.php b/src/lib/pg-query/src/Flow/PgQuery/ParsedQuery.php
deleted file mode 100644
index 2b49cc7e0..000000000
--- a/src/lib/pg-query/src/Flow/PgQuery/ParsedQuery.php
+++ /dev/null
@@ -1,59 +0,0 @@
-parseResult->serializeToString());
- }
-
- return \pg_query_deparse_opts(
- $this->parseResult->serializeToString(),
- $options->hasPrettyPrint(),
- $options->getIndentSize(),
- $options->getMaxLineLength(),
- $options->hasTrailingNewline(),
- $options->commasAtStartOfLine()
- );
- }
-
- public function raw() : ParseResult
- {
- return $this->parseResult;
- }
-
- /**
- * Traverse the AST with visitors and/or modifiers.
- *
- * Visitors collect information (read-only), modifiers mutate nodes.
- * Returns $this to allow method chaining.
- */
- public function traverse(NodeVisitor|NodeModifier ...$handlers) : self
- {
- $traverser = new Traverser(...$handlers);
- $traverser->traverse($this->parseResult);
-
- return $this;
- }
-}
diff --git a/src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/ParsedQueryTest.php b/src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/ParsedQueryTest.php
deleted file mode 100644
index 4cd748fab..000000000
--- a/src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/ParsedQueryTest.php
+++ /dev/null
@@ -1,267 +0,0 @@
-forTable('u');
- $orderColumns = pg_query_columns($result)->forTable('o');
-
- self::assertCount(2, $userColumns);
- $userColumnNames = \array_map(fn (Column $c) => $c->name(), $userColumns);
- self::assertContains('id', $userColumnNames);
-
- self::assertCount(2, $orderColumns);
- $orderColumnNames = \array_map(fn (Column $c) => $c->name(), $orderColumns);
- self::assertContains('order_date', $orderColumnNames);
- self::assertContains('user_id', $orderColumnNames);
- }
-
- public function test_columns_from_select() : void
- {
- $result = pg_parse('SELECT id, name FROM users');
-
- $columns = pg_query_columns($result)->all();
-
- self::assertCount(2, $columns);
-
- $columnNames = \array_map(fn (Column $c) => $c->name(), $columns);
- self::assertContains('id', $columnNames);
- self::assertContains('name', $columnNames);
- }
-
- public function test_columns_from_where_clause() : void
- {
- $result = pg_parse('SELECT 1 FROM users WHERE active = true AND name LIKE \'%john%\'');
-
- $columns = pg_query_columns($result)->all();
-
- $columnNames = \array_map(fn (Column $c) => $c->name(), $columns);
- self::assertContains('active', $columnNames);
- self::assertContains('name', $columnNames);
- }
-
- public function test_columns_with_star() : void
- {
- $result = pg_parse('SELECT * FROM users');
-
- $columns = pg_query_columns($result)->all();
-
- self::assertCount(1, $columns);
- self::assertSame('*', $columns[0]->name());
- self::assertNull($columns[0]->table());
- }
-
- public function test_columns_with_table_qualified_star() : void
- {
- $result = pg_parse('SELECT u.* FROM users u');
-
- $columns = pg_query_columns($result)->all();
-
- self::assertCount(1, $columns);
- self::assertSame('*', $columns[0]->name());
- self::assertSame('u', $columns[0]->table());
- }
-
- public function test_columns_with_table_qualifier() : void
- {
- $result = pg_parse('SELECT u.id, u.name FROM users u');
-
- $columns = pg_query_columns($result)->all();
-
- self::assertCount(2, $columns);
-
- foreach ($columns as $column) {
- self::assertSame('u', $column->table());
- }
- }
-
- public function test_functions_from_select() : void
- {
- $result = pg_parse('SELECT COUNT(*), SUM(amount) FROM orders');
-
- $functions = pg_query_functions($result)->all();
-
- self::assertCount(2, $functions);
-
- $functionNames = \array_map(fn (FunctionCall $f) => $f->name(), $functions);
- self::assertContains('count', $functionNames);
- self::assertContains('sum', $functionNames);
- }
-
- public function test_functions_nested() : void
- {
- $result = pg_parse('SELECT UPPER(CONCAT(first_name, last_name)) FROM users');
-
- $functions = pg_query_functions($result)->all();
-
- self::assertCount(2, $functions);
-
- $functionNames = \array_map(fn (FunctionCall $f) => $f->name(), $functions);
- self::assertContains('upper', $functionNames);
- self::assertContains('concat', $functionNames);
- }
-
- public function test_functions_with_schema() : void
- {
- $result = pg_parse('SELECT pg_catalog.now()');
-
- $functions = pg_query_functions($result)->all();
-
- self::assertCount(1, $functions);
- self::assertSame('now', $functions[0]->name());
- self::assertSame('pg_catalog', $functions[0]->schema());
- }
-
- public function test_raw_returns_parse_result() : void
- {
- $result = pg_parse('SELECT 1');
-
- self::assertInstanceOf(ParseResult::class, $result->raw());
- }
-
- public function test_tables_from_cte() : void
- {
- $result = pg_parse('WITH active_users AS (SELECT * FROM users WHERE active = true) SELECT * FROM active_users');
-
- $tables = pg_query_tables($result)->all();
-
- self::assertCount(2, $tables);
-
- $tableNames = \array_map(fn (Table $t) => $t->name(), $tables);
- self::assertContains('users', $tableNames);
- self::assertContains('active_users', $tableNames);
- }
-
- public function test_tables_from_delete() : void
- {
- $result = pg_parse('DELETE FROM users WHERE id = 1');
-
- $tables = pg_query_tables($result)->all();
-
- self::assertCount(1, $tables);
- self::assertSame('users', $tables[0]->name());
- }
-
- public function test_tables_from_insert() : void
- {
- $result = pg_parse('INSERT INTO users (name) VALUES (\'john\')');
-
- $tables = pg_query_tables($result)->all();
-
- self::assertCount(1, $tables);
- self::assertSame('users', $tables[0]->name());
- }
-
- public function test_tables_from_join() : void
- {
- $result = pg_parse('SELECT * FROM users u JOIN orders o ON u.id = o.user_id');
-
- $tables = pg_query_tables($result)->all();
-
- self::assertCount(2, $tables);
-
- $tableNames = \array_map(fn (Table $t) => $t->name(), $tables);
- self::assertContains('users', $tableNames);
- self::assertContains('orders', $tableNames);
- }
-
- public function test_tables_from_simple_select() : void
- {
- $result = pg_parse('SELECT * FROM users');
-
- $tables = pg_query_tables($result)->all();
-
- self::assertCount(1, $tables);
- self::assertInstanceOf(Table::class, $tables[0]);
- self::assertSame('users', $tables[0]->name());
- self::assertNull($tables[0]->schema());
- self::assertNull($tables[0]->alias());
- }
-
- public function test_tables_from_subquery() : void
- {
- $result = pg_parse('SELECT * FROM (SELECT * FROM orders) AS sub');
-
- $tables = pg_query_tables($result)->all();
-
- self::assertCount(1, $tables);
- self::assertSame('orders', $tables[0]->name());
- }
-
- public function test_tables_from_update() : void
- {
- $result = pg_parse('UPDATE users SET name = \'john\' WHERE id = 1');
-
- $tables = pg_query_tables($result)->all();
-
- self::assertCount(1, $tables);
- self::assertSame('users', $tables[0]->name());
- }
-
- public function test_tables_with_alias() : void
- {
- $result = pg_parse('SELECT * FROM users AS u');
-
- $tables = pg_query_tables($result)->all();
-
- self::assertCount(1, $tables);
- self::assertSame('users', $tables[0]->name());
- self::assertSame('u', $tables[0]->alias());
- }
-
- public function test_tables_with_schema() : void
- {
- $result = pg_parse('SELECT * FROM public.users');
-
- $tables = pg_query_tables($result)->all();
-
- self::assertCount(1, $tables);
- self::assertSame('users', $tables[0]->name());
- self::assertSame('public', $tables[0]->schema());
- }
-
- public function test_traverse_with_multiple_visitors() : void
- {
- $result = pg_parse('SELECT COUNT(id), name FROM users WHERE active = true');
-
- $columnCollector = new ColumnRefCollector();
- $funcCollector = new FuncCallCollector();
- $rangeVarCollector = new RangeVarCollector();
-
- $result->traverse($columnCollector, $funcCollector, $rangeVarCollector);
-
- self::assertCount(3, $columnCollector->getColumnRefs());
- self::assertCount(1, $funcCollector->getFuncCalls());
- self::assertCount(1, $rangeVarCollector->getRangeVars());
- }
-
- public function test_traverse_with_single_visitor() : void
- {
- $result = pg_parse('SELECT id, name FROM users');
-
- $collector = new ColumnRefCollector();
- $result->traverse($collector);
-
- self::assertCount(2, $collector->getColumnRefs());
- }
-}
diff --git a/src/lib/pg-query/.gitattributes b/src/lib/postgresql/.gitattributes
similarity index 100%
rename from src/lib/pg-query/.gitattributes
rename to src/lib/postgresql/.gitattributes
diff --git a/src/lib/pg-query/.github/workflows/readonly.yaml b/src/lib/postgresql/.github/workflows/readonly.yaml
similarity index 100%
rename from src/lib/pg-query/.github/workflows/readonly.yaml
rename to src/lib/postgresql/.github/workflows/readonly.yaml
diff --git a/src/lib/pg-query/CONTRIBUTING.md b/src/lib/postgresql/CONTRIBUTING.md
similarity index 100%
rename from src/lib/pg-query/CONTRIBUTING.md
rename to src/lib/postgresql/CONTRIBUTING.md
diff --git a/src/lib/pg-query/LICENSE b/src/lib/postgresql/LICENSE
similarity index 100%
rename from src/lib/pg-query/LICENSE
rename to src/lib/postgresql/LICENSE
diff --git a/src/lib/postgresql/README.md b/src/lib/postgresql/README.md
new file mode 100644
index 000000000..433f9cb30
--- /dev/null
+++ b/src/lib/postgresql/README.md
@@ -0,0 +1,11 @@
+# Parquet Viewer
+
+This package provides PHP Client for PostgreSQL that includes powerful parser and query builder.
+
+> [!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/libs/postgresql/)
+- ➡️ [Installation](https://flow-php.com/documentation/installation)
+- 🛠️ [Contributing](https://flow-php.com/documentation/contributing/)
+- 🚧 [Upgrading](https://flow-php.com/documentation/upgrading/)
\ No newline at end of file
diff --git a/src/lib/pg-query/composer.json b/src/lib/postgresql/composer.json
similarity index 74%
rename from src/lib/pg-query/composer.json
rename to src/lib/postgresql/composer.json
index 113a0c778..705cd502b 100644
--- a/src/lib/pg-query/composer.json
+++ b/src/lib/postgresql/composer.json
@@ -1,7 +1,7 @@
{
- "name": "flow-php/pg-query",
+ "name": "flow-php/postgresql",
"type": "library",
- "description": "PHP ETL - PostgreSQL Query Parser Library",
+ "description": "Flow PHP - PostgreSQL Client Library",
"keywords": [
"php",
"postgresql",
@@ -12,11 +12,15 @@
],
"require": {
"php": "~8.2.0 || ~8.3.0 || ~8.4.0",
- "ext-pg_query": "*",
"google/protobuf": "^4.0"
},
+ "require-dev": {
+ "ext-pg_query": "*",
+ "ext-pgsql": "*"
+ },
"suggest": {
- "ext-protobuf": "For faster protobuf parsing performance"
+ "ext-protobuf": "For faster protobuf parsing performance",
+ "ext-pg_query": "Mandatory for PostgreSQL query parsing functionality"
},
"config": {
"optimize-autoloader": true,
@@ -30,7 +34,7 @@
]
},
"files": [
- "src/Flow/PgQuery/DSL/functions.php",
+ "src/Flow/PostgreSql/DSL/functions.php",
"src/stubs.php"
]
},
diff --git a/src/lib/pg-query/resources/proto/pg_query.proto b/src/lib/postgresql/resources/proto/pg_query.proto
similarity index 99%
rename from src/lib/pg-query/resources/proto/pg_query.proto
rename to src/lib/postgresql/resources/proto/pg_query.proto
index 77abb7c96..95cb5f486 100644
--- a/src/lib/pg-query/resources/proto/pg_query.proto
+++ b/src/lib/postgresql/resources/proto/pg_query.proto
@@ -5,8 +5,8 @@ syntax = "proto3";
package pg_query;
-option php_namespace = "Flow\\PgQuery\\Protobuf\\AST";
-option php_metadata_namespace = "Flow\\PgQuery\\Protobuf\\Metadata";
+option php_namespace = "Flow\\PostgreSql\\Protobuf\\AST";
+option php_metadata_namespace = "Flow\\PostgreSql\\Protobuf\\Metadata";
message ParseResult {
int32 version = 1;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/AST/ModificationContext.php b/src/lib/postgresql/src/Flow/PostgreSql/AST/ModificationContext.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/AST/ModificationContext.php
rename to src/lib/postgresql/src/Flow/PostgreSql/AST/ModificationContext.php
index 2d3ec3add..9e3cb18fe 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/AST/ModificationContext.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/AST/ModificationContext.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace Flow\PgQuery\AST;
+namespace Flow\PostgreSql\AST;
/**
* Provides context information during AST modification.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/AST/NodeModifier.php b/src/lib/postgresql/src/Flow/PostgreSql/AST/NodeModifier.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/AST/NodeModifier.php
rename to src/lib/postgresql/src/Flow/PostgreSql/AST/NodeModifier.php
index f6e621868..19ea13043 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/AST/NodeModifier.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/AST/NodeModifier.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace Flow\PgQuery\AST;
+namespace Flow\PostgreSql\AST;
/**
* Interface for AST node modifiers.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/AST/NodeVisitor.php b/src/lib/postgresql/src/Flow/PostgreSql/AST/NodeVisitor.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/AST/NodeVisitor.php
rename to src/lib/postgresql/src/Flow/PostgreSql/AST/NodeVisitor.php
index 6ffb3b038..a7bb03e9c 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/AST/NodeVisitor.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/AST/NodeVisitor.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace Flow\PgQuery\AST;
+namespace Flow\PostgreSql\AST;
/**
* Interface for AST node visitors.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/AST/Nodes/Column.php b/src/lib/postgresql/src/Flow/PostgreSql/AST/Nodes/Column.php
similarity index 93%
rename from src/lib/pg-query/src/Flow/PgQuery/AST/Nodes/Column.php
rename to src/lib/postgresql/src/Flow/PostgreSql/AST/Nodes/Column.php
index 4702008c8..a4a0b7d13 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/AST/Nodes/Column.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/AST/Nodes/Column.php
@@ -2,9 +2,9 @@
declare(strict_types=1);
-namespace Flow\PgQuery\AST\Nodes;
+namespace Flow\PostgreSql\AST\Nodes;
-use Flow\PgQuery\Protobuf\AST\ColumnRef;
+use Flow\PostgreSql\Protobuf\AST\ColumnRef;
final readonly class Column
{
diff --git a/src/lib/pg-query/src/Flow/PgQuery/AST/Nodes/FunctionCall.php b/src/lib/postgresql/src/Flow/PostgreSql/AST/Nodes/FunctionCall.php
similarity index 93%
rename from src/lib/pg-query/src/Flow/PgQuery/AST/Nodes/FunctionCall.php
rename to src/lib/postgresql/src/Flow/PostgreSql/AST/Nodes/FunctionCall.php
index 064934d95..b765f7f22 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/AST/Nodes/FunctionCall.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/AST/Nodes/FunctionCall.php
@@ -2,9 +2,9 @@
declare(strict_types=1);
-namespace Flow\PgQuery\AST\Nodes;
+namespace Flow\PostgreSql\AST\Nodes;
-use Flow\PgQuery\Protobuf\AST\FuncCall;
+use Flow\PostgreSql\Protobuf\AST\FuncCall;
final readonly class FunctionCall
{
diff --git a/src/lib/pg-query/src/Flow/PgQuery/AST/Nodes/Table.php b/src/lib/postgresql/src/Flow/PostgreSql/AST/Nodes/Table.php
similarity index 90%
rename from src/lib/pg-query/src/Flow/PgQuery/AST/Nodes/Table.php
rename to src/lib/postgresql/src/Flow/PostgreSql/AST/Nodes/Table.php
index 5711c7252..ac8ddcaf4 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/AST/Nodes/Table.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/AST/Nodes/Table.php
@@ -2,9 +2,9 @@
declare(strict_types=1);
-namespace Flow\PgQuery\AST\Nodes;
+namespace Flow\PostgreSql\AST\Nodes;
-use Flow\PgQuery\Protobuf\AST\RangeVar;
+use Flow\PostgreSql\Protobuf\AST\RangeVar;
final readonly class Table
{
diff --git a/src/lib/pg-query/src/Flow/PgQuery/AST/Transformers/CountModifier.php b/src/lib/postgresql/src/Flow/PostgreSql/AST/Transformers/CountModifier.php
similarity index 94%
rename from src/lib/pg-query/src/Flow/PgQuery/AST/Transformers/CountModifier.php
rename to src/lib/postgresql/src/Flow/PostgreSql/AST/Transformers/CountModifier.php
index 41f8c98c5..c70e596be 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/AST/Transformers/CountModifier.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/AST/Transformers/CountModifier.php
@@ -2,10 +2,10 @@
declare(strict_types=1);
-namespace Flow\PgQuery\AST\Transformers;
+namespace Flow\PostgreSql\AST\Transformers;
-use Flow\PgQuery\AST\{ModificationContext, NodeModifier};
-use Flow\PgQuery\Protobuf\AST\{
+use Flow\PostgreSql\AST\{ModificationContext, NodeModifier};
+use Flow\PostgreSql\Protobuf\AST\{
Alias,
ColumnRef,
FuncCall,
@@ -15,7 +15,7 @@
ResTarget,
SelectStmt
};
-use Flow\PgQuery\Protobuf\AST\A_Star;
+use Flow\PostgreSql\Protobuf\AST\A_Star;
/**
* Transforms SELECT queries into COUNT queries for pagination.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/AST/Transformers/KeysetColumn.php b/src/lib/postgresql/src/Flow/PostgreSql/AST/Transformers/KeysetColumn.php
similarity index 85%
rename from src/lib/pg-query/src/Flow/PgQuery/AST/Transformers/KeysetColumn.php
rename to src/lib/postgresql/src/Flow/PostgreSql/AST/Transformers/KeysetColumn.php
index 5126d984e..29d341bde 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/AST/Transformers/KeysetColumn.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/AST/Transformers/KeysetColumn.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace Flow\PgQuery\AST\Transformers;
+namespace Flow\PostgreSql\AST\Transformers;
/**
* Defines a column for keyset pagination.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/AST/Transformers/KeysetPaginationConfig.php b/src/lib/postgresql/src/Flow/PostgreSql/AST/Transformers/KeysetPaginationConfig.php
similarity index 93%
rename from src/lib/pg-query/src/Flow/PgQuery/AST/Transformers/KeysetPaginationConfig.php
rename to src/lib/postgresql/src/Flow/PostgreSql/AST/Transformers/KeysetPaginationConfig.php
index 4bf2248fe..b3fdc724d 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/AST/Transformers/KeysetPaginationConfig.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/AST/Transformers/KeysetPaginationConfig.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace Flow\PgQuery\AST\Transformers;
+namespace Flow\PostgreSql\AST\Transformers;
/**
* Configuration for keyset (cursor-based) pagination.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/AST/Transformers/KeysetPaginationModifier.php b/src/lib/postgresql/src/Flow/PostgreSql/AST/Transformers/KeysetPaginationModifier.php
similarity index 94%
rename from src/lib/pg-query/src/Flow/PgQuery/AST/Transformers/KeysetPaginationModifier.php
rename to src/lib/postgresql/src/Flow/PostgreSql/AST/Transformers/KeysetPaginationModifier.php
index 73b5e9c18..6f8d8aa87 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/AST/Transformers/KeysetPaginationModifier.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/AST/Transformers/KeysetPaginationModifier.php
@@ -2,11 +2,11 @@
declare(strict_types=1);
-namespace Flow\PgQuery\AST\Transformers;
+namespace Flow\PostgreSql\AST\Transformers;
-use Flow\PgQuery\AST\{ModificationContext, NodeModifier};
-use Flow\PgQuery\Exception\PaginationException;
-use Flow\PgQuery\Protobuf\AST\{
+use Flow\PostgreSql\AST\{ModificationContext, NodeModifier};
+use Flow\PostgreSql\Exception\PaginationException;
+use Flow\PostgreSql\Protobuf\AST\{
A_Const,
A_Expr,
A_Expr_Kind,
@@ -20,6 +20,7 @@
ParamRef,
SelectStmt
};
+use Flow\PostgreSql\QueryBuilder\QualifiedIdentifier;
/**
* Applies keyset (cursor-based) pagination to SELECT queries.
@@ -173,10 +174,9 @@ private function buildKeysetCondition() : Node
private function createColumnRef(string $columnName) : Node
{
- $parts = \explode('.', $columnName);
$fields = [];
- foreach ($parts as $part) {
+ foreach (QualifiedIdentifier::parse($columnName)->parts() as $part) {
$str = new PBString();
$str->setSval($part);
$strNode = new Node();
diff --git a/src/lib/pg-query/src/Flow/PgQuery/AST/Transformers/PaginationConfig.php b/src/lib/postgresql/src/Flow/PostgreSql/AST/Transformers/PaginationConfig.php
similarity index 85%
rename from src/lib/pg-query/src/Flow/PgQuery/AST/Transformers/PaginationConfig.php
rename to src/lib/postgresql/src/Flow/PostgreSql/AST/Transformers/PaginationConfig.php
index 23bb19450..75d14a45f 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/AST/Transformers/PaginationConfig.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/AST/Transformers/PaginationConfig.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace Flow\PgQuery\AST\Transformers;
+namespace Flow\PostgreSql\AST\Transformers;
/**
* Configuration for OFFSET-based pagination transformations.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/AST/Transformers/PaginationModifier.php b/src/lib/postgresql/src/Flow/PostgreSql/AST/Transformers/PaginationModifier.php
similarity index 95%
rename from src/lib/pg-query/src/Flow/PgQuery/AST/Transformers/PaginationModifier.php
rename to src/lib/postgresql/src/Flow/PostgreSql/AST/Transformers/PaginationModifier.php
index aa156c064..f92ac4dc7 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/AST/Transformers/PaginationModifier.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/AST/Transformers/PaginationModifier.php
@@ -2,11 +2,11 @@
declare(strict_types=1);
-namespace Flow\PgQuery\AST\Transformers;
+namespace Flow\PostgreSql\AST\Transformers;
-use Flow\PgQuery\AST\{ModificationContext, NodeModifier};
-use Flow\PgQuery\Exception\PaginationException;
-use Flow\PgQuery\Protobuf\AST\{
+use Flow\PostgreSql\AST\{ModificationContext, NodeModifier};
+use Flow\PostgreSql\Exception\PaginationException;
+use Flow\PostgreSql\Protobuf\AST\{
A_Const,
A_Star,
Alias,
diff --git a/src/lib/pg-query/src/Flow/PgQuery/AST/Transformers/SortOrder.php b/src/lib/postgresql/src/Flow/PostgreSql/AST/Transformers/SortOrder.php
similarity index 71%
rename from src/lib/pg-query/src/Flow/PgQuery/AST/Transformers/SortOrder.php
rename to src/lib/postgresql/src/Flow/PostgreSql/AST/Transformers/SortOrder.php
index e24094af6..e903eaf1f 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/AST/Transformers/SortOrder.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/AST/Transformers/SortOrder.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace Flow\PgQuery\AST\Transformers;
+namespace Flow\PostgreSql\AST\Transformers;
enum SortOrder : string
{
diff --git a/src/lib/pg-query/src/Flow/PgQuery/AST/Traverser.php b/src/lib/postgresql/src/Flow/PostgreSql/AST/Traverser.php
similarity index 99%
rename from src/lib/pg-query/src/Flow/PgQuery/AST/Traverser.php
rename to src/lib/postgresql/src/Flow/PostgreSql/AST/Traverser.php
index e6fdb7b5e..b4806942c 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/AST/Traverser.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/AST/Traverser.php
@@ -2,9 +2,9 @@
declare(strict_types=1);
-namespace Flow\PgQuery\AST;
+namespace Flow\PostgreSql\AST;
-use Flow\PgQuery\Protobuf\AST\{Node, ParseResult};
+use Flow\PostgreSql\Protobuf\AST\{Node, ParseResult};
/**
* AST Traverser for PostgreSQL parse trees.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/AST/Visitors/ColumnRefCollector.php b/src/lib/postgresql/src/Flow/PostgreSql/AST/Visitors/ColumnRefCollector.php
similarity index 86%
rename from src/lib/pg-query/src/Flow/PgQuery/AST/Visitors/ColumnRefCollector.php
rename to src/lib/postgresql/src/Flow/PostgreSql/AST/Visitors/ColumnRefCollector.php
index 78d3013e8..eb4e08854 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/AST/Visitors/ColumnRefCollector.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/AST/Visitors/ColumnRefCollector.php
@@ -2,10 +2,10 @@
declare(strict_types=1);
-namespace Flow\PgQuery\AST\Visitors;
+namespace Flow\PostgreSql\AST\Visitors;
-use Flow\PgQuery\AST\NodeVisitor;
-use Flow\PgQuery\Protobuf\AST\ColumnRef;
+use Flow\PostgreSql\AST\NodeVisitor;
+use Flow\PostgreSql\Protobuf\AST\ColumnRef;
/**
* A visitor that collects all ColumnRef (column references) nodes.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/AST/Visitors/FuncCallCollector.php b/src/lib/postgresql/src/Flow/PostgreSql/AST/Visitors/FuncCallCollector.php
similarity index 86%
rename from src/lib/pg-query/src/Flow/PgQuery/AST/Visitors/FuncCallCollector.php
rename to src/lib/postgresql/src/Flow/PostgreSql/AST/Visitors/FuncCallCollector.php
index 6c1771d15..4a02c8fc1 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/AST/Visitors/FuncCallCollector.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/AST/Visitors/FuncCallCollector.php
@@ -2,10 +2,10 @@
declare(strict_types=1);
-namespace Flow\PgQuery\AST\Visitors;
+namespace Flow\PostgreSql\AST\Visitors;
-use Flow\PgQuery\AST\NodeVisitor;
-use Flow\PgQuery\Protobuf\AST\FuncCall;
+use Flow\PostgreSql\AST\NodeVisitor;
+use Flow\PostgreSql\Protobuf\AST\FuncCall;
/**
* A visitor that collects all FuncCall (function call) nodes.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/AST/Visitors/RangeVarCollector.php b/src/lib/postgresql/src/Flow/PostgreSql/AST/Visitors/RangeVarCollector.php
similarity index 86%
rename from src/lib/pg-query/src/Flow/PgQuery/AST/Visitors/RangeVarCollector.php
rename to src/lib/postgresql/src/Flow/PostgreSql/AST/Visitors/RangeVarCollector.php
index 08546af8a..7b2ca600f 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/AST/Visitors/RangeVarCollector.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/AST/Visitors/RangeVarCollector.php
@@ -2,10 +2,10 @@
declare(strict_types=1);
-namespace Flow\PgQuery\AST\Visitors;
+namespace Flow\PostgreSql\AST\Visitors;
-use Flow\PgQuery\AST\NodeVisitor;
-use Flow\PgQuery\Protobuf\AST\RangeVar;
+use Flow\PostgreSql\AST\NodeVisitor;
+use Flow\PostgreSql\Protobuf\AST\RangeVar;
/**
* A visitor that collects all RangeVar (table references) nodes.
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/DSL/functions.php b/src/lib/postgresql/src/Flow/PostgreSql/DSL/functions.php
new file mode 100644
index 000000000..3581a671e
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/DSL/functions.php
@@ -0,0 +1,2574 @@
+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 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.
+ *
+ * @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);
+}
+
+/**
+ * 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 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();
+}
+
+/**
+ * Parse SQL and convert to a QueryBuilder for modification.
+ *
+ * Only works for single-statement queries. For multiple statements,
+ * use pg_split() to parse statements individually.
+ *
+ * @throws \InvalidArgumentException if query contains multiple statements or unsupported statement type
+ */
+#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)]
+function sql_to_query_builder(string $sql) : SelectBuilder|InsertBuilder|UpdateBuilder|DeleteBuilder
+{
+ return sql_parse($sql)->toQueryBuilder();
+}
+
+// ----------------------------------------------------------------------------
+// Expressions
+// ----------------------------------------------------------------------------
+
+/**
+ * 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 string $type Target type name (can include schema like "pg_catalog.int4")
+ */
+#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)]
+function cast(Expression $expr, string $type) : TypeCast
+{
+ return new TypeCast($expr, QualifiedIdentifier::parse($type)->parts());
+}
+
+/**
+ * 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).
+ */
+#[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_selects(Expression $left, ComparisonOperator $operator, SelectFinalStep $subquery) : All
+{
+ $node = new Node();
+ $node->setSelectStmt($subquery->toAst());
+
+ return new All($left, $operator, $node);
+}
+
+/**
+ * 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).
+ */
+#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)]
+function raw_cond(string $sql) : RawCondition
+{
+ return new RawCondition($sql);
+}
+
+/**
+ * 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);
+}
+
+// ----------------------------------------------------------------------------
+// Table References
+// ----------------------------------------------------------------------------
+
+/**
+ * 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);
+}
+
+// ----------------------------------------------------------------------------
+// Clauses
+// ----------------------------------------------------------------------------
+
+/**
+ * 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,
+) : OrderByItem {
+ return new OrderByItem($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) : OrderByItem
+{
+ return new OrderByItem($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) : OrderByItem
+{
+ return new OrderByItem($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();
+}
+
+// ----------------------------------------------------------------------------
+// Transaction Commands
+// ----------------------------------------------------------------------------
+
+/**
+ * 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);
+}
+
+// ----------------------------------------------------------------------------
+// SQL Data Types
+// ----------------------------------------------------------------------------
+
+/**
+ * Create an INTEGER data type.
+ */
+#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)]
+function sql_type_integer() : DataType
+{
+ return DataType::integer();
+}
+
+/**
+ * Create a BIGINT data type.
+ */
+#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)]
+function sql_type_bigint() : DataType
+{
+ return DataType::bigint();
+}
+
+/**
+ * Create a SMALLINT data type.
+ */
+#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)]
+function sql_type_smallint() : DataType
+{
+ return DataType::smallint();
+}
+
+/**
+ * Create a SERIAL (auto-incrementing integer) data type.
+ */
+#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)]
+function sql_type_serial() : DataType
+{
+ return DataType::serial();
+}
+
+/**
+ * Create a BIGSERIAL (auto-incrementing bigint) data type.
+ */
+#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)]
+function sql_type_bigserial() : DataType
+{
+ return DataType::bigserial();
+}
+
+/**
+ * Create a SMALLSERIAL (auto-incrementing smallint) data type.
+ */
+#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)]
+function sql_type_smallserial() : DataType
+{
+ return DataType::smallserial();
+}
+
+/**
+ * Create a TEXT data type.
+ */
+#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)]
+function sql_type_text() : DataType
+{
+ return DataType::text();
+}
+
+/**
+ * Create a VARCHAR data type.
+ *
+ * @param int $length Maximum character length
+ */
+#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)]
+function sql_type_varchar(int $length) : DataType
+{
+ return DataType::varchar($length);
+}
+
+/**
+ * Create a CHAR data type.
+ *
+ * @param int $length Fixed character length
+ */
+#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)]
+function sql_type_char(int $length) : DataType
+{
+ return DataType::char($length);
+}
+
+/**
+ * Create a BOOLEAN data type.
+ */
+#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)]
+function sql_type_boolean() : DataType
+{
+ return DataType::boolean();
+}
+
+/**
+ * Create a DATE data type.
+ */
+#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)]
+function sql_type_date() : DataType
+{
+ return DataType::date();
+}
+
+/**
+ * Create a TIME data type.
+ *
+ * @param null|int $precision Fractional seconds precision
+ */
+#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)]
+function sql_type_time(?int $precision = null) : DataType
+{
+ return DataType::time($precision);
+}
+
+/**
+ * Create a TIMESTAMP data type.
+ *
+ * @param null|int $precision Fractional seconds precision
+ */
+#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)]
+function sql_type_timestamp(?int $precision = null) : DataType
+{
+ return DataType::timestamp($precision);
+}
+
+/**
+ * Create a TIMESTAMP WITH TIME ZONE data type.
+ *
+ * @param null|int $precision Fractional seconds precision
+ */
+#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)]
+function sql_type_timestamptz(?int $precision = null) : DataType
+{
+ return DataType::timestamptz($precision);
+}
+
+/**
+ * Create an INTERVAL data type.
+ */
+#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)]
+function sql_type_interval() : DataType
+{
+ return DataType::interval();
+}
+
+/**
+ * Create a NUMERIC data type.
+ *
+ * @param null|int $precision Total number of digits
+ * @param null|int $scale Number of digits after decimal point
+ */
+#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)]
+function sql_type_numeric(?int $precision = null, ?int $scale = null) : DataType
+{
+ return DataType::numeric($precision, $scale);
+}
+
+/**
+ * Create a DECIMAL data type (alias for NUMERIC).
+ *
+ * @param null|int $precision Total number of digits
+ * @param null|int $scale Number of digits after decimal point
+ */
+#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)]
+function sql_type_decimal(?int $precision = null, ?int $scale = null) : DataType
+{
+ return DataType::decimal($precision, $scale);
+}
+
+/**
+ * Create a REAL data type.
+ */
+#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)]
+function sql_type_real() : DataType
+{
+ return DataType::real();
+}
+
+/**
+ * Create a DOUBLE PRECISION data type.
+ */
+#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)]
+function sql_type_double() : DataType
+{
+ return DataType::doublePrecision();
+}
+
+/**
+ * Create a UUID data type.
+ */
+#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)]
+function sql_type_uuid() : DataType
+{
+ return DataType::uuid();
+}
+
+/**
+ * Create a JSON data type.
+ */
+#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)]
+function sql_type_json() : DataType
+{
+ return DataType::json();
+}
+
+/**
+ * Create a JSONB data type.
+ */
+#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)]
+function sql_type_jsonb() : DataType
+{
+ return DataType::jsonb();
+}
+
+/**
+ * Create a BYTEA data type.
+ */
+#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)]
+function sql_type_bytea() : DataType
+{
+ return DataType::bytea();
+}
+
+/**
+ * Create an INET data type.
+ */
+#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)]
+function sql_type_inet() : DataType
+{
+ return DataType::inet();
+}
+
+/**
+ * Create a CIDR data type.
+ */
+#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)]
+function sql_type_cidr() : DataType
+{
+ return DataType::cidr();
+}
+
+/**
+ * Create a MACADDR data type.
+ */
+#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)]
+function sql_type_macaddr() : DataType
+{
+ return DataType::macaddr();
+}
+
+/**
+ * Create an ARRAY data type.
+ *
+ * @param DataType $elementType The type of array elements
+ */
+#[DocumentationDSL(module: Module::PG_QUERY, type: DSLType::HELPER)]
+function sql_type_array(DataType $elementType) : DataType
+{
+ return DataType::array($elementType);
+}
+
+// ----------------------------------------------------------------------------
+// Column Definitions
+// ----------------------------------------------------------------------------
+
+/**
+ * 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);
+}
+
+// ----------------------------------------------------------------------------
+// Table Constraints
+// ----------------------------------------------------------------------------
+
+/**
+ * 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);
+}
+
+// ----------------------------------------------------------------------------
+// DDL Factory Entry Points
+// ----------------------------------------------------------------------------
+
+/**
+ * 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', sql_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', sql_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);
+}
+
+// ----------------------------------------------------------------------------
+// Referential Actions (for Foreign Keys)
+// ----------------------------------------------------------------------------
+
+/**
+ * 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;
+}
+
+// ----------------------------------------------------------------------------
+// Utility Commands
+// ----------------------------------------------------------------------------
+
+/**
+ * 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);
+}
+
+// ----------------------------------------------------------------------------
+// Grant/Revoke Commands
+// ----------------------------------------------------------------------------
+
+/**
+ * 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);
+}
+
+// ----------------------------------------------------------------------------
+// Session Commands
+// ----------------------------------------------------------------------------
+
+/**
+ * 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();
+}
+
+// ----------------------------------------------------------------------------
+// Ownership Commands
+// ----------------------------------------------------------------------------
+
+/**
+ * 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);
+}
+
+// =====================================================
+// Function and Procedure Helpers
+// =====================================================
+
+/**
+ * Creates a new function argument for use in function/procedure definitions.
+ *
+ * Example: func_arg(sql_type_integer())
+ * Example: func_arg(sql_type_text())->named('username')
+ * Example: func_arg(sql_type_integer())->named('count')->default('0')
+ * Example: func_arg(sql_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);
+}
+
+// =====================================================
+// Type Helpers
+// =====================================================
+
+/**
+ * Creates a type attribute for composite types.
+ *
+ * Example: type_attr('name', sql_type_text())
+ * Produces: name text
+ *
+ * Example: type_attr('description', sql_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);
+}
diff --git a/src/lib/pg-query/src/Flow/PgQuery/DeparseOptions.php b/src/lib/postgresql/src/Flow/PostgreSql/DeparseOptions.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/DeparseOptions.php
rename to src/lib/postgresql/src/Flow/PostgreSql/DeparseOptions.php
index 16e756431..aca013128 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/DeparseOptions.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/DeparseOptions.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace Flow\PgQuery;
+namespace Flow\PostgreSql;
final class DeparseOptions
{
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Exception/ExtensionNotLoadedException.php b/src/lib/postgresql/src/Flow/PostgreSql/Exception/ExtensionNotLoadedException.php
similarity index 87%
rename from src/lib/pg-query/src/Flow/PgQuery/Exception/ExtensionNotLoadedException.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Exception/ExtensionNotLoadedException.php
index 685ac4f07..23ec7e901 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Exception/ExtensionNotLoadedException.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Exception/ExtensionNotLoadedException.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace Flow\PgQuery\Exception;
+namespace Flow\PostgreSql\Exception;
final class ExtensionNotLoadedException extends \RuntimeException
{
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Exception/PaginationException.php b/src/lib/postgresql/src/Flow/PostgreSql/Exception/PaginationException.php
similarity index 73%
rename from src/lib/pg-query/src/Flow/PgQuery/Exception/PaginationException.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Exception/PaginationException.php
index 2c17cadaa..92daa297a 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Exception/PaginationException.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Exception/PaginationException.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace Flow\PgQuery\Exception;
+namespace Flow\PostgreSql\Exception;
final class PaginationException extends TransformationException
{
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Exception/ParserException.php b/src/lib/postgresql/src/Flow/PostgreSql/Exception/ParserException.php
similarity index 71%
rename from src/lib/pg-query/src/Flow/PgQuery/Exception/ParserException.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Exception/ParserException.php
index 597cf7417..13fcdb9cb 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Exception/ParserException.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Exception/ParserException.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace Flow\PgQuery\Exception;
+namespace Flow\PostgreSql\Exception;
final class ParserException extends \RuntimeException
{
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Exception/TransformationException.php b/src/lib/postgresql/src/Flow/PostgreSql/Exception/TransformationException.php
similarity index 71%
rename from src/lib/pg-query/src/Flow/PgQuery/Exception/TransformationException.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Exception/TransformationException.php
index 28ca1b621..2e70c863f 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Exception/TransformationException.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Exception/TransformationException.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace Flow\PgQuery\Exception;
+namespace Flow\PostgreSql\Exception;
class TransformationException extends \RuntimeException
{
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Extractors/Columns.php b/src/lib/postgresql/src/Flow/PostgreSql/Extractors/Columns.php
similarity index 82%
rename from src/lib/pg-query/src/Flow/PgQuery/Extractors/Columns.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Extractors/Columns.php
index c85b5763a..b812ad378 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Extractors/Columns.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Extractors/Columns.php
@@ -2,11 +2,11 @@
declare(strict_types=1);
-namespace Flow\PgQuery\Extractors;
+namespace Flow\PostgreSql\Extractors;
-use Flow\PgQuery\AST\Nodes\Column;
-use Flow\PgQuery\AST\Visitors\ColumnRefCollector;
-use Flow\PgQuery\ParsedQuery;
+use Flow\PostgreSql\AST\Nodes\Column;
+use Flow\PostgreSql\AST\Visitors\ColumnRefCollector;
+use Flow\PostgreSql\ParsedQuery;
final readonly class Columns
{
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Extractors/Functions.php b/src/lib/postgresql/src/Flow/PostgreSql/Extractors/Functions.php
similarity index 76%
rename from src/lib/pg-query/src/Flow/PgQuery/Extractors/Functions.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Extractors/Functions.php
index 76ec335e6..4808b27dc 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Extractors/Functions.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Extractors/Functions.php
@@ -2,11 +2,11 @@
declare(strict_types=1);
-namespace Flow\PgQuery\Extractors;
+namespace Flow\PostgreSql\Extractors;
-use Flow\PgQuery\AST\Nodes\FunctionCall;
-use Flow\PgQuery\AST\Visitors\FuncCallCollector;
-use Flow\PgQuery\ParsedQuery;
+use Flow\PostgreSql\AST\Nodes\FunctionCall;
+use Flow\PostgreSql\AST\Visitors\FuncCallCollector;
+use Flow\PostgreSql\ParsedQuery;
final readonly class Functions
{
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Extractors/Tables.php b/src/lib/postgresql/src/Flow/PostgreSql/Extractors/Tables.php
similarity index 76%
rename from src/lib/pg-query/src/Flow/PgQuery/Extractors/Tables.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Extractors/Tables.php
index bf6560b49..74bb10f3f 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Extractors/Tables.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Extractors/Tables.php
@@ -2,11 +2,11 @@
declare(strict_types=1);
-namespace Flow\PgQuery\Extractors;
+namespace Flow\PostgreSql\Extractors;
-use Flow\PgQuery\AST\Nodes\Table;
-use Flow\PgQuery\AST\Visitors\RangeVarCollector;
-use Flow\PgQuery\ParsedQuery;
+use Flow\PostgreSql\AST\Nodes\Table;
+use Flow\PostgreSql\AST\Visitors\RangeVarCollector;
+use Flow\PostgreSql\ParsedQuery;
final readonly class Tables
{
diff --git a/src/lib/pg-query/src/Flow/PgQuery/NamedParameterNormalizer.php b/src/lib/postgresql/src/Flow/PostgreSql/NamedParameterNormalizer.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/NamedParameterNormalizer.php
rename to src/lib/postgresql/src/Flow/PostgreSql/NamedParameterNormalizer.php
index c8c2a4546..4bb0e834e 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/NamedParameterNormalizer.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/NamedParameterNormalizer.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace Flow\PgQuery;
+namespace Flow\PostgreSql;
final class NamedParameterNormalizer
{
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/ParsedQuery.php b/src/lib/postgresql/src/Flow/PostgreSql/ParsedQuery.php
new file mode 100644
index 000000000..90ee920f3
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/ParsedQuery.php
@@ -0,0 +1,175 @@
+parseResult->serializeToString());
+ }
+
+ return \pg_query_deparse_opts(
+ $this->parseResult->serializeToString(),
+ $options->hasPrettyPrint(),
+ $options->getIndentSize(),
+ $options->getMaxLineLength(),
+ $options->hasTrailingNewline(),
+ $options->commasAtStartOfLine()
+ );
+ }
+
+ public function raw() : ParseResult
+ {
+ return $this->parseResult;
+ }
+
+ /**
+ * Convert parsed query to a DeleteBuilder.
+ *
+ * @throws \InvalidArgumentException if query is not a DELETE statement
+ */
+ public function toDeleteBuilder() : DeleteBuilder
+ {
+ $node = $this->getSingleStatementNode();
+
+ if ($node->getDeleteStmt() === null) {
+ throw new \InvalidArgumentException('Query is not a DELETE statement');
+ }
+
+ return DeleteBuilder::fromAst($node);
+ }
+
+ /**
+ * Convert parsed query to an InsertBuilder.
+ *
+ * @throws \InvalidArgumentException if query is not an INSERT statement
+ */
+ public function toInsertBuilder() : InsertBuilder
+ {
+ $node = $this->getSingleStatementNode();
+
+ if ($node->getInsertStmt() === null) {
+ throw new \InvalidArgumentException('Query is not an INSERT statement');
+ }
+
+ return InsertBuilder::fromAst($node);
+ }
+
+ /**
+ * Convert parsed query to a QueryBuilder.
+ *
+ * Only works for single-statement queries. For multiple statements,
+ * use pg_split() to parse statements individually.
+ *
+ * @throws \InvalidArgumentException if query contains multiple statements or unsupported statement type
+ */
+ public function toQueryBuilder() : SelectBuilder|InsertBuilder|UpdateBuilder|DeleteBuilder
+ {
+ $node = $this->getSingleStatementNode();
+
+ return match (true) {
+ $node->getSelectStmt() !== null => SelectBuilder::fromAst($node),
+ $node->getInsertStmt() !== null => InsertBuilder::fromAst($node),
+ $node->getUpdateStmt() !== null => UpdateBuilder::fromAst($node),
+ $node->getDeleteStmt() !== null => DeleteBuilder::fromAst($node),
+ default => throw new \InvalidArgumentException('Unsupported statement type'),
+ };
+ }
+
+ /**
+ * Convert parsed query to a SelectBuilder.
+ *
+ * @throws \InvalidArgumentException if query is not a SELECT statement
+ */
+ public function toSelectBuilder() : SelectBuilder
+ {
+ $node = $this->getSingleStatementNode();
+
+ if ($node->getSelectStmt() === null) {
+ throw new \InvalidArgumentException('Query is not a SELECT statement');
+ }
+
+ return SelectBuilder::fromAst($node);
+ }
+
+ /**
+ * Convert parsed query to an UpdateBuilder.
+ *
+ * @throws \InvalidArgumentException if query is not an UPDATE statement
+ */
+ public function toUpdateBuilder() : UpdateBuilder
+ {
+ $node = $this->getSingleStatementNode();
+
+ if ($node->getUpdateStmt() === null) {
+ throw new \InvalidArgumentException('Query is not an UPDATE statement');
+ }
+
+ return UpdateBuilder::fromAst($node);
+ }
+
+ /**
+ * Traverse the AST with visitors and/or modifiers.
+ *
+ * Visitors collect information (read-only), modifiers mutate nodes.
+ * Returns $this to allow method chaining.
+ */
+ public function traverse(NodeVisitor|NodeModifier ...$handlers) : self
+ {
+ $traverser = new Traverser(...$handlers);
+ $traverser->traverse($this->parseResult);
+
+ return $this;
+ }
+
+ /**
+ * @throws \InvalidArgumentException if no statements or multiple statements found
+ */
+ private function getSingleStatementNode() : Node
+ {
+ $stmts = $this->parseResult->getStmts();
+ $count = \count($stmts);
+
+ if ($count === 0) {
+ throw new \InvalidArgumentException('No statements found');
+ }
+
+ if ($count > 1) {
+ throw new \InvalidArgumentException(
+ 'Multiple statements found. Use pg_split() to parse statements individually.'
+ );
+ }
+
+ $node = $stmts[0]->getStmt();
+
+ if ($node === null) {
+ throw new \InvalidArgumentException('Statement has no node');
+ }
+
+ return $node;
+ }
+}
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Parser.php b/src/lib/postgresql/src/Flow/PostgreSql/Parser.php
similarity index 91%
rename from src/lib/pg-query/src/Flow/PgQuery/Parser.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Parser.php
index 4d1c1708f..0d973dcd0 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Parser.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Parser.php
@@ -2,10 +2,10 @@
declare(strict_types=1);
-namespace Flow\PgQuery;
+namespace Flow\PostgreSql;
-use Flow\PgQuery\Exception\{ExtensionNotLoadedException, ParserException};
-use Flow\PgQuery\Protobuf\AST\ParseResult;
+use Flow\PostgreSql\Exception\{ExtensionNotLoadedException, ParserException};
+use Flow\PostgreSql\Protobuf\AST\ParseResult;
final class Parser
{
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/A_ArrayExpr.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/A_ArrayExpr.php
similarity index 96%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/A_ArrayExpr.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/A_ArrayExpr.php
index a753cef78..3aaaaae15 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/A_ArrayExpr.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/A_ArrayExpr.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/A_Const.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/A_Const.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/A_Const.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/A_Const.php
index 93b83afdc..e7cfdc0d8 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/A_Const.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/A_Const.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/A_Expr.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/A_Expr.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/A_Expr.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/A_Expr.php
index 5648d7fdd..156c57625 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/A_Expr.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/A_Expr.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/A_Expr_Kind.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/A_Expr_Kind.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/A_Expr_Kind.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/A_Expr_Kind.php
index 2711361ef..c72b201ed 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/A_Expr_Kind.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/A_Expr_Kind.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.A_Expr_Kind.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/A_Indices.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/A_Indices.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/A_Indices.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/A_Indices.php
index daa24aba1..a91abddd4 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/A_Indices.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/A_Indices.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/A_Indirection.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/A_Indirection.php
similarity index 96%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/A_Indirection.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/A_Indirection.php
index d3046d9dc..51fa57de4 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/A_Indirection.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/A_Indirection.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/A_Star.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/A_Star.php
similarity index 87%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/A_Star.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/A_Star.php
index 9dd321b60..cfc2d0245 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/A_Star.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/A_Star.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\Message;
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AccessPriv.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AccessPriv.php
similarity index 96%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AccessPriv.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AccessPriv.php
index 337e5c62d..bea8904b2 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AccessPriv.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AccessPriv.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AggSplit.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AggSplit.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AggSplit.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AggSplit.php
index 2a9d09fe9..020c0e058 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AggSplit.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AggSplit.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.AggSplit.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AggStrategy.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AggStrategy.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AggStrategy.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AggStrategy.php
index c3cd15a51..84ce2e27d 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AggStrategy.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AggStrategy.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.AggStrategy.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/Aggref.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/Aggref.php
similarity index 99%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/Aggref.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/Aggref.php
index 9e48f3bbc..37f147c61 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/Aggref.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/Aggref.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/Alias.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/Alias.php
similarity index 96%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/Alias.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/Alias.php
index 04ada64ef..93ae39944 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/Alias.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/Alias.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterCollationStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterCollationStmt.php
similarity index 94%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterCollationStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterCollationStmt.php
index 5f4ce702b..9376f711b 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterCollationStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterCollationStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterDatabaseRefreshCollStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterDatabaseRefreshCollStmt.php
similarity index 93%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterDatabaseRefreshCollStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterDatabaseRefreshCollStmt.php
index 9d79f09ae..e12897760 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterDatabaseRefreshCollStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterDatabaseRefreshCollStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterDatabaseSetStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterDatabaseSetStmt.php
similarity index 96%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterDatabaseSetStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterDatabaseSetStmt.php
index a53d6c58c..bfa10c779 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterDatabaseSetStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterDatabaseSetStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterDatabaseStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterDatabaseStmt.php
similarity index 96%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterDatabaseStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterDatabaseStmt.php
index f0a6a470d..a7e28b8d1 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterDatabaseStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterDatabaseStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterDefaultPrivilegesStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterDefaultPrivilegesStmt.php
similarity index 96%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterDefaultPrivilegesStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterDefaultPrivilegesStmt.php
index 811333e1b..174413839 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterDefaultPrivilegesStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterDefaultPrivilegesStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterDomainStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterDomainStmt.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterDomainStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterDomainStmt.php
index d9b314e8e..30c1b72cb 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterDomainStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterDomainStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterEnumStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterEnumStmt.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterEnumStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterEnumStmt.php
index a5a6ba233..dfc63bfa3 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterEnumStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterEnumStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterEventTrigStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterEventTrigStmt.php
similarity index 95%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterEventTrigStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterEventTrigStmt.php
index 12f4a1eb8..1212248d5 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterEventTrigStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterEventTrigStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterExtensionContentsStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterExtensionContentsStmt.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterExtensionContentsStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterExtensionContentsStmt.php
index 86ac6c0a3..7e0394237 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterExtensionContentsStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterExtensionContentsStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterExtensionStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterExtensionStmt.php
similarity index 96%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterExtensionStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterExtensionStmt.php
index 2292b8b07..d8c8b9d37 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterExtensionStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterExtensionStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterFdwStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterFdwStmt.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterFdwStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterFdwStmt.php
index 059c72e99..de3090ba5 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterFdwStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterFdwStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterForeignServerStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterForeignServerStmt.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterForeignServerStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterForeignServerStmt.php
index 3ae71fb1e..473396f88 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterForeignServerStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterForeignServerStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterFunctionStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterFunctionStmt.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterFunctionStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterFunctionStmt.php
index dbc5cd7fb..e9ec01349 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterFunctionStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterFunctionStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterObjectDependsStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterObjectDependsStmt.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterObjectDependsStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterObjectDependsStmt.php
index 0a283f285..a3e08b3aa 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterObjectDependsStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterObjectDependsStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterObjectSchemaStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterObjectSchemaStmt.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterObjectSchemaStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterObjectSchemaStmt.php
index 14a21f5a2..fe662ca99 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterObjectSchemaStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterObjectSchemaStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterOpFamilyStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterOpFamilyStmt.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterOpFamilyStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterOpFamilyStmt.php
index 9b23c88d4..455a0c2b3 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterOpFamilyStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterOpFamilyStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterOperatorStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterOperatorStmt.php
similarity index 96%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterOperatorStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterOperatorStmt.php
index 3aa2da3c9..5ec3428b2 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterOperatorStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterOperatorStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterOwnerStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterOwnerStmt.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterOwnerStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterOwnerStmt.php
index ddbca7ddf..9b0f02ef9 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterOwnerStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterOwnerStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterPolicyStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterPolicyStmt.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterPolicyStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterPolicyStmt.php
index f62f7d76c..3c54cd813 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterPolicyStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterPolicyStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterPublicationAction.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterPublicationAction.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterPublicationAction.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterPublicationAction.php
index 8592f1ceb..73d7f483e 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterPublicationAction.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterPublicationAction.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.AlterPublicationAction.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterPublicationStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterPublicationStmt.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterPublicationStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterPublicationStmt.php
index 5c748b9b7..708807ff7 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterPublicationStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterPublicationStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterRoleSetStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterRoleSetStmt.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterRoleSetStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterRoleSetStmt.php
index a4192e5aa..d1e83d880 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterRoleSetStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterRoleSetStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterRoleStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterRoleStmt.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterRoleStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterRoleStmt.php
index 5f27641b1..e4e46f2a7 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterRoleStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterRoleStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterSeqStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterSeqStmt.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterSeqStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterSeqStmt.php
index 877e9ad0e..41cd58623 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterSeqStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterSeqStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterStatsStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterStatsStmt.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterStatsStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterStatsStmt.php
index 6fd199edc..40d23e58a 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterStatsStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterStatsStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterSubscriptionStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterSubscriptionStmt.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterSubscriptionStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterSubscriptionStmt.php
index 35b8e67fd..32f154128 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterSubscriptionStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterSubscriptionStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterSubscriptionType.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterSubscriptionType.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterSubscriptionType.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterSubscriptionType.php
index 29bd78590..5744667f1 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterSubscriptionType.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterSubscriptionType.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.AlterSubscriptionType.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterSystemStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterSystemStmt.php
similarity index 94%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterSystemStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterSystemStmt.php
index 6f73138cc..af04fe75b 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterSystemStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterSystemStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterTSConfigType.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterTSConfigType.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterTSConfigType.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterTSConfigType.php
index 29d724d04..504e57cfd 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterTSConfigType.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterTSConfigType.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.AlterTSConfigType.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterTSConfigurationStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterTSConfigurationStmt.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterTSConfigurationStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterTSConfigurationStmt.php
index b18697009..83e56309c 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterTSConfigurationStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterTSConfigurationStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterTSDictionaryStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterTSDictionaryStmt.php
similarity index 96%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterTSDictionaryStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterTSDictionaryStmt.php
index b0a2389d7..3efb46bf4 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterTSDictionaryStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterTSDictionaryStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterTableCmd.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterTableCmd.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterTableCmd.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterTableCmd.php
index db288cb99..db7e2862b 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterTableCmd.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterTableCmd.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterTableMoveAllStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterTableMoveAllStmt.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterTableMoveAllStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterTableMoveAllStmt.php
index 23ee336fb..a1056fafa 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterTableMoveAllStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterTableMoveAllStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterTableSpaceOptionsStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterTableSpaceOptionsStmt.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterTableSpaceOptionsStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterTableSpaceOptionsStmt.php
index cd12f064e..dbde7b674 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterTableSpaceOptionsStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterTableSpaceOptionsStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterTableStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterTableStmt.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterTableStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterTableStmt.php
index 2f875bfdd..36fa5d072 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterTableStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterTableStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterTableType.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterTableType.php
similarity index 99%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterTableType.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterTableType.php
index ef133fa42..81a8286b3 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterTableType.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterTableType.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.AlterTableType.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterTypeStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterTypeStmt.php
similarity index 96%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterTypeStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterTypeStmt.php
index 30b180c0e..58471cf2e 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterTypeStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterTypeStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterUserMappingStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterUserMappingStmt.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterUserMappingStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterUserMappingStmt.php
index 2d6f0fc04..fb4b38293 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlterUserMappingStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlterUserMappingStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlternativeSubPlan.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlternativeSubPlan.php
similarity index 96%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlternativeSubPlan.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlternativeSubPlan.php
index fd30bd369..5f26cded9 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/AlternativeSubPlan.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/AlternativeSubPlan.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ArrayCoerceExpr.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ArrayCoerceExpr.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ArrayCoerceExpr.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ArrayCoerceExpr.php
index 8bf3f09b0..763b77ea7 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ArrayCoerceExpr.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ArrayCoerceExpr.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ArrayExpr.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ArrayExpr.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ArrayExpr.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ArrayExpr.php
index 96423dde0..8d0979f20 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ArrayExpr.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ArrayExpr.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/BitString.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/BitString.php
similarity index 93%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/BitString.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/BitString.php
index 2bfbd07de..870329472 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/BitString.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/BitString.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/BoolExpr.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/BoolExpr.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/BoolExpr.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/BoolExpr.php
index d0ab7ff31..eba140b29 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/BoolExpr.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/BoolExpr.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/BoolExprType.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/BoolExprType.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/BoolExprType.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/BoolExprType.php
index ddf187ee0..16137b66d 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/BoolExprType.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/BoolExprType.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.BoolExprType.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/BoolTestType.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/BoolTestType.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/BoolTestType.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/BoolTestType.php
index 186884968..3ed09bf52 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/BoolTestType.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/BoolTestType.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.BoolTestType.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/Boolean.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/Boolean.php
similarity index 93%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/Boolean.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/Boolean.php
index 3c08d5fb0..95ffa2301 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/Boolean.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/Boolean.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/BooleanTest.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/BooleanTest.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/BooleanTest.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/BooleanTest.php
index 41e47b841..c529e0855 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/BooleanTest.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/BooleanTest.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CTECycleClause.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CTECycleClause.php
similarity index 99%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CTECycleClause.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CTECycleClause.php
index 21ab9b914..f437f9504 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CTECycleClause.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CTECycleClause.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CTEMaterialize.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CTEMaterialize.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CTEMaterialize.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CTEMaterialize.php
index 9d7da4c15..65c233a38 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CTEMaterialize.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CTEMaterialize.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.CTEMaterialize.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CTESearchClause.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CTESearchClause.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CTESearchClause.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CTESearchClause.php
index f671188dc..be63218cf 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CTESearchClause.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CTESearchClause.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CallContext.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CallContext.php
similarity index 93%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CallContext.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CallContext.php
index bbb434b92..27f444615 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CallContext.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CallContext.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CallStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CallStmt.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CallStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CallStmt.php
index 992f67e46..1b577884f 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CallStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CallStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CaseExpr.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CaseExpr.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CaseExpr.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CaseExpr.php
index fbdbbf09d..825e257d3 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CaseExpr.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CaseExpr.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CaseTestExpr.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CaseTestExpr.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CaseTestExpr.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CaseTestExpr.php
index bbfd0c79a..7f9460d4e 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CaseTestExpr.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CaseTestExpr.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CaseWhen.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CaseWhen.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CaseWhen.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CaseWhen.php
index 61da844e0..2a2c69f85 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CaseWhen.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CaseWhen.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CheckPointStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CheckPointStmt.php
similarity index 87%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CheckPointStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CheckPointStmt.php
index 5982136a5..fbb4d82c3 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CheckPointStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CheckPointStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\Message;
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ClosePortalStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ClosePortalStmt.php
similarity index 94%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ClosePortalStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ClosePortalStmt.php
index fcc5dfbcb..e1496e645 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ClosePortalStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ClosePortalStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ClusterStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ClusterStmt.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ClusterStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ClusterStmt.php
index 20446fdca..45946cc41 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ClusterStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ClusterStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CmdType.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CmdType.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CmdType.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CmdType.php
index c91f3c6c9..7efaa58dc 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CmdType.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CmdType.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.CmdType.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CoalesceExpr.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CoalesceExpr.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CoalesceExpr.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CoalesceExpr.php
index fbb588f5f..d521654d7 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CoalesceExpr.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CoalesceExpr.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CoerceToDomain.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CoerceToDomain.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CoerceToDomain.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CoerceToDomain.php
index 30dc65a30..d889ed343 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CoerceToDomain.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CoerceToDomain.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CoerceToDomainValue.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CoerceToDomainValue.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CoerceToDomainValue.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CoerceToDomainValue.php
index 58a24fec7..7376b3dce 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CoerceToDomainValue.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CoerceToDomainValue.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CoerceViaIO.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CoerceViaIO.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CoerceViaIO.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CoerceViaIO.php
index ca72274b4..b53a00490 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CoerceViaIO.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CoerceViaIO.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CoercionContext.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CoercionContext.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CoercionContext.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CoercionContext.php
index 763b8fea3..c00a350c9 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CoercionContext.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CoercionContext.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.CoercionContext.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CoercionForm.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CoercionForm.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CoercionForm.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CoercionForm.php
index 44563fadd..bd3ebe782 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CoercionForm.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CoercionForm.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.CoercionForm.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CollateClause.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CollateClause.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CollateClause.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CollateClause.php
index a9e685095..1ee4c7f4f 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CollateClause.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CollateClause.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CollateExpr.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CollateExpr.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CollateExpr.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CollateExpr.php
index c880928dd..750bc243f 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CollateExpr.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CollateExpr.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ColumnDef.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ColumnDef.php
similarity index 99%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ColumnDef.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ColumnDef.php
index a712926cc..8be13aee0 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ColumnDef.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ColumnDef.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ColumnRef.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ColumnRef.php
similarity index 96%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ColumnRef.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ColumnRef.php
index 734ff35a4..2d2719ead 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ColumnRef.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ColumnRef.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CommentStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CommentStmt.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CommentStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CommentStmt.php
index 88e787805..1a6af23df 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CommentStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CommentStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CommonTableExpr.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CommonTableExpr.php
similarity index 99%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CommonTableExpr.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CommonTableExpr.php
index 3d782b2ba..a4d291039 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CommonTableExpr.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CommonTableExpr.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CompositeTypeStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CompositeTypeStmt.php
similarity index 96%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CompositeTypeStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CompositeTypeStmt.php
index 5f55612db..e112e5af7 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CompositeTypeStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CompositeTypeStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ConstrType.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ConstrType.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ConstrType.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ConstrType.php
index 6c9d2b719..10846dba7 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ConstrType.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ConstrType.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.ConstrType.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/Constraint.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/Constraint.php
similarity index 99%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/Constraint.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/Constraint.php
index 46cce146c..7441c4eed 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/Constraint.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/Constraint.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ConstraintsSetStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ConstraintsSetStmt.php
similarity index 96%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ConstraintsSetStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ConstraintsSetStmt.php
index 8d7950853..c1957ea3b 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ConstraintsSetStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ConstraintsSetStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ConvertRowtypeExpr.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ConvertRowtypeExpr.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ConvertRowtypeExpr.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ConvertRowtypeExpr.php
index 8ab10a5a9..ea4b1439a 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ConvertRowtypeExpr.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ConvertRowtypeExpr.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CopyStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CopyStmt.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CopyStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CopyStmt.php
index 20f96fc8a..f8c606138 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CopyStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CopyStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateAmStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateAmStmt.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateAmStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateAmStmt.php
index 12cb699fb..4c98de0fa 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateAmStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateAmStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateCastStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateCastStmt.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateCastStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateCastStmt.php
index 5885603f2..1e4da75b0 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateCastStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateCastStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateConversionStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateConversionStmt.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateConversionStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateConversionStmt.php
index 6762b8aff..29fece56a 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateConversionStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateConversionStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateDomainStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateDomainStmt.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateDomainStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateDomainStmt.php
index d79beb220..186a16442 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateDomainStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateDomainStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateEnumStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateEnumStmt.php
similarity index 96%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateEnumStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateEnumStmt.php
index 0b695b08e..faac83f25 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateEnumStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateEnumStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateEventTrigStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateEventTrigStmt.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateEventTrigStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateEventTrigStmt.php
index 06048d2ee..e4819f079 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateEventTrigStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateEventTrigStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateExtensionStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateExtensionStmt.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateExtensionStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateExtensionStmt.php
index fb28e0e33..d12dacd24 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateExtensionStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateExtensionStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateFdwStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateFdwStmt.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateFdwStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateFdwStmt.php
index 5acc77829..e08918c4e 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateFdwStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateFdwStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateForeignServerStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateForeignServerStmt.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateForeignServerStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateForeignServerStmt.php
index 3ba154fcc..f581d9617 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateForeignServerStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateForeignServerStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateForeignTableStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateForeignTableStmt.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateForeignTableStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateForeignTableStmt.php
index 09aea8bfb..1dfa7f053 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateForeignTableStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateForeignTableStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateFunctionStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateFunctionStmt.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateFunctionStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateFunctionStmt.php
index 026290939..a5cf64261 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateFunctionStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateFunctionStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateOpClassItem.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateOpClassItem.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateOpClassItem.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateOpClassItem.php
index ac988fa96..d4260f5af 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateOpClassItem.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateOpClassItem.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateOpClassStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateOpClassStmt.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateOpClassStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateOpClassStmt.php
index 90d37aba3..c53b427a8 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateOpClassStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateOpClassStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateOpFamilyStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateOpFamilyStmt.php
similarity index 96%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateOpFamilyStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateOpFamilyStmt.php
index dc34c5c2c..1c114e877 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateOpFamilyStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateOpFamilyStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreatePLangStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreatePLangStmt.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreatePLangStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreatePLangStmt.php
index 73c44d3f9..e892eb356 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreatePLangStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreatePLangStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreatePolicyStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreatePolicyStmt.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreatePolicyStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreatePolicyStmt.php
index 5f135fba9..405ca6baa 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreatePolicyStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreatePolicyStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreatePublicationStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreatePublicationStmt.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreatePublicationStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreatePublicationStmt.php
index 30d393a65..06f007c35 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreatePublicationStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreatePublicationStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateRangeStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateRangeStmt.php
similarity index 96%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateRangeStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateRangeStmt.php
index c04b59bf2..a9dc171f4 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateRangeStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateRangeStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateRoleStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateRoleStmt.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateRoleStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateRoleStmt.php
index beb93350b..e0866f4c8 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateRoleStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateRoleStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateSchemaStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateSchemaStmt.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateSchemaStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateSchemaStmt.php
index b2b4387cf..310907178 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateSchemaStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateSchemaStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateSeqStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateSeqStmt.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateSeqStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateSeqStmt.php
index 6925a9ec0..efc81c012 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateSeqStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateSeqStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateStatsStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateStatsStmt.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateStatsStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateStatsStmt.php
index 552c847b2..0fad07222 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateStatsStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateStatsStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateStmt.php
similarity index 99%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateStmt.php
index 3510bcc30..9ab5dca98 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateSubscriptionStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateSubscriptionStmt.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateSubscriptionStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateSubscriptionStmt.php
index da808116a..5328a817c 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateSubscriptionStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateSubscriptionStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateTableAsStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateTableAsStmt.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateTableAsStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateTableAsStmt.php
index 5467d407e..5a81ef475 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateTableAsStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateTableAsStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateTableSpaceStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateTableSpaceStmt.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateTableSpaceStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateTableSpaceStmt.php
index 6709bdc25..5183d4467 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateTableSpaceStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateTableSpaceStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateTransformStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateTransformStmt.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateTransformStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateTransformStmt.php
index 8c0e84cc6..54c754061 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateTransformStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateTransformStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateTrigStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateTrigStmt.php
similarity index 99%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateTrigStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateTrigStmt.php
index 48a6f4627..af0e2276d 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateTrigStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateTrigStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateUserMappingStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateUserMappingStmt.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateUserMappingStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateUserMappingStmt.php
index cff74f037..ade1f0db9 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreateUserMappingStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreateUserMappingStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreatedbStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreatedbStmt.php
similarity index 96%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreatedbStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreatedbStmt.php
index 997ceb62a..8db38f180 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CreatedbStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CreatedbStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CurrentOfExpr.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CurrentOfExpr.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CurrentOfExpr.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CurrentOfExpr.php
index a97cf9187..0d1f3cc4f 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/CurrentOfExpr.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/CurrentOfExpr.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DeallocateStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DeallocateStmt.php
similarity index 96%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DeallocateStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DeallocateStmt.php
index 89aa8db07..26266c922 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DeallocateStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DeallocateStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DeclareCursorStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DeclareCursorStmt.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DeclareCursorStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DeclareCursorStmt.php
index 29d4e5273..c676b435d 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DeclareCursorStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DeclareCursorStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DefElem.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DefElem.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DefElem.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DefElem.php
index aaef01baa..f17282112 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DefElem.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DefElem.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DefElemAction.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DefElemAction.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DefElemAction.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DefElemAction.php
index f9f364d01..137c6c83a 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DefElemAction.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DefElemAction.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.DefElemAction.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DefineStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DefineStmt.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DefineStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DefineStmt.php
index ddb87ebc3..ff5644a39 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DefineStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DefineStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DeleteStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DeleteStmt.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DeleteStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DeleteStmt.php
index a73e00c62..c8162e7d2 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DeleteStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DeleteStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DiscardMode.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DiscardMode.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DiscardMode.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DiscardMode.php
index f3ac49f67..bd9da6a51 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DiscardMode.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DiscardMode.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.DiscardMode.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DiscardStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DiscardStmt.php
similarity index 93%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DiscardStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DiscardStmt.php
index 0376f197c..d993e2ac9 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DiscardStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DiscardStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DistinctExpr.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DistinctExpr.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DistinctExpr.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DistinctExpr.php
index 568e9ee97..c0c85337a 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DistinctExpr.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DistinctExpr.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DoStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DoStmt.php
similarity index 94%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DoStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DoStmt.php
index dcc45d964..b5f31d149 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DoStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DoStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DropBehavior.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DropBehavior.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DropBehavior.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DropBehavior.php
index da38affe2..e2840af50 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DropBehavior.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DropBehavior.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.DropBehavior.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DropOwnedStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DropOwnedStmt.php
similarity index 96%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DropOwnedStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DropOwnedStmt.php
index 5aa31618e..2ff1f096d 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DropOwnedStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DropOwnedStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DropRoleStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DropRoleStmt.php
similarity index 96%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DropRoleStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DropRoleStmt.php
index 8273751c8..3776166f8 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DropRoleStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DropRoleStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DropStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DropStmt.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DropStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DropStmt.php
index a470acb1b..0d34a2b37 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DropStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DropStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DropSubscriptionStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DropSubscriptionStmt.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DropSubscriptionStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DropSubscriptionStmt.php
index cd67aa7b5..f1596a1d3 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DropSubscriptionStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DropSubscriptionStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DropTableSpaceStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DropTableSpaceStmt.php
similarity index 96%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DropTableSpaceStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DropTableSpaceStmt.php
index bbf963df6..fabef2373 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DropTableSpaceStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DropTableSpaceStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DropUserMappingStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DropUserMappingStmt.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DropUserMappingStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DropUserMappingStmt.php
index f24e35a13..390ca9a85 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DropUserMappingStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DropUserMappingStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DropdbStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DropdbStmt.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DropdbStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DropdbStmt.php
index 58f28c7fd..95ffdbc3d 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/DropdbStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/DropdbStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ExecuteStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ExecuteStmt.php
similarity index 96%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ExecuteStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ExecuteStmt.php
index 9960b6e0a..ec930f665 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ExecuteStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ExecuteStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ExplainStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ExplainStmt.php
similarity index 96%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ExplainStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ExplainStmt.php
index 00da405f3..32df8a564 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ExplainStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ExplainStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/FetchDirection.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/FetchDirection.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/FetchDirection.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/FetchDirection.php
index 3c04d71fd..6c8dc100d 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/FetchDirection.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/FetchDirection.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.FetchDirection.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/FetchStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/FetchStmt.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/FetchStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/FetchStmt.php
index 39a7399d5..f043cd86c 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/FetchStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/FetchStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/FieldSelect.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/FieldSelect.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/FieldSelect.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/FieldSelect.php
index 40e191566..476ee34b7 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/FieldSelect.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/FieldSelect.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/FieldStore.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/FieldStore.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/FieldStore.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/FieldStore.php
index ed13f867a..2e7d9a0fd 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/FieldStore.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/FieldStore.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/FromExpr.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/FromExpr.php
similarity index 96%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/FromExpr.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/FromExpr.php
index 0c3cbb08d..ff3cec67b 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/FromExpr.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/FromExpr.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/FuncCall.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/FuncCall.php
similarity index 99%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/FuncCall.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/FuncCall.php
index fa6a5659a..f66a1acbd 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/FuncCall.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/FuncCall.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/FuncExpr.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/FuncExpr.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/FuncExpr.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/FuncExpr.php
index 937b412ee..cb97cfc40 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/FuncExpr.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/FuncExpr.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/FunctionParameter.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/FunctionParameter.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/FunctionParameter.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/FunctionParameter.php
index 20b194381..08b071dd0 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/FunctionParameter.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/FunctionParameter.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/FunctionParameterMode.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/FunctionParameterMode.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/FunctionParameterMode.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/FunctionParameterMode.php
index e41b91f3d..630f05166 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/FunctionParameterMode.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/FunctionParameterMode.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.FunctionParameterMode.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/GrantRoleStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/GrantRoleStmt.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/GrantRoleStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/GrantRoleStmt.php
index d46e45c34..ea7642418 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/GrantRoleStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/GrantRoleStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/GrantStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/GrantStmt.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/GrantStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/GrantStmt.php
index fe55fd937..63aa75cb6 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/GrantStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/GrantStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/GrantTargetType.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/GrantTargetType.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/GrantTargetType.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/GrantTargetType.php
index 9e4dc901c..433cb4264 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/GrantTargetType.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/GrantTargetType.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.GrantTargetType.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/GroupingFunc.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/GroupingFunc.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/GroupingFunc.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/GroupingFunc.php
index a43394f3f..34ac0e588 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/GroupingFunc.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/GroupingFunc.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/GroupingSet.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/GroupingSet.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/GroupingSet.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/GroupingSet.php
index b367c6da9..89b0b8d81 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/GroupingSet.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/GroupingSet.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/GroupingSetKind.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/GroupingSetKind.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/GroupingSetKind.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/GroupingSetKind.php
index 6c3188151..c48109c8e 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/GroupingSetKind.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/GroupingSetKind.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.GroupingSetKind.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ImportForeignSchemaStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ImportForeignSchemaStmt.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ImportForeignSchemaStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ImportForeignSchemaStmt.php
index 77a7c88a5..a19b4b307 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ImportForeignSchemaStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ImportForeignSchemaStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ImportForeignSchemaType.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ImportForeignSchemaType.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ImportForeignSchemaType.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ImportForeignSchemaType.php
index eba7fe800..2c345274c 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ImportForeignSchemaType.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ImportForeignSchemaType.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.ImportForeignSchemaType.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/IndexElem.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/IndexElem.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/IndexElem.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/IndexElem.php
index cb55057b7..c997a96e9 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/IndexElem.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/IndexElem.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/IndexStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/IndexStmt.php
similarity index 99%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/IndexStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/IndexStmt.php
index 1ea142a96..9bb8c22d1 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/IndexStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/IndexStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/InferClause.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/InferClause.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/InferClause.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/InferClause.php
index 191dd53fb..3e3d2418f 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/InferClause.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/InferClause.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/InferenceElem.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/InferenceElem.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/InferenceElem.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/InferenceElem.php
index 4826da1e9..0b638b25a 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/InferenceElem.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/InferenceElem.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/InlineCodeBlock.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/InlineCodeBlock.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/InlineCodeBlock.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/InlineCodeBlock.php
index a2fe9bb6d..b6894b86e 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/InlineCodeBlock.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/InlineCodeBlock.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/InsertStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/InsertStmt.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/InsertStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/InsertStmt.php
index a01582c10..ac2341747 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/InsertStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/InsertStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/IntList.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/IntList.php
similarity index 94%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/IntList.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/IntList.php
index ac310d0fb..a7a85e689 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/IntList.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/IntList.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/Integer.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/Integer.php
similarity index 93%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/Integer.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/Integer.php
index 8ce5e32ef..aa20066ac 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/Integer.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/Integer.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/IntoClause.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/IntoClause.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/IntoClause.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/IntoClause.php
index 81151d8c0..c91f105ed 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/IntoClause.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/IntoClause.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JoinExpr.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JoinExpr.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JoinExpr.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JoinExpr.php
index bf866325c..45de23d09 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JoinExpr.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JoinExpr.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JoinType.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JoinType.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JoinType.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JoinType.php
index 8931ebc4e..122e733f9 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JoinType.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JoinType.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.JoinType.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonAggConstructor.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonAggConstructor.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonAggConstructor.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonAggConstructor.php
index 0283dc06b..29c2806b7 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonAggConstructor.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonAggConstructor.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonArgument.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonArgument.php
similarity index 96%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonArgument.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonArgument.php
index 9df7a9633..b4d6f47eb 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonArgument.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonArgument.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonArrayAgg.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonArrayAgg.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonArrayAgg.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonArrayAgg.php
index f74306d36..61b5fab70 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonArrayAgg.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonArrayAgg.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonArrayConstructor.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonArrayConstructor.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonArrayConstructor.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonArrayConstructor.php
index 15bbdc0c0..d6883188b 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonArrayConstructor.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonArrayConstructor.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonArrayQueryConstructor.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonArrayQueryConstructor.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonArrayQueryConstructor.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonArrayQueryConstructor.php
index 5bc122678..1eea929a5 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonArrayQueryConstructor.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonArrayQueryConstructor.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonBehavior.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonBehavior.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonBehavior.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonBehavior.php
index 7bb4c2e8f..06a082780 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonBehavior.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonBehavior.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonBehaviorType.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonBehaviorType.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonBehaviorType.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonBehaviorType.php
index 4bb328e75..bb91865a3 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonBehaviorType.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonBehaviorType.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.JsonBehaviorType.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonConstructorExpr.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonConstructorExpr.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonConstructorExpr.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonConstructorExpr.php
index 7ffb1be78..2905a3a1d 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonConstructorExpr.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonConstructorExpr.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonConstructorType.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonConstructorType.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonConstructorType.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonConstructorType.php
index ace3af78e..d455ac1ec 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonConstructorType.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonConstructorType.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.JsonConstructorType.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonEncoding.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonEncoding.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonEncoding.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonEncoding.php
index 14eb0a6b7..b61dbb40c 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonEncoding.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonEncoding.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.JsonEncoding.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonExpr.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonExpr.php
similarity index 99%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonExpr.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonExpr.php
index 068eebd4b..85ae22ed4 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonExpr.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonExpr.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonExprOp.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonExprOp.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonExprOp.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonExprOp.php
index 12fc95330..527efd385 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonExprOp.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonExprOp.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.JsonExprOp.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonFormat.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonFormat.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonFormat.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonFormat.php
index 97b9b71c6..7595d7de7 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonFormat.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonFormat.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonFormatType.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonFormatType.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonFormatType.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonFormatType.php
index 885c5ad5a..b81964e2c 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonFormatType.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonFormatType.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.JsonFormatType.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonFuncExpr.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonFuncExpr.php
similarity index 99%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonFuncExpr.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonFuncExpr.php
index b5ec09a21..9acc5329b 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonFuncExpr.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonFuncExpr.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonIsPredicate.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonIsPredicate.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonIsPredicate.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonIsPredicate.php
index aca8f3fa0..824c3d93e 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonIsPredicate.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonIsPredicate.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonKeyValue.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonKeyValue.php
similarity index 96%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonKeyValue.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonKeyValue.php
index 834a609f8..a07f4f722 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonKeyValue.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonKeyValue.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonObjectAgg.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonObjectAgg.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonObjectAgg.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonObjectAgg.php
index e3713d992..ee264b24b 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonObjectAgg.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonObjectAgg.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonObjectConstructor.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonObjectConstructor.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonObjectConstructor.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonObjectConstructor.php
index 87844020d..3a0e51f8e 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonObjectConstructor.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonObjectConstructor.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonOutput.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonOutput.php
similarity index 96%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonOutput.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonOutput.php
index 9b6f04f80..c6476752d 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonOutput.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonOutput.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonParseExpr.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonParseExpr.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonParseExpr.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonParseExpr.php
index 7ee2269c1..5ba5de377 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonParseExpr.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonParseExpr.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonQuotes.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonQuotes.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonQuotes.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonQuotes.php
index 3822c86bd..647e8273d 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonQuotes.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonQuotes.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.JsonQuotes.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonReturning.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonReturning.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonReturning.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonReturning.php
index b5fe48760..718e078ab 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonReturning.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonReturning.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonScalarExpr.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonScalarExpr.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonScalarExpr.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonScalarExpr.php
index 16203b40e..b490a587f 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonScalarExpr.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonScalarExpr.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonSerializeExpr.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonSerializeExpr.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonSerializeExpr.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonSerializeExpr.php
index d9bfe31f2..44ca28574 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonSerializeExpr.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonSerializeExpr.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonTable.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonTable.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonTable.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonTable.php
index 4ed391caa..82b7714ac 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonTable.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonTable.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonTableColumn.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonTableColumn.php
similarity index 99%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonTableColumn.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonTableColumn.php
index e8eb133fe..f5bae4a85 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonTableColumn.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonTableColumn.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonTableColumnType.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonTableColumnType.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonTableColumnType.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonTableColumnType.php
index 70b40a637..72a627180 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonTableColumnType.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonTableColumnType.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.JsonTableColumnType.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonTablePath.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonTablePath.php
similarity index 93%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonTablePath.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonTablePath.php
index 501a820c7..3ba6e867e 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonTablePath.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonTablePath.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonTablePathScan.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonTablePathScan.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonTablePathScan.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonTablePathScan.php
index 7c0766ed5..776ceb88b 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonTablePathScan.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonTablePathScan.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonTablePathSpec.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonTablePathSpec.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonTablePathSpec.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonTablePathSpec.php
index 9cc5bb0c9..4cdfd82b7 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonTablePathSpec.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonTablePathSpec.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonTableSiblingJoin.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonTableSiblingJoin.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonTableSiblingJoin.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonTableSiblingJoin.php
index ab5627d15..9d11f6147 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonTableSiblingJoin.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonTableSiblingJoin.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonValueExpr.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonValueExpr.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonValueExpr.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonValueExpr.php
index 2c5c35f49..07065ea55 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonValueExpr.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonValueExpr.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonValueType.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonValueType.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonValueType.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonValueType.php
index 327b2086c..0ed11d1f2 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonValueType.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonValueType.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.JsonValueType.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonWrapper.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonWrapper.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonWrapper.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonWrapper.php
index fe7743db9..2384cdba1 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/JsonWrapper.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/JsonWrapper.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.JsonWrapper.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/KeywordKind.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/KeywordKind.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/KeywordKind.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/KeywordKind.php
index b6ef52826..19713d078 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/KeywordKind.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/KeywordKind.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.KeywordKind.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/LimitOption.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/LimitOption.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/LimitOption.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/LimitOption.php
index 311fabcae..5399ab32a 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/LimitOption.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/LimitOption.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.LimitOption.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ListenStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ListenStmt.php
similarity index 94%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ListenStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ListenStmt.php
index bac754939..1644a9b5a 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ListenStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ListenStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/LoadStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/LoadStmt.php
similarity index 93%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/LoadStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/LoadStmt.php
index 5a2990aab..48b138c45 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/LoadStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/LoadStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/LockClauseStrength.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/LockClauseStrength.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/LockClauseStrength.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/LockClauseStrength.php
index f001b3124..047df91e7 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/LockClauseStrength.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/LockClauseStrength.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.LockClauseStrength.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/LockStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/LockStmt.php
similarity index 96%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/LockStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/LockStmt.php
index be0ef02a1..ab2bf3cab 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/LockStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/LockStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/LockTupleMode.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/LockTupleMode.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/LockTupleMode.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/LockTupleMode.php
index 63b50a699..a55cada9f 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/LockTupleMode.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/LockTupleMode.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.LockTupleMode.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/LockWaitPolicy.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/LockWaitPolicy.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/LockWaitPolicy.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/LockWaitPolicy.php
index f528d36be..a307ecff5 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/LockWaitPolicy.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/LockWaitPolicy.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.LockWaitPolicy.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/LockingClause.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/LockingClause.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/LockingClause.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/LockingClause.php
index 52b7367a6..77d67b217 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/LockingClause.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/LockingClause.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/MergeAction.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/MergeAction.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/MergeAction.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/MergeAction.php
index ee9e2a70c..b9dcf3bd8 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/MergeAction.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/MergeAction.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/MergeMatchKind.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/MergeMatchKind.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/MergeMatchKind.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/MergeMatchKind.php
index f5c3de672..42bdb5c91 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/MergeMatchKind.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/MergeMatchKind.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.MergeMatchKind.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/MergeStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/MergeStmt.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/MergeStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/MergeStmt.php
index 7dfa1a3dc..15e2b4ce4 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/MergeStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/MergeStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/MergeSupportFunc.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/MergeSupportFunc.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/MergeSupportFunc.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/MergeSupportFunc.php
index c6632ecca..6b92a68e1 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/MergeSupportFunc.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/MergeSupportFunc.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/MergeWhenClause.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/MergeWhenClause.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/MergeWhenClause.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/MergeWhenClause.php
index 97dfda39c..fa6a949c4 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/MergeWhenClause.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/MergeWhenClause.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/MinMaxExpr.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/MinMaxExpr.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/MinMaxExpr.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/MinMaxExpr.php
index 85bb77791..118235f52 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/MinMaxExpr.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/MinMaxExpr.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/MinMaxOp.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/MinMaxOp.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/MinMaxOp.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/MinMaxOp.php
index 37828fcf0..2b36a9f7e 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/MinMaxOp.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/MinMaxOp.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.MinMaxOp.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/MultiAssignRef.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/MultiAssignRef.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/MultiAssignRef.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/MultiAssignRef.php
index 8cd81d661..6c8436e25 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/MultiAssignRef.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/MultiAssignRef.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/NamedArgExpr.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/NamedArgExpr.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/NamedArgExpr.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/NamedArgExpr.php
index e7c86395d..5e917dfba 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/NamedArgExpr.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/NamedArgExpr.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/NextValueExpr.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/NextValueExpr.php
similarity index 96%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/NextValueExpr.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/NextValueExpr.php
index d8b30cc08..35716fc4f 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/NextValueExpr.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/NextValueExpr.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/Node.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/Node.php
similarity index 99%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/Node.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/Node.php
index b538cd106..25ef32d81 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/Node.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/Node.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/NotifyStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/NotifyStmt.php
similarity index 96%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/NotifyStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/NotifyStmt.php
index 0d3efcbcf..f7e38cf35 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/NotifyStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/NotifyStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/NullIfExpr.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/NullIfExpr.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/NullIfExpr.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/NullIfExpr.php
index 05b0f9dcb..c452b7bea 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/NullIfExpr.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/NullIfExpr.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/NullTest.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/NullTest.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/NullTest.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/NullTest.php
index 07686612a..7cefdd68d 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/NullTest.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/NullTest.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/NullTestType.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/NullTestType.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/NullTestType.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/NullTestType.php
index cff1c0f14..a3b6341ee 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/NullTestType.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/NullTestType.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.NullTestType.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ObjectType.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ObjectType.php
similarity index 99%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ObjectType.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ObjectType.php
index 5f641bcb3..0e67b592c 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ObjectType.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ObjectType.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.ObjectType.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ObjectWithArgs.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ObjectWithArgs.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ObjectWithArgs.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ObjectWithArgs.php
index 16c141820..f288ee13a 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ObjectWithArgs.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ObjectWithArgs.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/OidList.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/OidList.php
similarity index 94%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/OidList.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/OidList.php
index b4fa888f3..6ba17b00b 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/OidList.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/OidList.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/OnCommitAction.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/OnCommitAction.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/OnCommitAction.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/OnCommitAction.php
index be6093b5b..26ef5551d 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/OnCommitAction.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/OnCommitAction.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.OnCommitAction.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/OnConflictAction.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/OnConflictAction.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/OnConflictAction.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/OnConflictAction.php
index 0c4e04f26..5524d6971 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/OnConflictAction.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/OnConflictAction.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.OnConflictAction.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/OnConflictClause.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/OnConflictClause.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/OnConflictClause.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/OnConflictClause.php
index 478ace97e..d98f26071 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/OnConflictClause.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/OnConflictClause.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/OnConflictExpr.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/OnConflictExpr.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/OnConflictExpr.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/OnConflictExpr.php
index 6eac7cc48..3084efddc 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/OnConflictExpr.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/OnConflictExpr.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/OpExpr.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/OpExpr.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/OpExpr.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/OpExpr.php
index 2ac04c5b7..3080d861f 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/OpExpr.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/OpExpr.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/OverridingKind.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/OverridingKind.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/OverridingKind.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/OverridingKind.php
index 30b14bfbd..a8aa87bcc 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/OverridingKind.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/OverridingKind.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.OverridingKind.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PBFloat.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PBFloat.php
similarity index 93%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PBFloat.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PBFloat.php
index d4209594f..c795832e8 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PBFloat.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PBFloat.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PBList.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PBList.php
similarity index 94%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PBList.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PBList.php
index f0073658b..e6f36ac03 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PBList.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PBList.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PBString.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PBString.php
similarity index 93%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PBString.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PBString.php
index 7acf9291f..222701891 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PBString.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PBString.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PBVar.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PBVar.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PBVar.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PBVar.php
index a2ac06eb4..242a714c1 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PBVar.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PBVar.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PLAssignStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PLAssignStmt.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PLAssignStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PLAssignStmt.php
index 0d01d584a..2e82d9466 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PLAssignStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PLAssignStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/Param.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/Param.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/Param.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/Param.php
index 35d712d31..52f02bc3c 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/Param.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/Param.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ParamKind.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ParamKind.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ParamKind.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ParamKind.php
index 98299fc83..d89139578 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ParamKind.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ParamKind.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.ParamKind.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ParamRef.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ParamRef.php
similarity index 95%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ParamRef.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ParamRef.php
index b3a5750e3..256a9befd 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ParamRef.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ParamRef.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ParseResult.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ParseResult.php
similarity index 95%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ParseResult.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ParseResult.php
index 55e286380..764b09378 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ParseResult.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ParseResult.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PartitionBoundSpec.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PartitionBoundSpec.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PartitionBoundSpec.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PartitionBoundSpec.php
index 095aac35d..74ffd5da2 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PartitionBoundSpec.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PartitionBoundSpec.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PartitionCmd.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PartitionCmd.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PartitionCmd.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PartitionCmd.php
index 0767064ff..b639fc2cb 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PartitionCmd.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PartitionCmd.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PartitionElem.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PartitionElem.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PartitionElem.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PartitionElem.php
index df7b2be09..d64c22043 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PartitionElem.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PartitionElem.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PartitionRangeDatum.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PartitionRangeDatum.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PartitionRangeDatum.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PartitionRangeDatum.php
index 50d50e255..32946e264 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PartitionRangeDatum.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PartitionRangeDatum.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PartitionRangeDatumKind.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PartitionRangeDatumKind.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PartitionRangeDatumKind.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PartitionRangeDatumKind.php
index 9f1b0a7e2..91faf8d31 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PartitionRangeDatumKind.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PartitionRangeDatumKind.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.PartitionRangeDatumKind.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PartitionSpec.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PartitionSpec.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PartitionSpec.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PartitionSpec.php
index 4fb5bd804..5ec9d2fe4 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PartitionSpec.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PartitionSpec.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PartitionStrategy.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PartitionStrategy.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PartitionStrategy.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PartitionStrategy.php
index d3dff454e..a959909b8 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PartitionStrategy.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PartitionStrategy.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.PartitionStrategy.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PrepareStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PrepareStmt.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PrepareStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PrepareStmt.php
index 77b410329..ba303e294 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PrepareStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PrepareStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PublicationObjSpec.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PublicationObjSpec.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PublicationObjSpec.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PublicationObjSpec.php
index 9120d956b..5e9b8055c 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PublicationObjSpec.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PublicationObjSpec.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PublicationObjSpecType.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PublicationObjSpecType.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PublicationObjSpecType.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PublicationObjSpecType.php
index 2c0f72780..38814f971 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PublicationObjSpecType.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PublicationObjSpecType.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.PublicationObjSpecType.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PublicationTable.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PublicationTable.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PublicationTable.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PublicationTable.php
index 9bc3cdde0..2d67559e7 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/PublicationTable.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/PublicationTable.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/Query.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/Query.php
similarity index 99%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/Query.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/Query.php
index a7ec62ea9..2d64b323e 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/Query.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/Query.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/QuerySource.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/QuerySource.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/QuerySource.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/QuerySource.php
index d5ba48afa..58b8b62b3 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/QuerySource.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/QuerySource.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.QuerySource.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RTEKind.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RTEKind.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RTEKind.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RTEKind.php
index a33935a13..5d05b2bf9 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RTEKind.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RTEKind.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.RTEKind.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RTEPermissionInfo.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RTEPermissionInfo.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RTEPermissionInfo.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RTEPermissionInfo.php
index a89679fc6..067e4aa38 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RTEPermissionInfo.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RTEPermissionInfo.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RangeFunction.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RangeFunction.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RangeFunction.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RangeFunction.php
index f5d37c877..3a498d5f3 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RangeFunction.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RangeFunction.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RangeSubselect.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RangeSubselect.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RangeSubselect.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RangeSubselect.php
index c86851094..e0c96bddc 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RangeSubselect.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RangeSubselect.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RangeTableFunc.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RangeTableFunc.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RangeTableFunc.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RangeTableFunc.php
index b6b32dd8b..1d4fbf917 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RangeTableFunc.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RangeTableFunc.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RangeTableFuncCol.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RangeTableFuncCol.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RangeTableFuncCol.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RangeTableFuncCol.php
index 8c8a71dcc..3e7f68bd2 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RangeTableFuncCol.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RangeTableFuncCol.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RangeTableSample.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RangeTableSample.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RangeTableSample.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RangeTableSample.php
index e30ea0d21..b5f66807e 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RangeTableSample.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RangeTableSample.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RangeTblEntry.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RangeTblEntry.php
similarity index 99%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RangeTblEntry.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RangeTblEntry.php
index c5f691632..e41c4d486 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RangeTblEntry.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RangeTblEntry.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RangeTblFunction.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RangeTblFunction.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RangeTblFunction.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RangeTblFunction.php
index 440b2937f..819404b37 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RangeTblFunction.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RangeTblFunction.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RangeTblRef.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RangeTblRef.php
similarity index 93%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RangeTblRef.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RangeTblRef.php
index 797b04024..792ae939b 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RangeTblRef.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RangeTblRef.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RangeVar.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RangeVar.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RangeVar.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RangeVar.php
index b99f87ba6..d6d8ba27b 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RangeVar.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RangeVar.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RawStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RawStmt.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RawStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RawStmt.php
index 6878f7a72..4b0cea391 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RawStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RawStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ReassignOwnedStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ReassignOwnedStmt.php
similarity index 96%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ReassignOwnedStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ReassignOwnedStmt.php
index 1f31e982a..5e478f2a3 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ReassignOwnedStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ReassignOwnedStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RefreshMatViewStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RefreshMatViewStmt.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RefreshMatViewStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RefreshMatViewStmt.php
index 829fe183f..0db4fa296 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RefreshMatViewStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RefreshMatViewStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ReindexObjectType.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ReindexObjectType.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ReindexObjectType.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ReindexObjectType.php
index 741708af1..90c9af549 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ReindexObjectType.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ReindexObjectType.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.ReindexObjectType.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ReindexStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ReindexStmt.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ReindexStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ReindexStmt.php
index 45cda60dd..a9c9067b6 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ReindexStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ReindexStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RelabelType.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RelabelType.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RelabelType.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RelabelType.php
index dee069ddf..f36c3d3cb 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RelabelType.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RelabelType.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RenameStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RenameStmt.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RenameStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RenameStmt.php
index f937e73ee..40fddd0bd 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RenameStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RenameStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ReplicaIdentityStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ReplicaIdentityStmt.php
similarity index 95%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ReplicaIdentityStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ReplicaIdentityStmt.php
index 78002ee17..4c48acf66 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ReplicaIdentityStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ReplicaIdentityStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ResTarget.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ResTarget.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ResTarget.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ResTarget.php
index c653b49d2..11b1e39ae 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ResTarget.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ResTarget.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ReturnStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ReturnStmt.php
similarity index 94%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ReturnStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ReturnStmt.php
index 0e26da22e..c82e8e6b1 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ReturnStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ReturnStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RoleSpec.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RoleSpec.php
similarity index 96%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RoleSpec.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RoleSpec.php
index 345a73c8c..adffffd7d 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RoleSpec.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RoleSpec.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RoleSpecType.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RoleSpecType.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RoleSpecType.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RoleSpecType.php
index e5c2cdd9f..48798f5f5 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RoleSpecType.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RoleSpecType.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.RoleSpecType.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RoleStmtType.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RoleStmtType.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RoleStmtType.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RoleStmtType.php
index ba975bc6f..d7a3c8a79 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RoleStmtType.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RoleStmtType.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.RoleStmtType.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RowCompareExpr.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RowCompareExpr.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RowCompareExpr.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RowCompareExpr.php
index bfe3618d6..623ede837 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RowCompareExpr.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RowCompareExpr.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RowCompareType.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RowCompareType.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RowCompareType.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RowCompareType.php
index e9d45f7be..2539333c8 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RowCompareType.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RowCompareType.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.RowCompareType.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RowExpr.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RowExpr.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RowExpr.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RowExpr.php
index 71a20c720..bfdb74c2c 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RowExpr.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RowExpr.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RowMarkClause.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RowMarkClause.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RowMarkClause.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RowMarkClause.php
index 488899e1a..f59e295dd 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RowMarkClause.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RowMarkClause.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RuleStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RuleStmt.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RuleStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RuleStmt.php
index 814f21bed..b3a984672 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/RuleStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/RuleStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SQLValueFunction.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SQLValueFunction.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SQLValueFunction.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SQLValueFunction.php
index d1171ad6a..d31325acb 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SQLValueFunction.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SQLValueFunction.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SQLValueFunctionOp.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SQLValueFunctionOp.php
similarity index 99%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SQLValueFunctionOp.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SQLValueFunctionOp.php
index 1b63d46a6..a8edf31f0 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SQLValueFunctionOp.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SQLValueFunctionOp.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.SQLValueFunctionOp.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ScalarArrayOpExpr.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ScalarArrayOpExpr.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ScalarArrayOpExpr.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ScalarArrayOpExpr.php
index 61274f46a..96d517415 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ScalarArrayOpExpr.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ScalarArrayOpExpr.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ScanResult.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ScanResult.php
similarity index 95%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ScanResult.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ScanResult.php
index 0fe3932b0..d5acf4468 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ScanResult.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ScanResult.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ScanToken.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ScanToken.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ScanToken.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ScanToken.php
index c09b43641..bfcecd631 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ScanToken.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ScanToken.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SecLabelStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SecLabelStmt.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SecLabelStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SecLabelStmt.php
index 70ebb08ae..d92725b1e 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SecLabelStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SecLabelStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SelectStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SelectStmt.php
similarity index 99%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SelectStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SelectStmt.php
index 0d543c649..d981bccf7 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SelectStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SelectStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SetOpCmd.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SetOpCmd.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SetOpCmd.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SetOpCmd.php
index f70d49f0d..77d44ce91 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SetOpCmd.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SetOpCmd.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.SetOpCmd.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SetOpStrategy.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SetOpStrategy.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SetOpStrategy.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SetOpStrategy.php
index d27009674..5905ec46a 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SetOpStrategy.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SetOpStrategy.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.SetOpStrategy.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SetOperation.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SetOperation.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SetOperation.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SetOperation.php
index fb6b4ca9a..ae83f3ec5 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SetOperation.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SetOperation.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.SetOperation.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SetOperationStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SetOperationStmt.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SetOperationStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SetOperationStmt.php
index 75e246bb3..4583cb83d 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SetOperationStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SetOperationStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SetQuantifier.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SetQuantifier.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SetQuantifier.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SetQuantifier.php
index 687b42be3..595fc2663 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SetQuantifier.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SetQuantifier.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.SetQuantifier.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SetToDefault.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SetToDefault.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SetToDefault.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SetToDefault.php
index 45c0aab45..3815e5d93 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SetToDefault.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SetToDefault.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SinglePartitionSpec.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SinglePartitionSpec.php
similarity index 87%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SinglePartitionSpec.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SinglePartitionSpec.php
index ef472d0b9..e025c1c75 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SinglePartitionSpec.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SinglePartitionSpec.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\Message;
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SortBy.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SortBy.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SortBy.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SortBy.php
index 67e5240af..8a39cf96f 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SortBy.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SortBy.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SortByDir.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SortByDir.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SortByDir.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SortByDir.php
index 051f5f401..4aad9b8f9 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SortByDir.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SortByDir.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.SortByDir.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SortByNulls.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SortByNulls.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SortByNulls.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SortByNulls.php
index f1da9c8e8..0e7465598 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SortByNulls.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SortByNulls.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.SortByNulls.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SortGroupClause.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SortGroupClause.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SortGroupClause.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SortGroupClause.php
index 87ba95c41..0d5c5b87b 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SortGroupClause.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SortGroupClause.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/StatsElem.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/StatsElem.php
similarity index 96%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/StatsElem.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/StatsElem.php
index 0aa8cee58..572c24c92 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/StatsElem.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/StatsElem.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SubLink.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SubLink.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SubLink.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SubLink.php
index 6949ebb5e..f94dcf23d 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SubLink.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SubLink.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SubLinkType.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SubLinkType.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SubLinkType.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SubLinkType.php
index 2cf0c044d..9cc1bf584 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SubLinkType.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SubLinkType.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.SubLinkType.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SubPlan.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SubPlan.php
similarity index 99%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SubPlan.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SubPlan.php
index 275e05d20..847d90944 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SubPlan.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SubPlan.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SubscriptingRef.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SubscriptingRef.php
similarity index 99%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SubscriptingRef.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SubscriptingRef.php
index 0c857292b..315b55d85 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/SubscriptingRef.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/SubscriptingRef.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/TableFunc.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/TableFunc.php
similarity index 99%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/TableFunc.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/TableFunc.php
index f98e5e3d4..a874d041c 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/TableFunc.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/TableFunc.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/TableFuncType.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/TableFuncType.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/TableFuncType.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/TableFuncType.php
index 0733c2d9e..1b7ba59bc 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/TableFuncType.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/TableFuncType.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.TableFuncType.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/TableLikeClause.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/TableLikeClause.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/TableLikeClause.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/TableLikeClause.php
index fff53db90..2af1e144d 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/TableLikeClause.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/TableLikeClause.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/TableLikeOption.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/TableLikeOption.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/TableLikeOption.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/TableLikeOption.php
index 635b80522..dcb49c5c0 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/TableLikeOption.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/TableLikeOption.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.TableLikeOption.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/TableSampleClause.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/TableSampleClause.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/TableSampleClause.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/TableSampleClause.php
index 2a76726e7..097626481 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/TableSampleClause.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/TableSampleClause.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/TargetEntry.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/TargetEntry.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/TargetEntry.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/TargetEntry.php
index 370bca31c..fef54ab29 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/TargetEntry.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/TargetEntry.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/Token.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/Token.php
similarity index 99%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/Token.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/Token.php
index d489d7973..a61d68b15 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/Token.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/Token.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.Token.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/TransactionStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/TransactionStmt.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/TransactionStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/TransactionStmt.php
index ef3b3dce8..b17b78628 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/TransactionStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/TransactionStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/TransactionStmtKind.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/TransactionStmtKind.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/TransactionStmtKind.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/TransactionStmtKind.php
index d62e7ec2f..a72e42d15 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/TransactionStmtKind.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/TransactionStmtKind.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.TransactionStmtKind.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/TriggerTransition.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/TriggerTransition.php
similarity index 96%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/TriggerTransition.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/TriggerTransition.php
index 362e44e7e..b23791e71 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/TriggerTransition.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/TriggerTransition.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/TruncateStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/TruncateStmt.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/TruncateStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/TruncateStmt.php
index 180caf534..9ac3e7a1e 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/TruncateStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/TruncateStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/TypeCast.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/TypeCast.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/TypeCast.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/TypeCast.php
index 126bde28c..24584bac1 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/TypeCast.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/TypeCast.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/TypeName.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/TypeName.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/TypeName.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/TypeName.php
index 1d5660aff..75a52a385 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/TypeName.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/TypeName.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/UnlistenStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/UnlistenStmt.php
similarity index 94%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/UnlistenStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/UnlistenStmt.php
index b043cdd9f..ab838bad2 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/UnlistenStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/UnlistenStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/UpdateStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/UpdateStmt.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/UpdateStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/UpdateStmt.php
index 83d3d6de5..d5ae7b4ea 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/UpdateStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/UpdateStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/VacuumRelation.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/VacuumRelation.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/VacuumRelation.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/VacuumRelation.php
index 2656273b9..9c7602abb 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/VacuumRelation.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/VacuumRelation.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/VacuumStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/VacuumStmt.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/VacuumStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/VacuumStmt.php
index 6956c0b63..380c35270 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/VacuumStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/VacuumStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/VariableSetKind.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/VariableSetKind.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/VariableSetKind.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/VariableSetKind.php
index 584e1aeaa..27af6b561 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/VariableSetKind.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/VariableSetKind.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.VariableSetKind.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/VariableSetStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/VariableSetStmt.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/VariableSetStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/VariableSetStmt.php
index fb94918b3..d7643c015 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/VariableSetStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/VariableSetStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/VariableShowStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/VariableShowStmt.php
similarity index 93%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/VariableShowStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/VariableShowStmt.php
index 73470a42c..fbb74e29f 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/VariableShowStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/VariableShowStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ViewCheckOption.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ViewCheckOption.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ViewCheckOption.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ViewCheckOption.php
index bb588cee1..03e0c6c9d 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ViewCheckOption.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ViewCheckOption.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.ViewCheckOption.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ViewStmt.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ViewStmt.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ViewStmt.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ViewStmt.php
index cd6bdfba7..4b2cc26c7 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/ViewStmt.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/ViewStmt.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/WCOKind.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/WCOKind.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/WCOKind.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/WCOKind.php
index 5247663e2..ba8a4d60a 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/WCOKind.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/WCOKind.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.WCOKind.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/WindowClause.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/WindowClause.php
similarity index 99%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/WindowClause.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/WindowClause.php
index 1271a2cfe..627d5f0b5 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/WindowClause.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/WindowClause.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/WindowDef.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/WindowDef.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/WindowDef.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/WindowDef.php
index c567c79e9..4e7aefd72 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/WindowDef.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/WindowDef.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/WindowFunc.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/WindowFunc.php
similarity index 99%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/WindowFunc.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/WindowFunc.php
index 4e06295f7..f2824624f 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/WindowFunc.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/WindowFunc.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/WindowFuncRunCondition.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/WindowFuncRunCondition.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/WindowFuncRunCondition.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/WindowFuncRunCondition.php
index 08a067331..fed1a949b 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/WindowFuncRunCondition.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/WindowFuncRunCondition.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/WithCheckOption.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/WithCheckOption.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/WithCheckOption.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/WithCheckOption.php
index aa2ac88ac..51575cfd6 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/WithCheckOption.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/WithCheckOption.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/WithClause.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/WithClause.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/WithClause.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/WithClause.php
index c29399d8d..f8fd27109 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/WithClause.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/WithClause.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/XmlExpr.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/XmlExpr.php
similarity index 99%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/XmlExpr.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/XmlExpr.php
index f2639fef6..ab3bac802 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/XmlExpr.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/XmlExpr.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBType, GPBUtil, Message};
use Google\Protobuf\RepeatedField;
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/XmlExprOp.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/XmlExprOp.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/XmlExprOp.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/XmlExprOp.php
index 871e6ba40..d09d47bd0 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/XmlExprOp.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/XmlExprOp.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.XmlExprOp.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/XmlOptionType.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/XmlOptionType.php
similarity index 97%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/XmlOptionType.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/XmlOptionType.php
index e5682673a..9f906435c 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/XmlOptionType.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/XmlOptionType.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
/**
* Protobuf type pg_query.XmlOptionType.
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/XmlSerialize.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/XmlSerialize.php
similarity index 98%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/XmlSerialize.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/XmlSerialize.php
index 29dc60a8d..7c5fd591b 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/AST/XmlSerialize.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/AST/XmlSerialize.php
@@ -5,9 +5,9 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\AST;
+namespace Flow\PostgreSql\Protobuf\AST;
-use Flow\PgQuery\Protobuf\Metadata\PgQuery;
+use Flow\PostgreSql\Protobuf\Metadata\PgQuery;
use Google\Protobuf\Internal\{GPBUtil, Message};
/**
diff --git a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/Metadata/PgQuery.php b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/Metadata/PgQuery.php
similarity index 99%
rename from src/lib/pg-query/src/Flow/PgQuery/Protobuf/Metadata/PgQuery.php
rename to src/lib/postgresql/src/Flow/PostgreSql/Protobuf/Metadata/PgQuery.php
index a785d4283..8d11ca589 100644
--- a/src/lib/pg-query/src/Flow/PgQuery/Protobuf/Metadata/PgQuery.php
+++ b/src/lib/postgresql/src/Flow/PostgreSql/Protobuf/Metadata/PgQuery.php
@@ -5,7 +5,7 @@
// NO CHECKED-IN PROTOBUF GENCODE
// source: pg_query.proto
-namespace Flow\PgQuery\Protobuf\Metadata;
+namespace Flow\PostgreSql\Protobuf\Metadata;
use Google\Protobuf\Internal\DescriptorPool;
@@ -21,7 +21,7 @@ public static function initOnce() : void
return;
}
$pool->internalAddGeneratedFile(
- "\x0A\x8B\x85\x06\x0A\x0Epg_query.proto\x12\x08pg_query\"@\x0A\x0BParseResult\x12\x0F\x0A\x07version\x18\x01 \x01(\x05\x12 \x0A\x05stmts\x18\x02 \x03(\x0B2\x11.pg_query.RawStmt\"B\x0A\x0AScanResult\x12\x0F\x0A\x07version\x18\x01 \x01(\x05\x12#\x0A\x06tokens\x18\x02 \x03(\x0B2\x13.pg_query.ScanToken\"\xD5\x8E\x01\x0A\x04Node\x12'\x0A\x05alias\x18\x01 \x01(\x0B2\x0F.pg_query.AliasH\x00R\x05Alias\x121\x0A\x09range_var\x18\x02 \x01(\x0B2\x12.pg_query.RangeVarH\x00R\x08RangeVar\x124\x0A\x0Atable_func\x18\x03 \x01(\x0B2\x13.pg_query.TableFuncH\x00R\x09TableFunc\x127\x0A\x0Binto_clause\x18\x04 \x01(\x0B2\x14.pg_query.IntoClauseH\x00R\x0AIntoClause\x12!\x0A\x03var\x18\x05 \x01(\x0B2\x0D.pg_query.VarH\x00R\x03Var\x12'\x0A\x05param\x18\x06 \x01(\x0B2\x0F.pg_query.ParamH\x00R\x05Param\x12*\x0A\x06aggref\x18\x07 \x01(\x0B2\x10.pg_query.AggrefH\x00R\x06Aggref\x12=\x0A\x0Dgrouping_func\x18\x08 \x01(\x0B2\x16.pg_query.GroupingFuncH\x00R\x0CGroupingFunc\x127\x0A\x0Bwindow_func\x18\x09 \x01(\x0B2\x14.pg_query.WindowFuncH\x00R\x0AWindowFunc\x12]\x0A\x19window_func_run_condition\x18\x0A \x01(\x0B2 .pg_query.WindowFuncRunConditionH\x00R\x16WindowFuncRunCondition\x12J\x0A\x12merge_support_func\x18\x0B \x01(\x0B2\x1A.pg_query.MergeSupportFuncH\x00R\x10MergeSupportFunc\x12F\x0A\x10subscripting_ref\x18\x0C \x01(\x0B2\x19.pg_query.SubscriptingRefH\x00R\x0FSubscriptingRef\x121\x0A\x09func_expr\x18\x0D \x01(\x0B2\x12.pg_query.FuncExprH\x00R\x08FuncExpr\x12>\x0A\x0Enamed_arg_expr\x18\x0E \x01(\x0B2\x16.pg_query.NamedArgExprH\x00R\x0CNamedArgExpr\x12+\x0A\x07op_expr\x18\x0F \x01(\x0B2\x10.pg_query.OpExprH\x00R\x06OpExpr\x12=\x0A\x0Ddistinct_expr\x18\x10 \x01(\x0B2\x16.pg_query.DistinctExprH\x00R\x0CDistinctExpr\x128\x0A\x0Cnull_if_expr\x18\x11 \x01(\x0B2\x14.pg_query.NullIfExprH\x00R\x0ANullIfExpr\x12N\x0A\x14scalar_array_op_expr\x18\x12 \x01(\x0B2\x1B.pg_query.ScalarArrayOpExprH\x00R\x11ScalarArrayOpExpr\x121\x0A\x09bool_expr\x18\x13 \x01(\x0B2\x12.pg_query.BoolExprH\x00R\x08BoolExpr\x12.\x0A\x08sub_link\x18\x14 \x01(\x0B2\x11.pg_query.SubLinkH\x00R\x07SubLink\x12.\x0A\x08sub_plan\x18\x15 \x01(\x0B2\x11.pg_query.SubPlanH\x00R\x07SubPlan\x12P\x0A\x14alternative_sub_plan\x18\x16 \x01(\x0B2\x1C.pg_query.AlternativeSubPlanH\x00R\x12AlternativeSubPlan\x12:\x0A\x0Cfield_select\x18\x17 \x01(\x0B2\x15.pg_query.FieldSelectH\x00R\x0BFieldSelect\x127\x0A\x0Bfield_store\x18\x18 \x01(\x0B2\x14.pg_query.FieldStoreH\x00R\x0AFieldStore\x12:\x0A\x0Crelabel_type\x18\x19 \x01(\x0B2\x15.pg_query.RelabelTypeH\x00R\x0BRelabelType\x12;\x0A\x0Dcoerce_via_io\x18\x1A \x01(\x0B2\x15.pg_query.CoerceViaIOH\x00R\x0BCoerceViaIO\x12G\x0A\x11array_coerce_expr\x18\x1B \x01(\x0B2\x19.pg_query.ArrayCoerceExprH\x00R\x0FArrayCoerceExpr\x12P\x0A\x14convert_rowtype_expr\x18\x1C \x01(\x0B2\x1C.pg_query.ConvertRowtypeExprH\x00R\x12ConvertRowtypeExpr\x12:\x0A\x0Ccollate_expr\x18\x1D \x01(\x0B2\x15.pg_query.CollateExprH\x00R\x0BCollateExpr\x121\x0A\x09case_expr\x18\x1E \x01(\x0B2\x12.pg_query.CaseExprH\x00R\x08CaseExpr\x121\x0A\x09case_when\x18\x1F \x01(\x0B2\x12.pg_query.CaseWhenH\x00R\x08CaseWhen\x12>\x0A\x0Ecase_test_expr\x18 \x01(\x0B2\x16.pg_query.CaseTestExprH\x00R\x0CCaseTestExpr\x124\x0A\x0Aarray_expr\x18! \x01(\x0B2\x13.pg_query.ArrayExprH\x00R\x09ArrayExpr\x12.\x0A\x08row_expr\x18\" \x01(\x0B2\x11.pg_query.RowExprH\x00R\x07RowExpr\x12D\x0A\x10row_compare_expr\x18# \x01(\x0B2\x18.pg_query.RowCompareExprH\x00R\x0ERowCompareExpr\x12=\x0A\x0Dcoalesce_expr\x18\$ \x01(\x0B2\x16.pg_query.CoalesceExprH\x00R\x0CCoalesceExpr\x128\x0A\x0Cmin_max_expr\x18% \x01(\x0B2\x14.pg_query.MinMaxExprH\x00R\x0AMinMaxExpr\x12I\x0A\x11sqlvalue_function\x18& \x01(\x0B2\x1A.pg_query.SQLValueFunctionH\x00R\x10SQLValueFunction\x12.\x0A\x08xml_expr\x18' \x01(\x0B2\x11.pg_query.XmlExprH\x00R\x07XmlExpr\x127\x0A\x0Bjson_format\x18( \x01(\x0B2\x14.pg_query.JsonFormatH\x00R\x0AJsonFormat\x12@\x0A\x0Ejson_returning\x18) \x01(\x0B2\x17.pg_query.JsonReturningH\x00R\x0DJsonReturning\x12A\x0A\x0Fjson_value_expr\x18* \x01(\x0B2\x17.pg_query.JsonValueExprH\x00R\x0DJsonValueExpr\x12S\x0A\x15json_constructor_expr\x18+ \x01(\x0B2\x1D.pg_query.JsonConstructorExprH\x00R\x13JsonConstructorExpr\x12G\x0A\x11json_is_predicate\x18, \x01(\x0B2\x19.pg_query.JsonIsPredicateH\x00R\x0FJsonIsPredicate\x12=\x0A\x0Djson_behavior\x18- \x01(\x0B2\x16.pg_query.JsonBehaviorH\x00R\x0CJsonBehavior\x121\x0A\x09json_expr\x18. \x01(\x0B2\x12.pg_query.JsonExprH\x00R\x08JsonExpr\x12A\x0A\x0Fjson_table_path\x18/ \x01(\x0B2\x17.pg_query.JsonTablePathH\x00R\x0DJsonTablePath\x12N\x0A\x14json_table_path_scan\x180 \x01(\x0B2\x1B.pg_query.JsonTablePathScanH\x00R\x11JsonTablePathScan\x12W\x0A\x17json_table_sibling_join\x181 \x01(\x0B2\x1E.pg_query.JsonTableSiblingJoinH\x00R\x14JsonTableSiblingJoin\x121\x0A\x09null_test\x182 \x01(\x0B2\x12.pg_query.NullTestH\x00R\x08NullTest\x12:\x0A\x0Cboolean_test\x183 \x01(\x0B2\x15.pg_query.BooleanTestH\x00R\x0BBooleanTest\x12:\x0A\x0Cmerge_action\x184 \x01(\x0B2\x15.pg_query.MergeActionH\x00R\x0BMergeAction\x12D\x0A\x10coerce_to_domain\x185 \x01(\x0B2\x18.pg_query.CoerceToDomainH\x00R\x0ECoerceToDomain\x12T\x0A\x16coerce_to_domain_value\x186 \x01(\x0B2\x1D.pg_query.CoerceToDomainValueH\x00R\x13CoerceToDomainValue\x12>\x0A\x0Eset_to_default\x187 \x01(\x0B2\x16.pg_query.SetToDefaultH\x00R\x0CSetToDefault\x12A\x0A\x0Fcurrent_of_expr\x188 \x01(\x0B2\x17.pg_query.CurrentOfExprH\x00R\x0DCurrentOfExpr\x12A\x0A\x0Fnext_value_expr\x189 \x01(\x0B2\x17.pg_query.NextValueExprH\x00R\x0DNextValueExpr\x12@\x0A\x0Einference_elem\x18: \x01(\x0B2\x17.pg_query.InferenceElemH\x00R\x0DInferenceElem\x12:\x0A\x0Ctarget_entry\x18; \x01(\x0B2\x15.pg_query.TargetEntryH\x00R\x0BTargetEntry\x12;\x0A\x0Drange_tbl_ref\x18< \x01(\x0B2\x15.pg_query.RangeTblRefH\x00R\x0BRangeTblRef\x121\x0A\x09join_expr\x18= \x01(\x0B2\x12.pg_query.JoinExprH\x00R\x08JoinExpr\x121\x0A\x09from_expr\x18> \x01(\x0B2\x12.pg_query.FromExprH\x00R\x08FromExpr\x12D\x0A\x10on_conflict_expr\x18? \x01(\x0B2\x18.pg_query.OnConflictExprH\x00R\x0EOnConflictExpr\x12'\x0A\x05query\x18@ \x01(\x0B2\x0F.pg_query.QueryH\x00R\x05Query\x121\x0A\x09type_name\x18A \x01(\x0B2\x12.pg_query.TypeNameH\x00R\x08TypeName\x124\x0A\x0Acolumn_ref\x18B \x01(\x0B2\x13.pg_query.ColumnRefH\x00R\x09ColumnRef\x121\x0A\x09param_ref\x18C \x01(\x0B2\x12.pg_query.ParamRefH\x00R\x08ParamRef\x12*\x0A\x06a_expr\x18D \x01(\x0B2\x10.pg_query.A_ExprH\x00R\x06A_Expr\x121\x0A\x09type_cast\x18E \x01(\x0B2\x12.pg_query.TypeCastH\x00R\x08TypeCast\x12@\x0A\x0Ecollate_clause\x18F \x01(\x0B2\x17.pg_query.CollateClauseH\x00R\x0DCollateClause\x121\x0A\x09role_spec\x18G \x01(\x0B2\x12.pg_query.RoleSpecH\x00R\x08RoleSpec\x121\x0A\x09func_call\x18H \x01(\x0B2\x12.pg_query.FuncCallH\x00R\x08FuncCall\x12*\x0A\x06a_star\x18I \x01(\x0B2\x10.pg_query.A_StarH\x00R\x06A_Star\x123\x0A\x09a_indices\x18J \x01(\x0B2\x13.pg_query.A_IndicesH\x00R\x09A_Indices\x12?\x0A\x0Da_indirection\x18K \x01(\x0B2\x17.pg_query.A_IndirectionH\x00R\x0DA_Indirection\x12:\x0A\x0Ca_array_expr\x18L \x01(\x0B2\x15.pg_query.A_ArrayExprH\x00R\x0BA_ArrayExpr\x124\x0A\x0Ares_target\x18M \x01(\x0B2\x13.pg_query.ResTargetH\x00R\x09ResTarget\x12D\x0A\x10multi_assign_ref\x18N \x01(\x0B2\x18.pg_query.MultiAssignRefH\x00R\x0EMultiAssignRef\x12+\x0A\x07sort_by\x18O \x01(\x0B2\x10.pg_query.SortByH\x00R\x06SortBy\x124\x0A\x0Awindow_def\x18P \x01(\x0B2\x13.pg_query.WindowDefH\x00R\x09WindowDef\x12C\x0A\x0Frange_subselect\x18Q \x01(\x0B2\x18.pg_query.RangeSubselectH\x00R\x0ERangeSubselect\x12@\x0A\x0Erange_function\x18R \x01(\x0B2\x17.pg_query.RangeFunctionH\x00R\x0DRangeFunction\x12D\x0A\x10range_table_func\x18S \x01(\x0B2\x18.pg_query.RangeTableFuncH\x00R\x0ERangeTableFunc\x12N\x0A\x14range_table_func_col\x18T \x01(\x0B2\x1B.pg_query.RangeTableFuncColH\x00R\x11RangeTableFuncCol\x12J\x0A\x12range_table_sample\x18U \x01(\x0B2\x1A.pg_query.RangeTableSampleH\x00R\x10RangeTableSample\x124\x0A\x0Acolumn_def\x18V \x01(\x0B2\x13.pg_query.ColumnDefH\x00R\x09ColumnDef\x12G\x0A\x11table_like_clause\x18W \x01(\x0B2\x19.pg_query.TableLikeClauseH\x00R\x0FTableLikeClause\x124\x0A\x0Aindex_elem\x18X \x01(\x0B2\x13.pg_query.IndexElemH\x00R\x09IndexElem\x12.\x0A\x08def_elem\x18Y \x01(\x0B2\x11.pg_query.DefElemH\x00R\x07DefElem\x12@\x0A\x0Elocking_clause\x18Z \x01(\x0B2\x17.pg_query.LockingClauseH\x00R\x0DLockingClause\x12=\x0A\x0Dxml_serialize\x18[ \x01(\x0B2\x16.pg_query.XmlSerializeH\x00R\x0CXmlSerialize\x12@\x0A\x0Epartition_elem\x18\\ \x01(\x0B2\x17.pg_query.PartitionElemH\x00R\x0DPartitionElem\x12@\x0A\x0Epartition_spec\x18] \x01(\x0B2\x17.pg_query.PartitionSpecH\x00R\x0DPartitionSpec\x12P\x0A\x14partition_bound_spec\x18^ \x01(\x0B2\x1C.pg_query.PartitionBoundSpecH\x00R\x12PartitionBoundSpec\x12S\x0A\x15partition_range_datum\x18_ \x01(\x0B2\x1D.pg_query.PartitionRangeDatumH\x00R\x13PartitionRangeDatum\x12S\x0A\x15single_partition_spec\x18` \x01(\x0B2\x1D.pg_query.SinglePartitionSpecH\x00R\x13SinglePartitionSpec\x12=\x0A\x0Dpartition_cmd\x18a \x01(\x0B2\x16.pg_query.PartitionCmdH\x00R\x0CPartitionCmd\x12A\x0A\x0Frange_tbl_entry\x18b \x01(\x0B2\x17.pg_query.RangeTblEntryH\x00R\x0DRangeTblEntry\x12L\x0A\x12rtepermission_info\x18c \x01(\x0B2\x1B.pg_query.RTEPermissionInfoH\x00R\x11RTEPermissionInfo\x12J\x0A\x12range_tbl_function\x18d \x01(\x0B2\x1A.pg_query.RangeTblFunctionH\x00R\x10RangeTblFunction\x12M\x0A\x13table_sample_clause\x18e \x01(\x0B2\x1B.pg_query.TableSampleClauseH\x00R\x11TableSampleClause\x12G\x0A\x11with_check_option\x18f \x01(\x0B2\x19.pg_query.WithCheckOptionH\x00R\x0FWithCheckOption\x12G\x0A\x11sort_group_clause\x18g \x01(\x0B2\x19.pg_query.SortGroupClauseH\x00R\x0FSortGroupClause\x12:\x0A\x0Cgrouping_set\x18h \x01(\x0B2\x15.pg_query.GroupingSetH\x00R\x0BGroupingSet\x12=\x0A\x0Dwindow_clause\x18i \x01(\x0B2\x16.pg_query.WindowClauseH\x00R\x0CWindowClause\x12A\x0A\x0Frow_mark_clause\x18j \x01(\x0B2\x17.pg_query.RowMarkClauseH\x00R\x0DRowMarkClause\x127\x0A\x0Bwith_clause\x18k \x01(\x0B2\x14.pg_query.WithClauseH\x00R\x0AWithClause\x12:\x0A\x0Cinfer_clause\x18l \x01(\x0B2\x15.pg_query.InferClauseH\x00R\x0BInferClause\x12J\x0A\x12on_conflict_clause\x18m \x01(\x0B2\x1A.pg_query.OnConflictClauseH\x00R\x10OnConflictClause\x12F\x0A\x10ctesearch_clause\x18n \x01(\x0B2\x19.pg_query.CTESearchClauseH\x00R\x0FCTESearchClause\x12C\x0A\x0Fctecycle_clause\x18o \x01(\x0B2\x18.pg_query.CTECycleClauseH\x00R\x0ECTECycleClause\x12G\x0A\x11common_table_expr\x18p \x01(\x0B2\x19.pg_query.CommonTableExprH\x00R\x0FCommonTableExpr\x12G\x0A\x11merge_when_clause\x18q \x01(\x0B2\x19.pg_query.MergeWhenClauseH\x00R\x0FMergeWhenClause\x12L\x0A\x12trigger_transition\x18r \x01(\x0B2\x1B.pg_query.TriggerTransitionH\x00R\x11TriggerTransition\x127\x0A\x0Bjson_output\x18s \x01(\x0B2\x14.pg_query.JsonOutputH\x00R\x0AJsonOutput\x12=\x0A\x0Djson_argument\x18t \x01(\x0B2\x16.pg_query.JsonArgumentH\x00R\x0CJsonArgument\x12>\x0A\x0Ejson_func_expr\x18u \x01(\x0B2\x16.pg_query.JsonFuncExprH\x00R\x0CJsonFuncExpr\x12N\x0A\x14json_table_path_spec\x18v \x01(\x0B2\x1B.pg_query.JsonTablePathSpecH\x00R\x11JsonTablePathSpec\x124\x0A\x0Ajson_table\x18w \x01(\x0B2\x13.pg_query.JsonTableH\x00R\x09JsonTable\x12G\x0A\x11json_table_column\x18x \x01(\x0B2\x19.pg_query.JsonTableColumnH\x00R\x0FJsonTableColumn\x12>\x0A\x0Ejson_key_value\x18y \x01(\x0B2\x16.pg_query.JsonKeyValueH\x00R\x0CJsonKeyValue\x12A\x0A\x0Fjson_parse_expr\x18z \x01(\x0B2\x17.pg_query.JsonParseExprH\x00R\x0DJsonParseExpr\x12D\x0A\x10json_scalar_expr\x18{ \x01(\x0B2\x18.pg_query.JsonScalarExprH\x00R\x0EJsonScalarExpr\x12M\x0A\x13json_serialize_expr\x18| \x01(\x0B2\x1B.pg_query.JsonSerializeExprH\x00R\x11JsonSerializeExpr\x12Y\x0A\x17json_object_constructor\x18} \x01(\x0B2\x1F.pg_query.JsonObjectConstructorH\x00R\x15JsonObjectConstructor\x12V\x0A\x16json_array_constructor\x18~ \x01(\x0B2\x1E.pg_query.JsonArrayConstructorH\x00R\x14JsonArrayConstructor\x12f\x0A\x1Cjson_array_query_constructor\x18\x7F \x01(\x0B2#.pg_query.JsonArrayQueryConstructorH\x00R\x19JsonArrayQueryConstructor\x12Q\x0A\x14json_agg_constructor\x18\x80\x01 \x01(\x0B2\x1C.pg_query.JsonAggConstructorH\x00R\x12JsonAggConstructor\x12B\x0A\x0Fjson_object_agg\x18\x81\x01 \x01(\x0B2\x17.pg_query.JsonObjectAggH\x00R\x0DJsonObjectAgg\x12?\x0A\x0Ejson_array_agg\x18\x82\x01 \x01(\x0B2\x16.pg_query.JsonArrayAggH\x00R\x0CJsonArrayAgg\x12/\x0A\x08raw_stmt\x18\x83\x01 \x01(\x0B2\x11.pg_query.RawStmtH\x00R\x07RawStmt\x128\x0A\x0Binsert_stmt\x18\x84\x01 \x01(\x0B2\x14.pg_query.InsertStmtH\x00R\x0AInsertStmt\x128\x0A\x0Bdelete_stmt\x18\x85\x01 \x01(\x0B2\x14.pg_query.DeleteStmtH\x00R\x0ADeleteStmt\x128\x0A\x0Bupdate_stmt\x18\x86\x01 \x01(\x0B2\x14.pg_query.UpdateStmtH\x00R\x0AUpdateStmt\x125\x0A\x0Amerge_stmt\x18\x87\x01 \x01(\x0B2\x13.pg_query.MergeStmtH\x00R\x09MergeStmt\x128\x0A\x0Bselect_stmt\x18\x88\x01 \x01(\x0B2\x14.pg_query.SelectStmtH\x00R\x0ASelectStmt\x12K\x0A\x12set_operation_stmt\x18\x89\x01 \x01(\x0B2\x1A.pg_query.SetOperationStmtH\x00R\x10SetOperationStmt\x128\x0A\x0Breturn_stmt\x18\x8A\x01 \x01(\x0B2\x14.pg_query.ReturnStmtH\x00R\x0AReturnStmt\x12>\x0A\x0Dplassign_stmt\x18\x8B\x01 \x01(\x0B2\x16.pg_query.PLAssignStmtH\x00R\x0CPLAssignStmt\x12K\x0A\x12create_schema_stmt\x18\x8C\x01 \x01(\x0B2\x1A.pg_query.CreateSchemaStmtH\x00R\x10CreateSchemaStmt\x12E\x0A\x10alter_table_stmt\x18\x8D\x01 \x01(\x0B2\x18.pg_query.AlterTableStmtH\x00R\x0EAlterTableStmt\x12T\x0A\x15replica_identity_stmt\x18\x8E\x01 \x01(\x0B2\x1D.pg_query.ReplicaIdentityStmtH\x00R\x13ReplicaIdentityStmt\x12B\x0A\x0Falter_table_cmd\x18\x8F\x01 \x01(\x0B2\x17.pg_query.AlterTableCmdH\x00R\x0DAlterTableCmd\x12Q\x0A\x14alter_collation_stmt\x18\x90\x01 \x01(\x0B2\x1C.pg_query.AlterCollationStmtH\x00R\x12AlterCollationStmt\x12H\x0A\x11alter_domain_stmt\x18\x91\x01 \x01(\x0B2\x19.pg_query.AlterDomainStmtH\x00R\x0FAlterDomainStmt\x125\x0A\x0Agrant_stmt\x18\x92\x01 \x01(\x0B2\x13.pg_query.GrantStmtH\x00R\x09GrantStmt\x12E\x0A\x10object_with_args\x18\x93\x01 \x01(\x0B2\x18.pg_query.ObjectWithArgsH\x00R\x0EObjectWithArgs\x128\x0A\x0Baccess_priv\x18\x94\x01 \x01(\x0B2\x14.pg_query.AccessPrivH\x00R\x0AAccessPriv\x12B\x0A\x0Fgrant_role_stmt\x18\x95\x01 \x01(\x0B2\x17.pg_query.GrantRoleStmtH\x00R\x0DGrantRoleStmt\x12j\x0A\x1Dalter_default_privileges_stmt\x18\x96\x01 \x01(\x0B2\$.pg_query.AlterDefaultPrivilegesStmtH\x00R\x1AAlterDefaultPrivilegesStmt\x122\x0A\x09copy_stmt\x18\x97\x01 \x01(\x0B2\x12.pg_query.CopyStmtH\x00R\x08CopyStmt\x12H\x0A\x11variable_set_stmt\x18\x98\x01 \x01(\x0B2\x19.pg_query.VariableSetStmtH\x00R\x0FVariableSetStmt\x12K\x0A\x12variable_show_stmt\x18\x99\x01 \x01(\x0B2\x1A.pg_query.VariableShowStmtH\x00R\x10VariableShowStmt\x128\x0A\x0Bcreate_stmt\x18\x9A\x01 \x01(\x0B2\x14.pg_query.CreateStmtH\x00R\x0ACreateStmt\x127\x0A\x0Aconstraint\x18\x9B\x01 \x01(\x0B2\x14.pg_query.ConstraintH\x00R\x0AConstraint\x12X\x0A\x17create_table_space_stmt\x18\x9C\x01 \x01(\x0B2\x1E.pg_query.CreateTableSpaceStmtH\x00R\x14CreateTableSpaceStmt\x12R\x0A\x15drop_table_space_stmt\x18\x9D\x01 \x01(\x0B2\x1C.pg_query.DropTableSpaceStmtH\x00R\x12DropTableSpaceStmt\x12k\x0A\x1Ealter_table_space_options_stmt\x18\x9E\x01 \x01(\x0B2\$.pg_query.AlterTableSpaceOptionsStmtH\x00R\x1AAlterTableSpaceOptionsStmt\x12\\\x0A\x19alter_table_move_all_stmt\x18\x9F\x01 \x01(\x0B2\x1F.pg_query.AlterTableMoveAllStmtH\x00R\x15AlterTableMoveAllStmt\x12T\x0A\x15create_extension_stmt\x18\xA0\x01 \x01(\x0B2\x1D.pg_query.CreateExtensionStmtH\x00R\x13CreateExtensionStmt\x12Q\x0A\x14alter_extension_stmt\x18\xA1\x01 \x01(\x0B2\x1C.pg_query.AlterExtensionStmtH\x00R\x12AlterExtensionStmt\x12j\x0A\x1Dalter_extension_contents_stmt\x18\xA2\x01 \x01(\x0B2\$.pg_query.AlterExtensionContentsStmtH\x00R\x1AAlterExtensionContentsStmt\x12B\x0A\x0Fcreate_fdw_stmt\x18\xA3\x01 \x01(\x0B2\x17.pg_query.CreateFdwStmtH\x00R\x0DCreateFdwStmt\x12?\x0A\x0Ealter_fdw_stmt\x18\xA4\x01 \x01(\x0B2\x16.pg_query.AlterFdwStmtH\x00R\x0CAlterFdwStmt\x12a\x0A\x1Acreate_foreign_server_stmt\x18\xA5\x01 \x01(\x0B2!.pg_query.CreateForeignServerStmtH\x00R\x17CreateForeignServerStmt\x12^\x0A\x19alter_foreign_server_stmt\x18\xA6\x01 \x01(\x0B2 .pg_query.AlterForeignServerStmtH\x00R\x16AlterForeignServerStmt\x12^\x0A\x19create_foreign_table_stmt\x18\xA7\x01 \x01(\x0B2 .pg_query.CreateForeignTableStmtH\x00R\x16CreateForeignTableStmt\x12[\x0A\x18create_user_mapping_stmt\x18\xA8\x01 \x01(\x0B2\x1F.pg_query.CreateUserMappingStmtH\x00R\x15CreateUserMappingStmt\x12X\x0A\x17alter_user_mapping_stmt\x18\xA9\x01 \x01(\x0B2\x1E.pg_query.AlterUserMappingStmtH\x00R\x14AlterUserMappingStmt\x12U\x0A\x16drop_user_mapping_stmt\x18\xAA\x01 \x01(\x0B2\x1D.pg_query.DropUserMappingStmtH\x00R\x13DropUserMappingStmt\x12a\x0A\x1Aimport_foreign_schema_stmt\x18\xAB\x01 \x01(\x0B2!.pg_query.ImportForeignSchemaStmtH\x00R\x17ImportForeignSchemaStmt\x12K\x0A\x12create_policy_stmt\x18\xAC\x01 \x01(\x0B2\x1A.pg_query.CreatePolicyStmtH\x00R\x10CreatePolicyStmt\x12H\x0A\x11alter_policy_stmt\x18\xAD\x01 \x01(\x0B2\x19.pg_query.AlterPolicyStmtH\x00R\x0FAlterPolicyStmt\x12?\x0A\x0Ecreate_am_stmt\x18\xAE\x01 \x01(\x0B2\x16.pg_query.CreateAmStmtH\x00R\x0CCreateAmStmt\x12E\x0A\x10create_trig_stmt\x18\xAF\x01 \x01(\x0B2\x18.pg_query.CreateTrigStmtH\x00R\x0ECreateTrigStmt\x12U\x0A\x16create_event_trig_stmt\x18\xB0\x01 \x01(\x0B2\x1D.pg_query.CreateEventTrigStmtH\x00R\x13CreateEventTrigStmt\x12R\x0A\x15alter_event_trig_stmt\x18\xB1\x01 \x01(\x0B2\x1C.pg_query.AlterEventTrigStmtH\x00R\x12AlterEventTrigStmt\x12H\x0A\x11create_plang_stmt\x18\xB2\x01 \x01(\x0B2\x19.pg_query.CreatePLangStmtH\x00R\x0FCreatePLangStmt\x12E\x0A\x10create_role_stmt\x18\xB3\x01 \x01(\x0B2\x18.pg_query.CreateRoleStmtH\x00R\x0ECreateRoleStmt\x12B\x0A\x0Falter_role_stmt\x18\xB4\x01 \x01(\x0B2\x17.pg_query.AlterRoleStmtH\x00R\x0DAlterRoleStmt\x12L\x0A\x13alter_role_set_stmt\x18\xB5\x01 \x01(\x0B2\x1A.pg_query.AlterRoleSetStmtH\x00R\x10AlterRoleSetStmt\x12?\x0A\x0Edrop_role_stmt\x18\xB6\x01 \x01(\x0B2\x16.pg_query.DropRoleStmtH\x00R\x0CDropRoleStmt\x12B\x0A\x0Fcreate_seq_stmt\x18\xB7\x01 \x01(\x0B2\x17.pg_query.CreateSeqStmtH\x00R\x0DCreateSeqStmt\x12?\x0A\x0Ealter_seq_stmt\x18\xB8\x01 \x01(\x0B2\x16.pg_query.AlterSeqStmtH\x00R\x0CAlterSeqStmt\x128\x0A\x0Bdefine_stmt\x18\xB9\x01 \x01(\x0B2\x14.pg_query.DefineStmtH\x00R\x0ADefineStmt\x12K\x0A\x12create_domain_stmt\x18\xBA\x01 \x01(\x0B2\x1A.pg_query.CreateDomainStmtH\x00R\x10CreateDomainStmt\x12O\x0A\x14create_op_class_stmt\x18\xBB\x01 \x01(\x0B2\x1B.pg_query.CreateOpClassStmtH\x00R\x11CreateOpClassStmt\x12O\x0A\x14create_op_class_item\x18\xBC\x01 \x01(\x0B2\x1B.pg_query.CreateOpClassItemH\x00R\x11CreateOpClassItem\x12R\x0A\x15create_op_family_stmt\x18\xBD\x01 \x01(\x0B2\x1C.pg_query.CreateOpFamilyStmtH\x00R\x12CreateOpFamilyStmt\x12O\x0A\x14alter_op_family_stmt\x18\xBE\x01 \x01(\x0B2\x1B.pg_query.AlterOpFamilyStmtH\x00R\x11AlterOpFamilyStmt\x122\x0A\x09drop_stmt\x18\xBF\x01 \x01(\x0B2\x12.pg_query.DropStmtH\x00R\x08DropStmt\x12>\x0A\x0Dtruncate_stmt\x18\xC0\x01 \x01(\x0B2\x16.pg_query.TruncateStmtH\x00R\x0CTruncateStmt\x12;\x0A\x0Ccomment_stmt\x18\xC1\x01 \x01(\x0B2\x15.pg_query.CommentStmtH\x00R\x0BCommentStmt\x12?\x0A\x0Esec_label_stmt\x18\xC2\x01 \x01(\x0B2\x16.pg_query.SecLabelStmtH\x00R\x0CSecLabelStmt\x12N\x0A\x13declare_cursor_stmt\x18\xC3\x01 \x01(\x0B2\x1B.pg_query.DeclareCursorStmtH\x00R\x11DeclareCursorStmt\x12H\x0A\x11close_portal_stmt\x18\xC4\x01 \x01(\x0B2\x19.pg_query.ClosePortalStmtH\x00R\x0FClosePortalStmt\x125\x0A\x0Afetch_stmt\x18\xC5\x01 \x01(\x0B2\x13.pg_query.FetchStmtH\x00R\x09FetchStmt\x125\x0A\x0Aindex_stmt\x18\xC6\x01 \x01(\x0B2\x13.pg_query.IndexStmtH\x00R\x09IndexStmt\x12H\x0A\x11create_stats_stmt\x18\xC7\x01 \x01(\x0B2\x19.pg_query.CreateStatsStmtH\x00R\x0FCreateStatsStmt\x125\x0A\x0Astats_elem\x18\xC8\x01 \x01(\x0B2\x13.pg_query.StatsElemH\x00R\x09StatsElem\x12E\x0A\x10alter_stats_stmt\x18\xC9\x01 \x01(\x0B2\x18.pg_query.AlterStatsStmtH\x00R\x0EAlterStatsStmt\x12Q\x0A\x14create_function_stmt\x18\xCA\x01 \x01(\x0B2\x1C.pg_query.CreateFunctionStmtH\x00R\x12CreateFunctionStmt\x12M\x0A\x12function_parameter\x18\xCB\x01 \x01(\x0B2\x1B.pg_query.FunctionParameterH\x00R\x11FunctionParameter\x12N\x0A\x13alter_function_stmt\x18\xCC\x01 \x01(\x0B2\x1B.pg_query.AlterFunctionStmtH\x00R\x11AlterFunctionStmt\x12,\x0A\x07do_stmt\x18\xCD\x01 \x01(\x0B2\x10.pg_query.DoStmtH\x00R\x06DoStmt\x12H\x0A\x11inline_code_block\x18\xCE\x01 \x01(\x0B2\x19.pg_query.InlineCodeBlockH\x00R\x0FInlineCodeBlock\x122\x0A\x09call_stmt\x18\xCF\x01 \x01(\x0B2\x12.pg_query.CallStmtH\x00R\x08CallStmt\x12;\x0A\x0Ccall_context\x18\xD0\x01 \x01(\x0B2\x15.pg_query.CallContextH\x00R\x0BCallContext\x128\x0A\x0Brename_stmt\x18\xD1\x01 \x01(\x0B2\x14.pg_query.RenameStmtH\x00R\x0ARenameStmt\x12^\x0A\x19alter_object_depends_stmt\x18\xD2\x01 \x01(\x0B2 .pg_query.AlterObjectDependsStmtH\x00R\x16AlterObjectDependsStmt\x12[\x0A\x18alter_object_schema_stmt\x18\xD3\x01 \x01(\x0B2\x1F.pg_query.AlterObjectSchemaStmtH\x00R\x15AlterObjectSchemaStmt\x12E\x0A\x10alter_owner_stmt\x18\xD4\x01 \x01(\x0B2\x18.pg_query.AlterOwnerStmtH\x00R\x0EAlterOwnerStmt\x12N\x0A\x13alter_operator_stmt\x18\xD5\x01 \x01(\x0B2\x1B.pg_query.AlterOperatorStmtH\x00R\x11AlterOperatorStmt\x12B\x0A\x0Falter_type_stmt\x18\xD6\x01 \x01(\x0B2\x17.pg_query.AlterTypeStmtH\x00R\x0DAlterTypeStmt\x122\x0A\x09rule_stmt\x18\xD7\x01 \x01(\x0B2\x12.pg_query.RuleStmtH\x00R\x08RuleStmt\x128\x0A\x0Bnotify_stmt\x18\xD8\x01 \x01(\x0B2\x14.pg_query.NotifyStmtH\x00R\x0ANotifyStmt\x128\x0A\x0Blisten_stmt\x18\xD9\x01 \x01(\x0B2\x14.pg_query.ListenStmtH\x00R\x0AListenStmt\x12>\x0A\x0Dunlisten_stmt\x18\xDA\x01 \x01(\x0B2\x16.pg_query.UnlistenStmtH\x00R\x0CUnlistenStmt\x12G\x0A\x10transaction_stmt\x18\xDB\x01 \x01(\x0B2\x19.pg_query.TransactionStmtH\x00R\x0FTransactionStmt\x12N\x0A\x13composite_type_stmt\x18\xDC\x01 \x01(\x0B2\x1B.pg_query.CompositeTypeStmtH\x00R\x11CompositeTypeStmt\x12E\x0A\x10create_enum_stmt\x18\xDD\x01 \x01(\x0B2\x18.pg_query.CreateEnumStmtH\x00R\x0ECreateEnumStmt\x12H\x0A\x11create_range_stmt\x18\xDE\x01 \x01(\x0B2\x19.pg_query.CreateRangeStmtH\x00R\x0FCreateRangeStmt\x12B\x0A\x0Falter_enum_stmt\x18\xDF\x01 \x01(\x0B2\x17.pg_query.AlterEnumStmtH\x00R\x0DAlterEnumStmt\x122\x0A\x09view_stmt\x18\xE0\x01 \x01(\x0B2\x12.pg_query.ViewStmtH\x00R\x08ViewStmt\x122\x0A\x09load_stmt\x18\xE1\x01 \x01(\x0B2\x12.pg_query.LoadStmtH\x00R\x08LoadStmt\x12>\x0A\x0Dcreatedb_stmt\x18\xE2\x01 \x01(\x0B2\x16.pg_query.CreatedbStmtH\x00R\x0CCreatedbStmt\x12N\x0A\x13alter_database_stmt\x18\xE3\x01 \x01(\x0B2\x1B.pg_query.AlterDatabaseStmtH\x00R\x11AlterDatabaseStmt\x12q\x0A alter_database_refresh_coll_stmt\x18\xE4\x01 \x01(\x0B2&.pg_query.AlterDatabaseRefreshCollStmtH\x00R\x1CAlterDatabaseRefreshCollStmt\x12X\x0A\x17alter_database_set_stmt\x18\xE5\x01 \x01(\x0B2\x1E.pg_query.AlterDatabaseSetStmtH\x00R\x14AlterDatabaseSetStmt\x128\x0A\x0Bdropdb_stmt\x18\xE6\x01 \x01(\x0B2\x14.pg_query.DropdbStmtH\x00R\x0ADropdbStmt\x12H\x0A\x11alter_system_stmt\x18\xE7\x01 \x01(\x0B2\x19.pg_query.AlterSystemStmtH\x00R\x0FAlterSystemStmt\x12;\x0A\x0Ccluster_stmt\x18\xE8\x01 \x01(\x0B2\x15.pg_query.ClusterStmtH\x00R\x0BClusterStmt\x128\x0A\x0Bvacuum_stmt\x18\xE9\x01 \x01(\x0B2\x14.pg_query.VacuumStmtH\x00R\x0AVacuumStmt\x12D\x0A\x0Fvacuum_relation\x18\xEA\x01 \x01(\x0B2\x18.pg_query.VacuumRelationH\x00R\x0EVacuumRelation\x12;\x0A\x0Cexplain_stmt\x18\xEB\x01 \x01(\x0B2\x15.pg_query.ExplainStmtH\x00R\x0BExplainStmt\x12O\x0A\x14create_table_as_stmt\x18\xEC\x01 \x01(\x0B2\x1B.pg_query.CreateTableAsStmtH\x00R\x11CreateTableAsStmt\x12R\x0A\x15refresh_mat_view_stmt\x18\xED\x01 \x01(\x0B2\x1C.pg_query.RefreshMatViewStmtH\x00R\x12RefreshMatViewStmt\x12E\x0A\x10check_point_stmt\x18\xEE\x01 \x01(\x0B2\x18.pg_query.CheckPointStmtH\x00R\x0ECheckPointStmt\x12;\x0A\x0Cdiscard_stmt\x18\xEF\x01 \x01(\x0B2\x15.pg_query.DiscardStmtH\x00R\x0BDiscardStmt\x122\x0A\x09lock_stmt\x18\xF0\x01 \x01(\x0B2\x12.pg_query.LockStmtH\x00R\x08LockStmt\x12Q\x0A\x14constraints_set_stmt\x18\xF1\x01 \x01(\x0B2\x1C.pg_query.ConstraintsSetStmtH\x00R\x12ConstraintsSetStmt\x12;\x0A\x0Creindex_stmt\x18\xF2\x01 \x01(\x0B2\x15.pg_query.ReindexStmtH\x00R\x0BReindexStmt\x12W\x0A\x16create_conversion_stmt\x18\xF3\x01 \x01(\x0B2\x1E.pg_query.CreateConversionStmtH\x00R\x14CreateConversionStmt\x12E\x0A\x10create_cast_stmt\x18\xF4\x01 \x01(\x0B2\x18.pg_query.CreateCastStmtH\x00R\x0ECreateCastStmt\x12T\x0A\x15create_transform_stmt\x18\xF5\x01 \x01(\x0B2\x1D.pg_query.CreateTransformStmtH\x00R\x13CreateTransformStmt\x12;\x0A\x0Cprepare_stmt\x18\xF6\x01 \x01(\x0B2\x15.pg_query.PrepareStmtH\x00R\x0BPrepareStmt\x12;\x0A\x0Cexecute_stmt\x18\xF7\x01 \x01(\x0B2\x15.pg_query.ExecuteStmtH\x00R\x0BExecuteStmt\x12D\x0A\x0Fdeallocate_stmt\x18\xF8\x01 \x01(\x0B2\x18.pg_query.DeallocateStmtH\x00R\x0EDeallocateStmt\x12B\x0A\x0Fdrop_owned_stmt\x18\xF9\x01 \x01(\x0B2\x17.pg_query.DropOwnedStmtH\x00R\x0DDropOwnedStmt\x12N\x0A\x13reassign_owned_stmt\x18\xFA\x01 \x01(\x0B2\x1B.pg_query.ReassignOwnedStmtH\x00R\x11ReassignOwnedStmt\x12Z\x0A\x17alter_tsdictionary_stmt\x18\xFB\x01 \x01(\x0B2\x1F.pg_query.AlterTSDictionaryStmtH\x00R\x15AlterTSDictionaryStmt\x12c\x0A\x1Aalter_tsconfiguration_stmt\x18\xFC\x01 \x01(\x0B2\".pg_query.AlterTSConfigurationStmtH\x00R\x18AlterTSConfigurationStmt\x12J\x0A\x11publication_table\x18\xFD\x01 \x01(\x0B2\x1A.pg_query.PublicationTableH\x00R\x10PublicationTable\x12Q\x0A\x14publication_obj_spec\x18\xFE\x01 \x01(\x0B2\x1C.pg_query.PublicationObjSpecH\x00R\x12PublicationObjSpec\x12Z\x0A\x17create_publication_stmt\x18\xFF\x01 \x01(\x0B2\x1F.pg_query.CreatePublicationStmtH\x00R\x15CreatePublicationStmt\x12W\x0A\x16alter_publication_stmt\x18\x80\x02 \x01(\x0B2\x1E.pg_query.AlterPublicationStmtH\x00R\x14AlterPublicationStmt\x12]\x0A\x18create_subscription_stmt\x18\x81\x02 \x01(\x0B2 .pg_query.CreateSubscriptionStmtH\x00R\x16CreateSubscriptionStmt\x12Z\x0A\x17alter_subscription_stmt\x18\x82\x02 \x01(\x0B2\x1F.pg_query.AlterSubscriptionStmtH\x00R\x15AlterSubscriptionStmt\x12W\x0A\x16drop_subscription_stmt\x18\x83\x02 \x01(\x0B2\x1E.pg_query.DropSubscriptionStmtH\x00R\x14DropSubscriptionStmt\x12.\x0A\x07integer\x18\x84\x02 \x01(\x0B2\x11.pg_query.IntegerH\x00R\x07Integer\x12(\x0A\x05float\x18\x85\x02 \x01(\x0B2\x0F.pg_query.FloatH\x00R\x05Float\x12.\x0A\x07boolean\x18\x86\x02 \x01(\x0B2\x11.pg_query.BooleanH\x00R\x07Boolean\x12+\x0A\x06string\x18\x87\x02 \x01(\x0B2\x10.pg_query.StringH\x00R\x06String\x125\x0A\x0Abit_string\x18\x88\x02 \x01(\x0B2\x13.pg_query.BitStringH\x00R\x09BitString\x12%\x0A\x04list\x18\x89\x02 \x01(\x0B2\x0E.pg_query.ListH\x00R\x04List\x12/\x0A\x08int_list\x18\x8A\x02 \x01(\x0B2\x11.pg_query.IntListH\x00R\x07IntList\x12/\x0A\x08oid_list\x18\x8B\x02 \x01(\x0B2\x11.pg_query.OidListH\x00R\x07OidList\x12.\x0A\x07a_const\x18\x8C\x02 \x01(\x0B2\x11.pg_query.A_ConstH\x00R\x07A_ConstB\x06\x0A\x04node\"\x17\x0A\x07Integer\x12\x0C\x0A\x04ival\x18\x01 \x01(\x05\"\x15\x0A\x05Float\x12\x0C\x0A\x04fval\x18\x01 \x01(\x09\"\x1A\x0A\x07Boolean\x12\x0F\x0A\x07boolval\x18\x01 \x01(\x08\"\x16\x0A\x06String\x12\x0C\x0A\x04sval\x18\x01 \x01(\x09\"\x1A\x0A\x09BitString\x12\x0D\x0A\x05bsval\x18\x01 \x01(\x09\"%\x0A\x04List\x12\x1D\x0A\x05items\x18\x01 \x03(\x0B2\x0E.pg_query.Node\"(\x0A\x07OidList\x12\x1D\x0A\x05items\x18\x01 \x03(\x0B2\x0E.pg_query.Node\"(\x0A\x07IntList\x12\x1D\x0A\x05items\x18\x01 \x03(\x0B2\x0E.pg_query.Node\"\xE4\x01\x0A\x07A_Const\x12!\x0A\x04ival\x18\x01 \x01(\x0B2\x11.pg_query.IntegerH\x00\x12\x1F\x0A\x04fval\x18\x02 \x01(\x0B2\x0F.pg_query.FloatH\x00\x12\$\x0A\x07boolval\x18\x03 \x01(\x0B2\x11.pg_query.BooleanH\x00\x12 \x0A\x04sval\x18\x04 \x01(\x0B2\x10.pg_query.StringH\x00\x12\$\x0A\x05bsval\x18\x05 \x01(\x0B2\x13.pg_query.BitStringH\x00\x12\x0E\x0A\x06isnull\x18\x0A \x01(\x08\x12\x10\x0A\x08location\x18\x0B \x01(\x05B\x05\x0A\x03val\"Q\x0A\x05Alias\x12\x1C\x0A\x09aliasname\x18\x01 \x01(\x09R\x09aliasname\x12*\x0A\x08colnames\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x08colnames\"\xE3\x01\x0A\x08RangeVar\x12 \x0A\x0Bcatalogname\x18\x01 \x01(\x09R\x0Bcatalogname\x12\x1E\x0A\x0Aschemaname\x18\x02 \x01(\x09R\x0Aschemaname\x12\x18\x0A\x07relname\x18\x03 \x01(\x09R\x07relname\x12\x10\x0A\x03inh\x18\x04 \x01(\x08R\x03inh\x12&\x0A\x0Erelpersistence\x18\x05 \x01(\x09R\x0Erelpersistence\x12%\x0A\x05alias\x18\x06 \x01(\x0B2\x0F.pg_query.AliasR\x05alias\x12\x1A\x0A\x08location\x18\x07 \x01(\x05R\x08location\"\xF4\x05\x0A\x09TableFunc\x123\x0A\x08functype\x18\x01 \x01(\x0E2\x17.pg_query.TableFuncTypeR\x08functype\x12(\x0A\x07ns_uris\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x07ns_uris\x12*\x0A\x08ns_names\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x08ns_names\x12(\x0A\x07docexpr\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x07docexpr\x12(\x0A\x07rowexpr\x18\x05 \x01(\x0B2\x0E.pg_query.NodeR\x07rowexpr\x12*\x0A\x08colnames\x18\x06 \x03(\x0B2\x0E.pg_query.NodeR\x08colnames\x12*\x0A\x08coltypes\x18\x07 \x03(\x0B2\x0E.pg_query.NodeR\x08coltypes\x12.\x0A\x0Acoltypmods\x18\x08 \x03(\x0B2\x0E.pg_query.NodeR\x0Acoltypmods\x124\x0A\x0Dcolcollations\x18\x09 \x03(\x0B2\x0E.pg_query.NodeR\x0Dcolcollations\x12*\x0A\x08colexprs\x18\x0A \x03(\x0B2\x0E.pg_query.NodeR\x08colexprs\x120\x0A\x0Bcoldefexprs\x18\x0B \x03(\x0B2\x0E.pg_query.NodeR\x0Bcoldefexprs\x120\x0A\x0Bcolvalexprs\x18\x0C \x03(\x0B2\x0E.pg_query.NodeR\x0Bcolvalexprs\x128\x0A\x0Fpassingvalexprs\x18\x0D \x03(\x0B2\x0E.pg_query.NodeR\x0Fpassingvalexprs\x12\x1A\x0A\x08notnulls\x18\x0E \x03(\x04R\x08notnulls\x12\"\x0A\x04plan\x18\x0F \x01(\x0B2\x0E.pg_query.NodeR\x04plan\x12\$\x0A\x0Dordinalitycol\x18\x10 \x01(\x05R\x0Dordinalitycol\x12\x1A\x0A\x08location\x18\x11 \x01(\x05R\x08location\"\xDB\x02\x0A\x0AIntoClause\x12\$\x0A\x03rel\x18\x01 \x01(\x0B2\x12.pg_query.RangeVarR\x03rel\x12+\x0A\x09col_names\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x08colNames\x12#\x0A\x0Daccess_method\x18\x03 \x01(\x09R\x0CaccessMethod\x12(\x0A\x07options\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x07options\x125\x0A\x09on_commit\x18\x05 \x01(\x0E2\x18.pg_query.OnCommitActionR\x08onCommit\x12(\x0A\x10table_space_name\x18\x06 \x01(\x09R\x0EtableSpaceName\x12-\x0A\x0Aview_query\x18\x07 \x01(\x0B2\x0E.pg_query.NodeR\x09viewQuery\x12\x1B\x0A\x09skip_data\x18\x08 \x01(\x08R\x08skipData\"\x95\x02\x0A\x03Var\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\x14\x0A\x05varno\x18\x02 \x01(\x05R\x05varno\x12\x1A\x0A\x08varattno\x18\x03 \x01(\x05R\x08varattno\x12\x18\x0A\x07vartype\x18\x04 \x01(\x0DR\x07vartype\x12\x1C\x0A\x09vartypmod\x18\x05 \x01(\x05R\x09vartypmod\x12\x1C\x0A\x09varcollid\x18\x06 \x01(\x0DR\x09varcollid\x12&\x0A\x0Evarnullingrels\x18\x07 \x03(\x04R\x0Evarnullingrels\x12 \x0A\x0Bvarlevelsup\x18\x08 \x01(\x0DR\x0Bvarlevelsup\x12\x1A\x0A\x08location\x18\x09 \x01(\x05R\x08location\"\xF4\x01\x0A\x05Param\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x121\x0A\x09paramkind\x18\x02 \x01(\x0E2\x13.pg_query.ParamKindR\x09paramkind\x12\x18\x0A\x07paramid\x18\x03 \x01(\x05R\x07paramid\x12\x1C\x0A\x09paramtype\x18\x04 \x01(\x0DR\x09paramtype\x12 \x0A\x0Bparamtypmod\x18\x05 \x01(\x05R\x0Bparamtypmod\x12 \x0A\x0Bparamcollid\x18\x06 \x01(\x0DR\x0Bparamcollid\x12\x1A\x0A\x08location\x18\x07 \x01(\x05R\x08location\"\xB2\x05\x0A\x06Aggref\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\x1A\x0A\x08aggfnoid\x18\x02 \x01(\x0DR\x08aggfnoid\x12\x18\x0A\x07aggtype\x18\x03 \x01(\x0DR\x07aggtype\x12\x1C\x0A\x09aggcollid\x18\x04 \x01(\x0DR\x09aggcollid\x12 \x0A\x0Binputcollid\x18\x05 \x01(\x0DR\x0Binputcollid\x120\x0A\x0Baggargtypes\x18\x06 \x03(\x0B2\x0E.pg_query.NodeR\x0Baggargtypes\x124\x0A\x0Daggdirectargs\x18\x07 \x03(\x0B2\x0E.pg_query.NodeR\x0Daggdirectargs\x12\"\x0A\x04args\x18\x08 \x03(\x0B2\x0E.pg_query.NodeR\x04args\x12*\x0A\x08aggorder\x18\x09 \x03(\x0B2\x0E.pg_query.NodeR\x08aggorder\x120\x0A\x0Baggdistinct\x18\x0A \x03(\x0B2\x0E.pg_query.NodeR\x0Baggdistinct\x12,\x0A\x09aggfilter\x18\x0B \x01(\x0B2\x0E.pg_query.NodeR\x09aggfilter\x12\x18\x0A\x07aggstar\x18\x0C \x01(\x08R\x07aggstar\x12 \x0A\x0Baggvariadic\x18\x0D \x01(\x08R\x0Baggvariadic\x12\x18\x0A\x07aggkind\x18\x0E \x01(\x09R\x07aggkind\x12 \x0A\x0Bagglevelsup\x18\x0F \x01(\x0DR\x0Bagglevelsup\x12.\x0A\x08aggsplit\x18\x10 \x01(\x0E2\x12.pg_query.AggSplitR\x08aggsplit\x12\x14\x0A\x05aggno\x18\x11 \x01(\x05R\x05aggno\x12\x1E\x0A\x0Aaggtransno\x18\x12 \x01(\x05R\x0Aaggtransno\x12\x1A\x0A\x08location\x18\x13 \x01(\x05R\x08location\"\xB6\x01\x0A\x0CGroupingFunc\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\"\x0A\x04args\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x04args\x12\"\x0A\x04refs\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x04refs\x12 \x0A\x0Bagglevelsup\x18\x04 \x01(\x0DR\x0Bagglevelsup\x12\x1A\x0A\x08location\x18\x05 \x01(\x05R\x08location\"\x91\x03\x0A\x0AWindowFunc\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\x1A\x0A\x08winfnoid\x18\x02 \x01(\x0DR\x08winfnoid\x12\x18\x0A\x07wintype\x18\x03 \x01(\x0DR\x07wintype\x12\x1C\x0A\x09wincollid\x18\x04 \x01(\x0DR\x09wincollid\x12 \x0A\x0Binputcollid\x18\x05 \x01(\x0DR\x0Binputcollid\x12\"\x0A\x04args\x18\x06 \x03(\x0B2\x0E.pg_query.NodeR\x04args\x12,\x0A\x09aggfilter\x18\x07 \x01(\x0B2\x0E.pg_query.NodeR\x09aggfilter\x123\x0A\x0Drun_condition\x18\x08 \x03(\x0B2\x0E.pg_query.NodeR\x0CrunCondition\x12\x16\x0A\x06winref\x18\x09 \x01(\x0DR\x06winref\x12\x18\x0A\x07winstar\x18\x0A \x01(\x08R\x07winstar\x12\x16\x0A\x06winagg\x18\x0B \x01(\x08R\x06winagg\x12\x1A\x0A\x08location\x18\x0C \x01(\x05R\x08location\"\xB2\x01\x0A\x16WindowFuncRunCondition\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\x12\x0A\x04opno\x18\x02 \x01(\x0DR\x04opno\x12 \x0A\x0Binputcollid\x18\x03 \x01(\x0DR\x0Binputcollid\x12\x1E\x0A\x0Awfunc_left\x18\x04 \x01(\x08R\x0Awfunc_left\x12 \x0A\x03arg\x18\x05 \x01(\x0B2\x0E.pg_query.NodeR\x03arg\"\x88\x01\x0A\x10MergeSupportFunc\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\x18\x0A\x07msftype\x18\x02 \x01(\x0DR\x07msftype\x12\x1C\x0A\x09msfcollid\x18\x03 \x01(\x0DR\x09msfcollid\x12\x1A\x0A\x08location\x18\x04 \x01(\x05R\x08location\"\xAF\x03\x0A\x0FSubscriptingRef\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12*\x0A\x10refcontainertype\x18\x02 \x01(\x0DR\x10refcontainertype\x12 \x0A\x0Brefelemtype\x18\x03 \x01(\x0DR\x0Brefelemtype\x12\x1E\x0A\x0Arefrestype\x18\x04 \x01(\x0DR\x0Arefrestype\x12\x1C\x0A\x09reftypmod\x18\x05 \x01(\x05R\x09reftypmod\x12\x1C\x0A\x09refcollid\x18\x06 \x01(\x0DR\x09refcollid\x128\x0A\x0Frefupperindexpr\x18\x07 \x03(\x0B2\x0E.pg_query.NodeR\x0Frefupperindexpr\x128\x0A\x0Freflowerindexpr\x18\x08 \x03(\x0B2\x0E.pg_query.NodeR\x0Freflowerindexpr\x12(\x0A\x07refexpr\x18\x09 \x01(\x0B2\x0E.pg_query.NodeR\x07refexpr\x122\x0A\x0Crefassgnexpr\x18\x0A \x01(\x0B2\x0E.pg_query.NodeR\x0Crefassgnexpr\"\xEA\x02\x0A\x08FuncExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\x16\x0A\x06funcid\x18\x02 \x01(\x0DR\x06funcid\x12&\x0A\x0Efuncresulttype\x18\x03 \x01(\x0DR\x0Efuncresulttype\x12\x1E\x0A\x0Afuncretset\x18\x04 \x01(\x08R\x0Afuncretset\x12\"\x0A\x0Cfuncvariadic\x18\x05 \x01(\x08R\x0Cfuncvariadic\x126\x0A\x0Afuncformat\x18\x06 \x01(\x0E2\x16.pg_query.CoercionFormR\x0Afuncformat\x12\x1E\x0A\x0Afunccollid\x18\x07 \x01(\x0DR\x0Afunccollid\x12 \x0A\x0Binputcollid\x18\x08 \x01(\x0DR\x0Binputcollid\x12\"\x0A\x04args\x18\x09 \x03(\x0B2\x0E.pg_query.NodeR\x04args\x12\x1A\x0A\x08location\x18\x0A \x01(\x05R\x08location\"\xA0\x01\x0A\x0CNamedArgExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12 \x0A\x03arg\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x03arg\x12\x12\x0A\x04name\x18\x03 \x01(\x09R\x04name\x12\x1C\x0A\x09argnumber\x18\x04 \x01(\x05R\x09argnumber\x12\x1A\x0A\x08location\x18\x05 \x01(\x05R\x08location\"\xFC\x01\x0A\x06OpExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\x12\x0A\x04opno\x18\x02 \x01(\x0DR\x04opno\x12\"\x0A\x0Copresulttype\x18\x03 \x01(\x0DR\x0Copresulttype\x12\x1A\x0A\x08opretset\x18\x04 \x01(\x08R\x08opretset\x12\x1A\x0A\x08opcollid\x18\x05 \x01(\x0DR\x08opcollid\x12 \x0A\x0Binputcollid\x18\x06 \x01(\x0DR\x0Binputcollid\x12\"\x0A\x04args\x18\x07 \x03(\x0B2\x0E.pg_query.NodeR\x04args\x12\x1A\x0A\x08location\x18\x08 \x01(\x05R\x08location\"\x82\x02\x0A\x0CDistinctExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\x12\x0A\x04opno\x18\x02 \x01(\x0DR\x04opno\x12\"\x0A\x0Copresulttype\x18\x03 \x01(\x0DR\x0Copresulttype\x12\x1A\x0A\x08opretset\x18\x04 \x01(\x08R\x08opretset\x12\x1A\x0A\x08opcollid\x18\x05 \x01(\x0DR\x08opcollid\x12 \x0A\x0Binputcollid\x18\x06 \x01(\x0DR\x0Binputcollid\x12\"\x0A\x04args\x18\x07 \x03(\x0B2\x0E.pg_query.NodeR\x04args\x12\x1A\x0A\x08location\x18\x08 \x01(\x05R\x08location\"\x80\x02\x0A\x0ANullIfExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\x12\x0A\x04opno\x18\x02 \x01(\x0DR\x04opno\x12\"\x0A\x0Copresulttype\x18\x03 \x01(\x0DR\x0Copresulttype\x12\x1A\x0A\x08opretset\x18\x04 \x01(\x08R\x08opretset\x12\x1A\x0A\x08opcollid\x18\x05 \x01(\x0DR\x08opcollid\x12 \x0A\x0Binputcollid\x18\x06 \x01(\x0DR\x0Binputcollid\x12\"\x0A\x04args\x18\x07 \x03(\x0B2\x0E.pg_query.NodeR\x04args\x12\x1A\x0A\x08location\x18\x08 \x01(\x05R\x08location\"\xC2\x01\x0A\x11ScalarArrayOpExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\x12\x0A\x04opno\x18\x02 \x01(\x0DR\x04opno\x12\x15\x0A\x06use_or\x18\x03 \x01(\x08R\x05useOr\x12 \x0A\x0Binputcollid\x18\x04 \x01(\x0DR\x0Binputcollid\x12\"\x0A\x04args\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x04args\x12\x1A\x0A\x08location\x18\x06 \x01(\x05R\x08location\"\x9C\x01\x0A\x08BoolExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12.\x0A\x06boolop\x18\x02 \x01(\x0E2\x16.pg_query.BoolExprTypeR\x06boolop\x12\"\x0A\x04args\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x04args\x12\x1A\x0A\x08location\x18\x04 \x01(\x05R\x08location\"\xA9\x02\x0A\x07SubLink\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x129\x0A\x0Dsub_link_type\x18\x02 \x01(\x0E2\x15.pg_query.SubLinkTypeR\x0BsubLinkType\x12\x1E\x0A\x0Bsub_link_id\x18\x03 \x01(\x05R\x09subLinkId\x12*\x0A\x08testexpr\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x08testexpr\x12+\x0A\x09oper_name\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x08operName\x12,\x0A\x09subselect\x18\x06 \x01(\x0B2\x0E.pg_query.NodeR\x09subselect\x12\x1A\x0A\x08location\x18\x07 \x01(\x05R\x08location\"\xB5\x05\x0A\x07SubPlan\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x129\x0A\x0Dsub_link_type\x18\x02 \x01(\x0E2\x15.pg_query.SubLinkTypeR\x0BsubLinkType\x12*\x0A\x08testexpr\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x08testexpr\x12+\x0A\x09param_ids\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x08paramIds\x12\x18\x0A\x07plan_id\x18\x05 \x01(\x05R\x07plan_id\x12\x1C\x0A\x09plan_name\x18\x06 \x01(\x09R\x09plan_name\x12\$\x0A\x0Efirst_col_type\x18\x07 \x01(\x0DR\x0CfirstColType\x12(\x0A\x10first_col_typmod\x18\x08 \x01(\x05R\x0EfirstColTypmod\x12.\x0A\x13first_col_collation\x18\x09 \x01(\x0DR\x11firstColCollation\x12\$\x0A\x0Euse_hash_table\x18\x0A \x01(\x08R\x0CuseHashTable\x12(\x0A\x10unknown_eq_false\x18\x0B \x01(\x08R\x0EunknownEqFalse\x12\$\x0A\x0Dparallel_safe\x18\x0C \x01(\x08R\x0Dparallel_safe\x12+\x0A\x09set_param\x18\x0D \x03(\x0B2\x0E.pg_query.NodeR\x08setParam\x12+\x0A\x09par_param\x18\x0E \x03(\x0B2\x0E.pg_query.NodeR\x08parParam\x12\"\x0A\x04args\x18\x0F \x03(\x0B2\x0E.pg_query.NodeR\x04args\x12\"\x0A\x0Cstartup_cost\x18\x10 \x01(\x01R\x0Cstartup_cost\x12\$\x0A\x0Dper_call_cost\x18\x11 \x01(\x01R\x0Dper_call_cost\"b\x0A\x12AlternativeSubPlan\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12*\x0A\x08subplans\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x08subplans\"\xD5\x01\x0A\x0BFieldSelect\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12 \x0A\x03arg\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x03arg\x12\x1A\x0A\x08fieldnum\x18\x03 \x01(\x05R\x08fieldnum\x12\x1E\x0A\x0Aresulttype\x18\x04 \x01(\x0DR\x0Aresulttype\x12\"\x0A\x0Cresulttypmod\x18\x05 \x01(\x05R\x0Cresulttypmod\x12\"\x0A\x0Cresultcollid\x18\x06 \x01(\x0DR\x0Cresultcollid\"\xC8\x01\x0A\x0AFieldStore\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12 \x0A\x03arg\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x03arg\x12(\x0A\x07newvals\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x07newvals\x12,\x0A\x09fieldnums\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x09fieldnums\x12\x1E\x0A\x0Aresulttype\x18\x05 \x01(\x0DR\x0Aresulttype\"\x93\x02\x0A\x0BRelabelType\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12 \x0A\x03arg\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x03arg\x12\x1E\x0A\x0Aresulttype\x18\x03 \x01(\x0DR\x0Aresulttype\x12\"\x0A\x0Cresulttypmod\x18\x04 \x01(\x05R\x0Cresulttypmod\x12\"\x0A\x0Cresultcollid\x18\x05 \x01(\x0DR\x0Cresultcollid\x12<\x0A\x0Drelabelformat\x18\x06 \x01(\x0E2\x16.pg_query.CoercionFormR\x0Drelabelformat\x12\x1A\x0A\x08location\x18\x07 \x01(\x05R\x08location\"\xED\x01\x0A\x0BCoerceViaIO\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12 \x0A\x03arg\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x03arg\x12\x1E\x0A\x0Aresulttype\x18\x03 \x01(\x0DR\x0Aresulttype\x12\"\x0A\x0Cresultcollid\x18\x04 \x01(\x0DR\x0Cresultcollid\x12:\x0A\x0Ccoerceformat\x18\x05 \x01(\x0E2\x16.pg_query.CoercionFormR\x0Ccoerceformat\x12\x1A\x0A\x08location\x18\x06 \x01(\x05R\x08location\"\xC1\x02\x0A\x0FArrayCoerceExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12 \x0A\x03arg\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x03arg\x12*\x0A\x08elemexpr\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x08elemexpr\x12\x1E\x0A\x0Aresulttype\x18\x04 \x01(\x0DR\x0Aresulttype\x12\"\x0A\x0Cresulttypmod\x18\x05 \x01(\x05R\x0Cresulttypmod\x12\"\x0A\x0Cresultcollid\x18\x06 \x01(\x0DR\x0Cresultcollid\x12:\x0A\x0Ccoerceformat\x18\x07 \x01(\x0E2\x16.pg_query.CoercionFormR\x0Ccoerceformat\x12\x1A\x0A\x08location\x18\x08 \x01(\x05R\x08location\"\xD2\x01\x0A\x12ConvertRowtypeExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12 \x0A\x03arg\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x03arg\x12\x1E\x0A\x0Aresulttype\x18\x03 \x01(\x0DR\x0Aresulttype\x12<\x0A\x0Dconvertformat\x18\x04 \x01(\x0E2\x16.pg_query.CoercionFormR\x0Dconvertformat\x12\x1A\x0A\x08location\x18\x05 \x01(\x05R\x08location\"\x88\x01\x0A\x0BCollateExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12 \x0A\x03arg\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x03arg\x12\x19\x0A\x08coll_oid\x18\x03 \x01(\x0DR\x07collOid\x12\x1A\x0A\x08location\x18\x04 \x01(\x05R\x08location\"\xF8\x01\x0A\x08CaseExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\x1A\x0A\x08casetype\x18\x02 \x01(\x0DR\x08casetype\x12\x1E\x0A\x0Acasecollid\x18\x03 \x01(\x0DR\x0Acasecollid\x12 \x0A\x03arg\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x03arg\x12\"\x0A\x04args\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x04args\x12,\x0A\x09defresult\x18\x06 \x01(\x0B2\x0E.pg_query.NodeR\x09defresult\x12\x1A\x0A\x08location\x18\x07 \x01(\x05R\x08location\"\x94\x01\x0A\x08CaseWhen\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\"\x0A\x04expr\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x04expr\x12&\x0A\x06result\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x06result\x12\x1A\x0A\x08location\x18\x04 \x01(\x05R\x08location\"\x82\x01\x0A\x0CCaseTestExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\x17\x0A\x07type_id\x18\x02 \x01(\x0DR\x06typeId\x12\x19\x0A\x08type_mod\x18\x03 \x01(\x05R\x07typeMod\x12\x1C\x0A\x09collation\x18\x04 \x01(\x0DR\x09collation\"\x83\x02\x0A\x09ArrayExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\"\x0A\x0Carray_typeid\x18\x02 \x01(\x0DR\x0Carray_typeid\x12\"\x0A\x0Carray_collid\x18\x03 \x01(\x0DR\x0Carray_collid\x12&\x0A\x0Eelement_typeid\x18\x04 \x01(\x0DR\x0Eelement_typeid\x12*\x0A\x08elements\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x08elements\x12\x1C\x0A\x09multidims\x18\x06 \x01(\x08R\x09multidims\x12\x1A\x0A\x08location\x18\x07 \x01(\x05R\x08location\"\xEF\x01\x0A\x07RowExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\"\x0A\x04args\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x04args\x12\x1E\x0A\x0Arow_typeid\x18\x03 \x01(\x0DR\x0Arow_typeid\x126\x0A\x0Arow_format\x18\x04 \x01(\x0E2\x16.pg_query.CoercionFormR\x0Arow_format\x12*\x0A\x08colnames\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x08colnames\x12\x1A\x0A\x08location\x18\x06 \x01(\x05R\x08location\"\xBA\x02\x0A\x0ERowCompareExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x120\x0A\x06rctype\x18\x02 \x01(\x0E2\x18.pg_query.RowCompareTypeR\x06rctype\x12\$\x0A\x05opnos\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x05opnos\x12.\x0A\x0Aopfamilies\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x0Aopfamilies\x122\x0A\x0Cinputcollids\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x0Cinputcollids\x12\$\x0A\x05largs\x18\x06 \x03(\x0B2\x0E.pg_query.NodeR\x05largs\x12\$\x0A\x05rargs\x18\x07 \x03(\x0B2\x0E.pg_query.NodeR\x05rargs\"\xBC\x01\x0A\x0CCoalesceExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\"\x0A\x0Ccoalescetype\x18\x02 \x01(\x0DR\x0Ccoalescetype\x12&\x0A\x0Ecoalescecollid\x18\x03 \x01(\x0DR\x0Ecoalescecollid\x12\"\x0A\x04args\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x04args\x12\x1A\x0A\x08location\x18\x05 \x01(\x05R\x08location\"\xF8\x01\x0A\x0AMinMaxExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\x1E\x0A\x0Aminmaxtype\x18\x02 \x01(\x0DR\x0Aminmaxtype\x12\"\x0A\x0Cminmaxcollid\x18\x03 \x01(\x0DR\x0Cminmaxcollid\x12 \x0A\x0Binputcollid\x18\x04 \x01(\x0DR\x0Binputcollid\x12\"\x0A\x02op\x18\x05 \x01(\x0E2\x12.pg_query.MinMaxOpR\x02op\x12\"\x0A\x04args\x18\x06 \x03(\x0B2\x0E.pg_query.NodeR\x04args\x12\x1A\x0A\x08location\x18\x07 \x01(\x05R\x08location\"\xAA\x01\x0A\x10SQLValueFunction\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12,\x0A\x02op\x18\x02 \x01(\x0E2\x1C.pg_query.SQLValueFunctionOpR\x02op\x12\x12\x0A\x04type\x18\x03 \x01(\x0DR\x04type\x12\x16\x0A\x06typmod\x18\x04 \x01(\x05R\x06typmod\x12\x1A\x0A\x08location\x18\x05 \x01(\x05R\x08location\"\xFD\x02\x0A\x07XmlExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12#\x0A\x02op\x18\x02 \x01(\x0E2\x13.pg_query.XmlExprOpR\x02op\x12\x12\x0A\x04name\x18\x03 \x01(\x09R\x04name\x12.\x0A\x0Anamed_args\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x0Anamed_args\x12,\x0A\x09arg_names\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x09arg_names\x12\"\x0A\x04args\x18\x06 \x03(\x0B2\x0E.pg_query.NodeR\x04args\x125\x0A\x09xmloption\x18\x07 \x01(\x0E2\x17.pg_query.XmlOptionTypeR\x09xmloption\x12\x16\x0A\x06indent\x18\x08 \x01(\x08R\x06indent\x12\x12\x0A\x04type\x18\x09 \x01(\x0DR\x04type\x12\x16\x0A\x06typmod\x18\x0A \x01(\x05R\x06typmod\x12\x1A\x0A\x08location\x18\x0B \x01(\x05R\x08location\"\x98\x01\x0A\x0AJsonFormat\x12:\x0A\x0Bformat_type\x18\x01 \x01(\x0E2\x18.pg_query.JsonFormatTypeR\x0Bformat_type\x122\x0A\x08encoding\x18\x02 \x01(\x0E2\x16.pg_query.JsonEncodingR\x08encoding\x12\x1A\x0A\x08location\x18\x03 \x01(\x05R\x08location\"k\x0A\x0DJsonReturning\x12,\x0A\x06format\x18\x01 \x01(\x0B2\x14.pg_query.JsonFormatR\x06format\x12\x14\x0A\x05typid\x18\x02 \x01(\x0DR\x05typid\x12\x16\x0A\x06typmod\x18\x03 \x01(\x05R\x06typmod\"\xA1\x01\x0A\x0DJsonValueExpr\x12*\x0A\x08raw_expr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x08raw_expr\x126\x0A\x0Eformatted_expr\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x0Eformatted_expr\x12,\x0A\x06format\x18\x03 \x01(\x0B2\x14.pg_query.JsonFormatR\x06format\"\xF1\x02\x0A\x13JsonConstructorExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x121\x0A\x04type\x18\x02 \x01(\x0E2\x1D.pg_query.JsonConstructorTypeR\x04type\x12\"\x0A\x04args\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x04args\x12\"\x0A\x04func\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x04func\x12*\x0A\x08coercion\x18\x05 \x01(\x0B2\x0E.pg_query.NodeR\x08coercion\x125\x0A\x09returning\x18\x06 \x01(\x0B2\x17.pg_query.JsonReturningR\x09returning\x12&\x0A\x0Eabsent_on_null\x18\x07 \x01(\x08R\x0Eabsent_on_null\x12\x16\x0A\x06unique\x18\x08 \x01(\x08R\x06unique\x12\x1A\x0A\x08location\x18\x09 \x01(\x05R\x08location\"\xD8\x01\x0A\x0FJsonIsPredicate\x12\"\x0A\x04expr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x04expr\x12,\x0A\x06format\x18\x02 \x01(\x0B2\x14.pg_query.JsonFormatR\x06format\x125\x0A\x09item_type\x18\x03 \x01(\x0E2\x17.pg_query.JsonValueTypeR\x09item_type\x12 \x0A\x0Bunique_keys\x18\x04 \x01(\x08R\x0Bunique_keys\x12\x1A\x0A\x08location\x18\x05 \x01(\x05R\x08location\"\x98\x01\x0A\x0CJsonBehavior\x120\x0A\x05btype\x18\x01 \x01(\x0E2\x1A.pg_query.JsonBehaviorTypeR\x05btype\x12\"\x0A\x04expr\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x04expr\x12\x16\x0A\x06coerce\x18\x03 \x01(\x08R\x06coerce\x12\x1A\x0A\x08location\x18\x04 \x01(\x05R\x08location\"\xFA\x05\x0A\x08JsonExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\$\x0A\x02op\x18\x02 \x01(\x0E2\x14.pg_query.JsonExprOpR\x02op\x12 \x0A\x0Bcolumn_name\x18\x03 \x01(\x09R\x0Bcolumn_name\x126\x0A\x0Eformatted_expr\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x0Eformatted_expr\x12,\x0A\x06format\x18\x05 \x01(\x0B2\x14.pg_query.JsonFormatR\x06format\x12,\x0A\x09path_spec\x18\x06 \x01(\x0B2\x0E.pg_query.NodeR\x09path_spec\x125\x0A\x09returning\x18\x07 \x01(\x0B2\x17.pg_query.JsonReturningR\x09returning\x124\x0A\x0Dpassing_names\x18\x08 \x03(\x0B2\x0E.pg_query.NodeR\x0Dpassing_names\x126\x0A\x0Epassing_values\x18\x09 \x03(\x0B2\x0E.pg_query.NodeR\x0Epassing_values\x122\x0A\x08on_empty\x18\x0A \x01(\x0B2\x16.pg_query.JsonBehaviorR\x08on_empty\x122\x0A\x08on_error\x18\x0B \x01(\x0B2\x16.pg_query.JsonBehaviorR\x08on_error\x12(\x0A\x0Fuse_io_coercion\x18\x0C \x01(\x08R\x0Fuse_io_coercion\x12,\x0A\x11use_json_coercion\x18\x0D \x01(\x08R\x11use_json_coercion\x12/\x0A\x07wrapper\x18\x0E \x01(\x0E2\x15.pg_query.JsonWrapperR\x07wrapper\x12 \x0A\x0Bomit_quotes\x18\x0F \x01(\x08R\x0Bomit_quotes\x12\x1C\x0A\x09collation\x18\x10 \x01(\x0DR\x09collation\x12\x1A\x0A\x08location\x18\x11 \x01(\x05R\x08location\"#\x0A\x0DJsonTablePath\x12\x12\x0A\x04name\x18\x01 \x01(\x09R\x04name\"\xE2\x01\x0A\x11JsonTablePathScan\x12\"\x0A\x04plan\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x04plan\x12+\x0A\x04path\x18\x02 \x01(\x0B2\x17.pg_query.JsonTablePathR\x04path\x12\$\x0A\x0Eerror_on_error\x18\x03 \x01(\x08R\x0CerrorOnError\x12\$\x0A\x05child\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x05child\x12\x17\x0A\x07col_min\x18\x05 \x01(\x05R\x06colMin\x12\x17\x0A\x07col_max\x18\x06 \x01(\x05R\x06colMax\"\x86\x01\x0A\x14JsonTableSiblingJoin\x12\"\x0A\x04plan\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x04plan\x12\$\x0A\x05lplan\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x05lplan\x12\$\x0A\x05rplan\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x05rplan\"\xC2\x01\x0A\x08NullTest\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12 \x0A\x03arg\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x03arg\x12:\x0A\x0Cnulltesttype\x18\x03 \x01(\x0E2\x16.pg_query.NullTestTypeR\x0Cnulltesttype\x12\x1A\x0A\x08argisrow\x18\x04 \x01(\x08R\x08argisrow\x12\x1A\x0A\x08location\x18\x05 \x01(\x05R\x08location\"\xA9\x01\x0A\x0BBooleanTest\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12 \x0A\x03arg\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x03arg\x12:\x0A\x0Cbooltesttype\x18\x03 \x01(\x0E2\x16.pg_query.BoolTestTypeR\x0Cbooltesttype\x12\x1A\x0A\x08location\x18\x04 \x01(\x05R\x08location\"\xBC\x02\x0A\x0BMergeAction\x127\x0A\x0Amatch_kind\x18\x01 \x01(\x0E2\x18.pg_query.MergeMatchKindR\x09matchKind\x124\x0A\x0Ccommand_type\x18\x02 \x01(\x0E2\x11.pg_query.CmdTypeR\x0BcommandType\x124\x0A\x08override\x18\x03 \x01(\x0E2\x18.pg_query.OverridingKindR\x08override\x12\"\x0A\x04qual\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x04qual\x12/\x0A\x0Btarget_list\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x0AtargetList\x123\x0A\x0Dupdate_colnos\x18\x06 \x03(\x0B2\x0E.pg_query.NodeR\x0CupdateColnos\"\x98\x02\x0A\x0ECoerceToDomain\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12 \x0A\x03arg\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x03arg\x12\x1E\x0A\x0Aresulttype\x18\x03 \x01(\x0DR\x0Aresulttype\x12\"\x0A\x0Cresulttypmod\x18\x04 \x01(\x05R\x0Cresulttypmod\x12\"\x0A\x0Cresultcollid\x18\x05 \x01(\x0DR\x0Cresultcollid\x12>\x0A\x0Ecoercionformat\x18\x06 \x01(\x0E2\x16.pg_query.CoercionFormR\x0Ecoercionformat\x12\x1A\x0A\x08location\x18\x07 \x01(\x05R\x08location\"\xA5\x01\x0A\x13CoerceToDomainValue\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\x17\x0A\x07type_id\x18\x02 \x01(\x0DR\x06typeId\x12\x19\x0A\x08type_mod\x18\x03 \x01(\x05R\x07typeMod\x12\x1C\x0A\x09collation\x18\x04 \x01(\x0DR\x09collation\x12\x1A\x0A\x08location\x18\x05 \x01(\x05R\x08location\"\x9E\x01\x0A\x0CSetToDefault\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\x17\x0A\x07type_id\x18\x02 \x01(\x0DR\x06typeId\x12\x19\x0A\x08type_mod\x18\x03 \x01(\x05R\x07typeMod\x12\x1C\x0A\x09collation\x18\x04 \x01(\x0DR\x09collation\x12\x1A\x0A\x08location\x18\x05 \x01(\x05R\x08location\"\x8F\x01\x0A\x0DCurrentOfExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\x16\x0A\x06cvarno\x18\x02 \x01(\x0DR\x06cvarno\x12 \x0A\x0Bcursor_name\x18\x03 \x01(\x09R\x0Bcursor_name\x12\"\x0A\x0Ccursor_param\x18\x04 \x01(\x05R\x0Ccursor_param\"`\x0A\x0DNextValueExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\x14\x0A\x05seqid\x18\x02 \x01(\x0DR\x05seqid\x12\x17\x0A\x07type_id\x18\x03 \x01(\x0DR\x06typeId\"\x9B\x01\x0A\x0DInferenceElem\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\"\x0A\x04expr\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x04expr\x12 \x0A\x0Binfercollid\x18\x03 \x01(\x0DR\x0Binfercollid\x12\"\x0A\x0Cinferopclass\x18\x04 \x01(\x0DR\x0Cinferopclass\"\x87\x02\x0A\x0BTargetEntry\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\"\x0A\x04expr\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x04expr\x12\x14\x0A\x05resno\x18\x03 \x01(\x05R\x05resno\x12\x18\x0A\x07resname\x18\x04 \x01(\x09R\x07resname\x12(\x0A\x0Fressortgroupref\x18\x05 \x01(\x0DR\x0Fressortgroupref\x12\x1E\x0A\x0Aresorigtbl\x18\x06 \x01(\x0DR\x0Aresorigtbl\x12\x1E\x0A\x0Aresorigcol\x18\x07 \x01(\x05R\x0Aresorigcol\x12\x18\x0A\x07resjunk\x18\x08 \x01(\x08R\x07resjunk\"'\x0A\x0BRangeTblRef\x12\x18\x0A\x07rtindex\x18\x01 \x01(\x05R\x07rtindex\"\xF8\x02\x0A\x08JoinExpr\x12.\x0A\x08jointype\x18\x01 \x01(\x0E2\x12.pg_query.JoinTypeR\x08jointype\x12\x1D\x0A\x0Ais_natural\x18\x02 \x01(\x08R\x09isNatural\x12\"\x0A\x04larg\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x04larg\x12\"\x0A\x04rarg\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x04rarg\x121\x0A\x0Cusing_clause\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x0BusingClause\x12;\x0A\x10join_using_alias\x18\x06 \x01(\x0B2\x0F.pg_query.AliasR\x10join_using_alias\x12\$\x0A\x05quals\x18\x07 \x01(\x0B2\x0E.pg_query.NodeR\x05quals\x12%\x0A\x05alias\x18\x08 \x01(\x0B2\x0F.pg_query.AliasR\x05alias\x12\x18\x0A\x07rtindex\x18\x09 \x01(\x05R\x07rtindex\"\\\x0A\x08FromExpr\x12*\x0A\x08fromlist\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x08fromlist\x12\$\x0A\x05quals\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x05quals\"\x9E\x03\x0A\x0EOnConflictExpr\x122\x0A\x06action\x18\x01 \x01(\x0E2\x1A.pg_query.OnConflictActionR\x06action\x123\x0A\x0Darbiter_elems\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x0CarbiterElems\x123\x0A\x0Darbiter_where\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x0CarbiterWhere\x12\x1E\x0A\x0Aconstraint\x18\x04 \x01(\x0DR\x0Aconstraint\x126\x0A\x0Fon_conflict_set\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x0DonConflictSet\x12:\x0A\x11on_conflict_where\x18\x06 \x01(\x0B2\x0E.pg_query.NodeR\x0FonConflictWhere\x12\$\x0A\x0Eexcl_rel_index\x18\x07 \x01(\x05R\x0CexclRelIndex\x124\x0A\x0Eexcl_rel_tlist\x18\x08 \x03(\x0B2\x0E.pg_query.NodeR\x0CexclRelTlist\"\xC6\x0F\x0A\x05Query\x124\x0A\x0Ccommand_type\x18\x01 \x01(\x0E2\x11.pg_query.CmdTypeR\x0BcommandType\x128\x0A\x0Cquery_source\x18\x02 \x01(\x0E2\x15.pg_query.QuerySourceR\x0BquerySource\x12\x1E\x0A\x0Bcan_set_tag\x18\x03 \x01(\x08R\x09canSetTag\x121\x0A\x0Cutility_stmt\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x0ButilityStmt\x12'\x0A\x0Fresult_relation\x18\x05 \x01(\x05R\x0EresultRelation\x12\x19\x0A\x08has_aggs\x18\x06 \x01(\x08R\x07hasAggs\x12(\x0A\x10has_window_funcs\x18\x07 \x01(\x08R\x0EhasWindowFuncs\x12&\x0A\x0Fhas_target_srfs\x18\x08 \x01(\x08R\x0DhasTargetSRFs\x12\"\x0A\x0Dhas_sub_links\x18\x09 \x01(\x08R\x0BhasSubLinks\x12&\x0A\x0Fhas_distinct_on\x18\x0A \x01(\x08R\x0DhasDistinctOn\x12#\x0A\x0Dhas_recursive\x18\x0B \x01(\x08R\x0ChasRecursive\x12*\x0A\x11has_modifying_cte\x18\x0C \x01(\x08R\x0FhasModifyingCTE\x12\$\x0A\x0Ehas_for_update\x18\x0D \x01(\x08R\x0ChasForUpdate\x12(\x0A\x10has_row_security\x18\x0E \x01(\x08R\x0EhasRowSecurity\x12\x1B\x0A\x09is_return\x18\x0F \x01(\x08R\x08isReturn\x12)\x0A\x08cte_list\x18\x10 \x03(\x0B2\x0E.pg_query.NodeR\x07cteList\x12&\x0A\x06rtable\x18\x11 \x03(\x0B2\x0E.pg_query.NodeR\x06rtable\x122\x0A\x0Crteperminfos\x18\x12 \x03(\x0B2\x0E.pg_query.NodeR\x0Crteperminfos\x12.\x0A\x08jointree\x18\x13 \x01(\x0B2\x12.pg_query.FromExprR\x08jointree\x12:\x0A\x11merge_action_list\x18\x14 \x03(\x0B2\x0E.pg_query.NodeR\x0FmergeActionList\x122\x0A\x15merge_target_relation\x18\x15 \x01(\x05R\x13mergeTargetRelation\x12@\x0A\x14merge_join_condition\x18\x16 \x01(\x0B2\x0E.pg_query.NodeR\x12mergeJoinCondition\x12/\x0A\x0Btarget_list\x18\x17 \x03(\x0B2\x0E.pg_query.NodeR\x0AtargetList\x124\x0A\x08override\x18\x18 \x01(\x0E2\x18.pg_query.OverridingKindR\x08override\x129\x0A\x0Bon_conflict\x18\x19 \x01(\x0B2\x18.pg_query.OnConflictExprR\x0AonConflict\x125\x0A\x0Ereturning_list\x18\x1A \x03(\x0B2\x0E.pg_query.NodeR\x0DreturningList\x121\x0A\x0Cgroup_clause\x18\x1B \x03(\x0B2\x0E.pg_query.NodeR\x0BgroupClause\x12%\x0A\x0Egroup_distinct\x18\x1C \x01(\x08R\x0DgroupDistinct\x123\x0A\x0Dgrouping_sets\x18\x1D \x03(\x0B2\x0E.pg_query.NodeR\x0CgroupingSets\x12/\x0A\x0Bhaving_qual\x18\x1E \x01(\x0B2\x0E.pg_query.NodeR\x0AhavingQual\x123\x0A\x0Dwindow_clause\x18\x1F \x03(\x0B2\x0E.pg_query.NodeR\x0CwindowClause\x127\x0A\x0Fdistinct_clause\x18 \x03(\x0B2\x0E.pg_query.NodeR\x0EdistinctClause\x12/\x0A\x0Bsort_clause\x18! \x03(\x0B2\x0E.pg_query.NodeR\x0AsortClause\x121\x0A\x0Climit_offset\x18\" \x01(\x0B2\x0E.pg_query.NodeR\x0BlimitOffset\x12/\x0A\x0Blimit_count\x18# \x01(\x0B2\x0E.pg_query.NodeR\x0AlimitCount\x128\x0A\x0Climit_option\x18\$ \x01(\x0E2\x15.pg_query.LimitOptionR\x0BlimitOption\x12+\x0A\x09row_marks\x18% \x03(\x0B2\x0E.pg_query.NodeR\x08rowMarks\x125\x0A\x0Eset_operations\x18& \x01(\x0B2\x0E.pg_query.NodeR\x0DsetOperations\x127\x0A\x0Fconstraint_deps\x18' \x03(\x0B2\x0E.pg_query.NodeR\x0EconstraintDeps\x12<\x0A\x12with_check_options\x18( \x03(\x0B2\x0E.pg_query.NodeR\x10withCheckOptions\x12\$\x0A\x0Dstmt_location\x18) \x01(\x05R\x0Dstmt_location\x12\x1A\x0A\x08stmt_len\x18* \x01(\x05R\x08stmt_len\"\x90\x02\x0A\x08TypeName\x12\$\x0A\x05names\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x05names\x12\x19\x0A\x08type_oid\x18\x02 \x01(\x0DR\x07typeOid\x12\x14\x0A\x05setof\x18\x03 \x01(\x08R\x05setof\x12\x1A\x0A\x08pct_type\x18\x04 \x01(\x08R\x08pct_type\x12(\x0A\x07typmods\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x07typmods\x12\x18\x0A\x07typemod\x18\x06 \x01(\x05R\x07typemod\x121\x0A\x0Carray_bounds\x18\x07 \x03(\x0B2\x0E.pg_query.NodeR\x0BarrayBounds\x12\x1A\x0A\x08location\x18\x08 \x01(\x05R\x08location\"O\x0A\x09ColumnRef\x12&\x0A\x06fields\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x06fields\x12\x1A\x0A\x08location\x18\x02 \x01(\x05R\x08location\">\x0A\x08ParamRef\x12\x16\x0A\x06number\x18\x01 \x01(\x05R\x06number\x12\x1A\x0A\x08location\x18\x02 \x01(\x05R\x08location\"\xBF\x01\x0A\x06A_Expr\x12)\x0A\x04kind\x18\x01 \x01(\x0E2\x15.pg_query.A_Expr_KindR\x04kind\x12\"\x0A\x04name\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x04name\x12\$\x0A\x05lexpr\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x05lexpr\x12\$\x0A\x05rexpr\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x05rexpr\x12\x1A\x0A\x08location\x18\x05 \x01(\x05R\x08location\"y\x0A\x08TypeCast\x12 \x0A\x03arg\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03arg\x12/\x0A\x09type_name\x18\x02 \x01(\x0B2\x12.pg_query.TypeNameR\x08typeName\x12\x1A\x0A\x08location\x18\x03 \x01(\x05R\x08location\"y\x0A\x0DCollateClause\x12 \x0A\x03arg\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03arg\x12*\x0A\x08collname\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x08collname\x12\x1A\x0A\x08location\x18\x03 \x01(\x05R\x08location\"v\x0A\x08RoleSpec\x122\x0A\x08roletype\x18\x01 \x01(\x0E2\x16.pg_query.RoleSpecTypeR\x08roletype\x12\x1A\x0A\x08rolename\x18\x02 \x01(\x09R\x08rolename\x12\x1A\x0A\x08location\x18\x03 \x01(\x05R\x08location\"\xC7\x03\x0A\x08FuncCall\x12*\x0A\x08funcname\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x08funcname\x12\"\x0A\x04args\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x04args\x12,\x0A\x09agg_order\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x09agg_order\x12.\x0A\x0Aagg_filter\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x0Aagg_filter\x12'\x0A\x04over\x18\x05 \x01(\x0B2\x13.pg_query.WindowDefR\x04over\x12*\x0A\x10agg_within_group\x18\x06 \x01(\x08R\x10agg_within_group\x12\x1A\x0A\x08agg_star\x18\x07 \x01(\x08R\x08agg_star\x12\"\x0A\x0Cagg_distinct\x18\x08 \x01(\x08R\x0Cagg_distinct\x12\$\x0A\x0Dfunc_variadic\x18\x09 \x01(\x08R\x0Dfunc_variadic\x126\x0A\x0Afuncformat\x18\x0A \x01(\x0E2\x16.pg_query.CoercionFormR\x0Afuncformat\x12\x1A\x0A\x08location\x18\x0B \x01(\x05R\x08location\"\x08\x0A\x06A_Star\"o\x0A\x09A_Indices\x12\x1A\x0A\x08is_slice\x18\x01 \x01(\x08R\x08is_slice\x12\"\x0A\x04lidx\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x04lidx\x12\"\x0A\x04uidx\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x04uidx\"c\x0A\x0DA_Indirection\x12 \x0A\x03arg\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03arg\x120\x0A\x0Bindirection\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x0Bindirection\"U\x0A\x0BA_ArrayExpr\x12*\x0A\x08elements\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x08elements\x12\x1A\x0A\x08location\x18\x02 \x01(\x05R\x08location\"\x8F\x01\x0A\x09ResTarget\x12\x12\x0A\x04name\x18\x01 \x01(\x09R\x04name\x120\x0A\x0Bindirection\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x0Bindirection\x12 \x0A\x03val\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x03val\x12\x1A\x0A\x08location\x18\x04 \x01(\x05R\x08location\"j\x0A\x0EMultiAssignRef\x12&\x0A\x06source\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x06source\x12\x14\x0A\x05colno\x18\x02 \x01(\x05R\x05colno\x12\x1A\x0A\x08ncolumns\x18\x03 \x01(\x05R\x08ncolumns\"\xDF\x01\x0A\x06SortBy\x12\"\x0A\x04node\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x04node\x123\x0A\x0Asortby_dir\x18\x02 \x01(\x0E2\x13.pg_query.SortByDirR\x0Asortby_dir\x129\x0A\x0Csortby_nulls\x18\x03 \x01(\x0E2\x15.pg_query.SortByNullsR\x0Csortby_nulls\x12%\x0A\x06use_op\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x05useOp\x12\x1A\x0A\x08location\x18\x05 \x01(\x05R\x08location\"\xCA\x02\x0A\x09WindowDef\x12\x12\x0A\x04name\x18\x01 \x01(\x09R\x04name\x12\x18\x0A\x07refname\x18\x02 \x01(\x09R\x07refname\x129\x0A\x10partition_clause\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x0FpartitionClause\x121\x0A\x0Corder_clause\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x0BorderClause\x12#\x0A\x0Dframe_options\x18\x05 \x01(\x05R\x0CframeOptions\x121\x0A\x0Cstart_offset\x18\x06 \x01(\x0B2\x0E.pg_query.NodeR\x0BstartOffset\x12-\x0A\x0Aend_offset\x18\x07 \x01(\x0B2\x0E.pg_query.NodeR\x09endOffset\x12\x1A\x0A\x08location\x18\x08 \x01(\x05R\x08location\"}\x0A\x0ERangeSubselect\x12\x18\x0A\x07lateral\x18\x01 \x01(\x08R\x07lateral\x12*\x0A\x08subquery\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x08subquery\x12%\x0A\x05alias\x18\x03 \x01(\x0B2\x0F.pg_query.AliasR\x05alias\"\xF0\x01\x0A\x0DRangeFunction\x12\x18\x0A\x07lateral\x18\x01 \x01(\x08R\x07lateral\x12\x1E\x0A\x0Aordinality\x18\x02 \x01(\x08R\x0Aordinality\x12 \x0A\x0Bis_rowsfrom\x18\x03 \x01(\x08R\x0Bis_rowsfrom\x12,\x0A\x09functions\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x09functions\x12%\x0A\x05alias\x18\x05 \x01(\x0B2\x0F.pg_query.AliasR\x05alias\x12.\x0A\x0Acoldeflist\x18\x06 \x03(\x0B2\x0E.pg_query.NodeR\x0Acoldeflist\"\x9B\x02\x0A\x0ERangeTableFunc\x12\x18\x0A\x07lateral\x18\x01 \x01(\x08R\x07lateral\x12(\x0A\x07docexpr\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x07docexpr\x12(\x0A\x07rowexpr\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x07rowexpr\x12.\x0A\x0Anamespaces\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x0Anamespaces\x12(\x0A\x07columns\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x07columns\x12%\x0A\x05alias\x18\x06 \x01(\x0B2\x0F.pg_query.AliasR\x05alias\x12\x1A\x0A\x08location\x18\x07 \x01(\x05R\x08location\"\x9E\x02\x0A\x11RangeTableFuncCol\x12\x18\x0A\x07colname\x18\x01 \x01(\x09R\x07colname\x12/\x0A\x09type_name\x18\x02 \x01(\x0B2\x12.pg_query.TypeNameR\x08typeName\x12&\x0A\x0Efor_ordinality\x18\x03 \x01(\x08R\x0Efor_ordinality\x12 \x0A\x0Bis_not_null\x18\x04 \x01(\x08R\x0Bis_not_null\x12(\x0A\x07colexpr\x18\x05 \x01(\x0B2\x0E.pg_query.NodeR\x07colexpr\x12.\x0A\x0Acoldefexpr\x18\x06 \x01(\x0B2\x0E.pg_query.NodeR\x0Acoldefexpr\x12\x1A\x0A\x08location\x18\x07 \x01(\x05R\x08location\"\xD6\x01\x0A\x10RangeTableSample\x12*\x0A\x08relation\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x08relation\x12&\x0A\x06method\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x06method\x12\"\x0A\x04args\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x04args\x12.\x0A\x0Arepeatable\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x0Arepeatable\x12\x1A\x0A\x08location\x18\x05 \x01(\x05R\x08location\"\xEC\x05\x0A\x09ColumnDef\x12\x18\x0A\x07colname\x18\x01 \x01(\x09R\x07colname\x12/\x0A\x09type_name\x18\x02 \x01(\x0B2\x12.pg_query.TypeNameR\x08typeName\x12 \x0A\x0Bcompression\x18\x03 \x01(\x09R\x0Bcompression\x12\x1A\x0A\x08inhcount\x18\x04 \x01(\x05R\x08inhcount\x12\x1A\x0A\x08is_local\x18\x05 \x01(\x08R\x08is_local\x12 \x0A\x0Bis_not_null\x18\x06 \x01(\x08R\x0Bis_not_null\x12\"\x0A\x0Cis_from_type\x18\x07 \x01(\x08R\x0Cis_from_type\x12\x18\x0A\x07storage\x18\x08 \x01(\x09R\x07storage\x12\"\x0A\x0Cstorage_name\x18\x09 \x01(\x09R\x0Cstorage_name\x120\x0A\x0Braw_default\x18\x0A \x01(\x0B2\x0E.pg_query.NodeR\x0Braw_default\x126\x0A\x0Ecooked_default\x18\x0B \x01(\x0B2\x0E.pg_query.NodeR\x0Ecooked_default\x12\x1A\x0A\x08identity\x18\x0C \x01(\x09R\x08identity\x12?\x0A\x11identity_sequence\x18\x0D \x01(\x0B2\x12.pg_query.RangeVarR\x10identitySequence\x12\x1C\x0A\x09generated\x18\x0E \x01(\x09R\x09generated\x128\x0A\x0Bcoll_clause\x18\x0F \x01(\x0B2\x17.pg_query.CollateClauseR\x0AcollClause\x12\x19\x0A\x08coll_oid\x18\x10 \x01(\x0DR\x07collOid\x120\x0A\x0Bconstraints\x18\x11 \x03(\x0B2\x0E.pg_query.NodeR\x0Bconstraints\x12.\x0A\x0Afdwoptions\x18\x12 \x03(\x0B2\x0E.pg_query.NodeR\x0Afdwoptions\x12\x1A\x0A\x08location\x18\x13 \x01(\x05R\x08location\"~\x0A\x0FTableLikeClause\x12.\x0A\x08relation\x18\x01 \x01(\x0B2\x12.pg_query.RangeVarR\x08relation\x12\x18\x0A\x07options\x18\x02 \x01(\x0DR\x07options\x12!\x0A\x0Crelation_oid\x18\x03 \x01(\x0DR\x0BrelationOid\"\xE1\x02\x0A\x09IndexElem\x12\x12\x0A\x04name\x18\x01 \x01(\x09R\x04name\x12\"\x0A\x04expr\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x04expr\x12\"\x0A\x0Cindexcolname\x18\x03 \x01(\x09R\x0Cindexcolname\x12,\x0A\x09collation\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x09collation\x12(\x0A\x07opclass\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x07opclass\x120\x0A\x0Bopclassopts\x18\x06 \x03(\x0B2\x0E.pg_query.NodeR\x0Bopclassopts\x12/\x0A\x08ordering\x18\x07 \x01(\x0E2\x13.pg_query.SortByDirR\x08ordering\x12=\x0A\x0Enulls_ordering\x18\x08 \x01(\x0E2\x15.pg_query.SortByNullsR\x0Enulls_ordering\"\xBC\x01\x0A\x07DefElem\x12\"\x0A\x0Cdefnamespace\x18\x01 \x01(\x09R\x0Cdefnamespace\x12\x18\x0A\x07defname\x18\x02 \x01(\x09R\x07defname\x12 \x0A\x03arg\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x03arg\x125\x0A\x09defaction\x18\x04 \x01(\x0E2\x17.pg_query.DefElemActionR\x09defaction\x12\x1A\x0A\x08location\x18\x05 \x01(\x05R\x08location\"\xB5\x01\x0A\x0DLockingClause\x12/\x0A\x0Blocked_rels\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x0AlockedRels\x128\x0A\x08strength\x18\x02 \x01(\x0E2\x1C.pg_query.LockClauseStrengthR\x08strength\x129\x0A\x0Bwait_policy\x18\x03 \x01(\x0E2\x18.pg_query.LockWaitPolicyR\x0AwaitPolicy\"\xCE\x01\x0A\x0CXmlSerialize\x125\x0A\x09xmloption\x18\x01 \x01(\x0E2\x17.pg_query.XmlOptionTypeR\x09xmloption\x12\"\x0A\x04expr\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x04expr\x12/\x0A\x09type_name\x18\x03 \x01(\x0B2\x12.pg_query.TypeNameR\x08typeName\x12\x16\x0A\x06indent\x18\x04 \x01(\x08R\x06indent\x12\x1A\x0A\x08location\x18\x05 \x01(\x05R\x08location\"\xBB\x01\x0A\x0DPartitionElem\x12\x12\x0A\x04name\x18\x01 \x01(\x09R\x04name\x12\"\x0A\x04expr\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x04expr\x12,\x0A\x09collation\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x09collation\x12(\x0A\x07opclass\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x07opclass\x12\x1A\x0A\x08location\x18\x05 \x01(\x05R\x08location\"\x95\x01\x0A\x0DPartitionSpec\x127\x0A\x08strategy\x18\x01 \x01(\x0E2\x1B.pg_query.PartitionStrategyR\x08strategy\x12/\x0A\x0Bpart_params\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x0ApartParams\x12\x1A\x0A\x08location\x18\x03 \x01(\x05R\x08location\"\xB8\x02\x0A\x12PartitionBoundSpec\x12\x1A\x0A\x08strategy\x18\x01 \x01(\x09R\x08strategy\x12\x1E\x0A\x0Ais_default\x18\x02 \x01(\x08R\x0Ais_default\x12\x18\x0A\x07modulus\x18\x03 \x01(\x05R\x07modulus\x12\x1C\x0A\x09remainder\x18\x04 \x01(\x05R\x09remainder\x12.\x0A\x0Alistdatums\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x0Alistdatums\x120\x0A\x0Blowerdatums\x18\x06 \x03(\x0B2\x0E.pg_query.NodeR\x0Blowerdatums\x120\x0A\x0Bupperdatums\x18\x07 \x03(\x0B2\x0E.pg_query.NodeR\x0Bupperdatums\x12\x1A\x0A\x08location\x18\x08 \x01(\x05R\x08location\"\x8E\x01\x0A\x13PartitionRangeDatum\x125\x0A\x04kind\x18\x01 \x01(\x0E2!.pg_query.PartitionRangeDatumKindR\x04kind\x12\$\x0A\x05value\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x05value\x12\x1A\x0A\x08location\x18\x03 \x01(\x05R\x08location\"\x15\x0A\x13SinglePartitionSpec\"\x8A\x01\x0A\x0CPartitionCmd\x12&\x0A\x04name\x18\x01 \x01(\x0B2\x12.pg_query.RangeVarR\x04name\x122\x0A\x05bound\x18\x02 \x01(\x0B2\x1C.pg_query.PartitionBoundSpecR\x05bound\x12\x1E\x0A\x0Aconcurrent\x18\x03 \x01(\x08R\x0Aconcurrent\"\xB9\x0A\x0A\x0DRangeTblEntry\x12%\x0A\x05alias\x18\x01 \x01(\x0B2\x0F.pg_query.AliasR\x05alias\x12#\x0A\x04eref\x18\x02 \x01(\x0B2\x0F.pg_query.AliasR\x04eref\x12+\x0A\x07rtekind\x18\x03 \x01(\x0E2\x11.pg_query.RTEKindR\x07rtekind\x12\x14\x0A\x05relid\x18\x04 \x01(\x0DR\x05relid\x12\x10\x0A\x03inh\x18\x05 \x01(\x08R\x03inh\x12\x18\x0A\x07relkind\x18\x06 \x01(\x09R\x07relkind\x12 \x0A\x0Brellockmode\x18\x07 \x01(\x05R\x0Brellockmode\x12\$\x0A\x0Dperminfoindex\x18\x08 \x01(\x0DR\x0Dperminfoindex\x12=\x0A\x0Btablesample\x18\x09 \x01(\x0B2\x1B.pg_query.TableSampleClauseR\x0Btablesample\x12+\x0A\x08subquery\x18\x0A \x01(\x0B2\x0F.pg_query.QueryR\x08subquery\x12*\x0A\x10security_barrier\x18\x0B \x01(\x08R\x10security_barrier\x12.\x0A\x08jointype\x18\x0C \x01(\x0E2\x12.pg_query.JoinTypeR\x08jointype\x12&\x0A\x0Ejoinmergedcols\x18\x0D \x01(\x05R\x0Ejoinmergedcols\x124\x0A\x0Djoinaliasvars\x18\x0E \x03(\x0B2\x0E.pg_query.NodeR\x0Djoinaliasvars\x122\x0A\x0Cjoinleftcols\x18\x0F \x03(\x0B2\x0E.pg_query.NodeR\x0Cjoinleftcols\x124\x0A\x0Djoinrightcols\x18\x10 \x03(\x0B2\x0E.pg_query.NodeR\x0Djoinrightcols\x12;\x0A\x10join_using_alias\x18\x11 \x01(\x0B2\x0F.pg_query.AliasR\x10join_using_alias\x12,\x0A\x09functions\x18\x12 \x03(\x0B2\x0E.pg_query.NodeR\x09functions\x12&\x0A\x0Efuncordinality\x18\x13 \x01(\x08R\x0Efuncordinality\x121\x0A\x09tablefunc\x18\x14 \x01(\x0B2\x13.pg_query.TableFuncR\x09tablefunc\x122\x0A\x0Cvalues_lists\x18\x15 \x03(\x0B2\x0E.pg_query.NodeR\x0Cvalues_lists\x12\x18\x0A\x07ctename\x18\x16 \x01(\x09R\x07ctename\x12 \x0A\x0Bctelevelsup\x18\x17 \x01(\x0DR\x0Bctelevelsup\x12&\x0A\x0Eself_reference\x18\x18 \x01(\x08R\x0Eself_reference\x12*\x0A\x08coltypes\x18\x19 \x03(\x0B2\x0E.pg_query.NodeR\x08coltypes\x12.\x0A\x0Acoltypmods\x18\x1A \x03(\x0B2\x0E.pg_query.NodeR\x0Acoltypmods\x124\x0A\x0Dcolcollations\x18\x1B \x03(\x0B2\x0E.pg_query.NodeR\x0Dcolcollations\x12\x18\x0A\x07enrname\x18\x1C \x01(\x09R\x07enrname\x12\x1C\x0A\x09enrtuples\x18\x1D \x01(\x01R\x09enrtuples\x12\x18\x0A\x07lateral\x18\x1E \x01(\x08R\x07lateral\x12\x1C\x0A\x0Ain_from_cl\x18\x1F \x01(\x08R\x08inFromCl\x125\x0A\x0Esecurity_quals\x18 \x03(\x0B2\x0E.pg_query.NodeR\x0DsecurityQuals\"\xF3\x01\x0A\x11RTEPermissionInfo\x12\x14\x0A\x05relid\x18\x01 \x01(\x0DR\x05relid\x12\x10\x0A\x03inh\x18\x02 \x01(\x08R\x03inh\x12%\x0A\x0Erequired_perms\x18\x03 \x01(\x04R\x0DrequiredPerms\x12\"\x0A\x0Dcheck_as_user\x18\x04 \x01(\x0DR\x0BcheckAsUser\x12#\x0A\x0Dselected_cols\x18\x05 \x03(\x04R\x0CselectedCols\x12#\x0A\x0Dinserted_cols\x18\x06 \x03(\x04R\x0CinsertedCols\x12!\x0A\x0Cupdated_cols\x18\x07 \x03(\x04R\x0BupdatedCols\"\xE0\x02\x0A\x10RangeTblFunction\x12*\x0A\x08funcexpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x08funcexpr\x12\"\x0A\x0Cfunccolcount\x18\x02 \x01(\x05R\x0Cfunccolcount\x122\x0A\x0Cfunccolnames\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x0Cfunccolnames\x122\x0A\x0Cfunccoltypes\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x0Cfunccoltypes\x126\x0A\x0Efunccoltypmods\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x0Efunccoltypmods\x12<\x0A\x11funccolcollations\x18\x06 \x03(\x0B2\x0E.pg_query.NodeR\x11funccolcollations\x12\x1E\x0A\x0Afuncparams\x18\x07 \x03(\x04R\x0Afuncparams\"\x87\x01\x0A\x11TableSampleClause\x12\x1E\x0A\x0Atsmhandler\x18\x01 \x01(\x0DR\x0Atsmhandler\x12\"\x0A\x04args\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x04args\x12.\x0A\x0Arepeatable\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x0Arepeatable\"\xAC\x01\x0A\x0FWithCheckOption\x12%\x0A\x04kind\x18\x01 \x01(\x0E2\x11.pg_query.WCOKindR\x04kind\x12\x18\x0A\x07relname\x18\x02 \x01(\x09R\x07relname\x12\x18\x0A\x07polname\x18\x03 \x01(\x09R\x07polname\x12\"\x0A\x04qual\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x04qual\x12\x1A\x0A\x08cascaded\x18\x05 \x01(\x08R\x08cascaded\"\xA8\x01\x0A\x0FSortGroupClause\x12+\x0A\x12tle_sort_group_ref\x18\x01 \x01(\x0DR\x0FtleSortGroupRef\x12\x12\x0A\x04eqop\x18\x02 \x01(\x0DR\x04eqop\x12\x16\x0A\x06sortop\x18\x03 \x01(\x0DR\x06sortop\x12 \x0A\x0Bnulls_first\x18\x04 \x01(\x08R\x0Bnulls_first\x12\x1A\x0A\x08hashable\x18\x05 \x01(\x08R\x08hashable\"\x82\x01\x0A\x0BGroupingSet\x12-\x0A\x04kind\x18\x01 \x01(\x0E2\x19.pg_query.GroupingSetKindR\x04kind\x12(\x0A\x07content\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x07content\x12\x1A\x0A\x08location\x18\x03 \x01(\x05R\x08location\"\xBD\x04\x0A\x0CWindowClause\x12\x12\x0A\x04name\x18\x01 \x01(\x09R\x04name\x12\x18\x0A\x07refname\x18\x02 \x01(\x09R\x07refname\x129\x0A\x10partition_clause\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x0FpartitionClause\x121\x0A\x0Corder_clause\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x0BorderClause\x12#\x0A\x0Dframe_options\x18\x05 \x01(\x05R\x0CframeOptions\x121\x0A\x0Cstart_offset\x18\x06 \x01(\x0B2\x0E.pg_query.NodeR\x0BstartOffset\x12-\x0A\x0Aend_offset\x18\x07 \x01(\x0B2\x0E.pg_query.NodeR\x09endOffset\x12-\x0A\x13start_in_range_func\x18\x08 \x01(\x0DR\x10startInRangeFunc\x12)\x0A\x11end_in_range_func\x18\x09 \x01(\x0DR\x0EendInRangeFunc\x12\"\x0A\x0Din_range_coll\x18\x0A \x01(\x0DR\x0BinRangeColl\x12 \x0A\x0Cin_range_asc\x18\x0B \x01(\x08R\x0AinRangeAsc\x12/\x0A\x14in_range_nulls_first\x18\x0C \x01(\x08R\x11inRangeNullsFirst\x12\x16\x0A\x06winref\x18\x0D \x01(\x0DR\x06winref\x12!\x0A\x0Ccopied_order\x18\x0E \x01(\x08R\x0BcopiedOrder\"\xB7\x01\x0A\x0DRowMarkClause\x12\x10\x0A\x03rti\x18\x01 \x01(\x0DR\x03rti\x128\x0A\x08strength\x18\x02 \x01(\x0E2\x1C.pg_query.LockClauseStrengthR\x08strength\x129\x0A\x0Bwait_policy\x18\x03 \x01(\x0E2\x18.pg_query.LockWaitPolicyR\x0AwaitPolicy\x12\x1F\x0A\x0Bpushed_down\x18\x04 \x01(\x08R\x0ApushedDown\"j\x0A\x0AWithClause\x12\"\x0A\x04ctes\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x04ctes\x12\x1C\x0A\x09recursive\x18\x02 \x01(\x08R\x09recursive\x12\x1A\x0A\x08location\x18\x03 \x01(\x05R\x08location\"\xA7\x01\x0A\x0BInferClause\x12/\x0A\x0Bindex_elems\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x0AindexElems\x121\x0A\x0Cwhere_clause\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x0BwhereClause\x12\x18\x0A\x07conname\x18\x03 \x01(\x09R\x07conname\x12\x1A\x0A\x08location\x18\x04 \x01(\x05R\x08location\"\xF3\x01\x0A\x10OnConflictClause\x122\x0A\x06action\x18\x01 \x01(\x0E2\x1A.pg_query.OnConflictActionR\x06action\x12+\x0A\x05infer\x18\x02 \x01(\x0B2\x15.pg_query.InferClauseR\x05infer\x12/\x0A\x0Btarget_list\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x0AtargetList\x121\x0A\x0Cwhere_clause\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x0BwhereClause\x12\x1A\x0A\x08location\x18\x05 \x01(\x05R\x08location\"\xC9\x01\x0A\x0FCTESearchClause\x128\x0A\x0Fsearch_col_list\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x0Fsearch_col_list\x122\x0A\x14search_breadth_first\x18\x02 \x01(\x08R\x14search_breadth_first\x12,\x0A\x11search_seq_column\x18\x03 \x01(\x09R\x11search_seq_column\x12\x1A\x0A\x08location\x18\x04 \x01(\x05R\x08location\"\xF2\x03\x0A\x0ECTECycleClause\x126\x0A\x0Ecycle_col_list\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x0Ecycle_col_list\x12,\x0A\x11cycle_mark_column\x18\x02 \x01(\x09R\x11cycle_mark_column\x12:\x0A\x10cycle_mark_value\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x10cycle_mark_value\x12>\x0A\x12cycle_mark_default\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x12cycle_mark_default\x12,\x0A\x11cycle_path_column\x18\x05 \x01(\x09R\x11cycle_path_column\x12\x1A\x0A\x08location\x18\x06 \x01(\x05R\x08location\x12(\x0A\x0Fcycle_mark_type\x18\x07 \x01(\x0DR\x0Fcycle_mark_type\x12,\x0A\x11cycle_mark_typmod\x18\x08 \x01(\x05R\x11cycle_mark_typmod\x122\x0A\x14cycle_mark_collation\x18\x09 \x01(\x0DR\x14cycle_mark_collation\x12(\x0A\x0Fcycle_mark_neop\x18\x0A \x01(\x0DR\x0Fcycle_mark_neop\"\x88\x05\x0A\x0FCommonTableExpr\x12\x18\x0A\x07ctename\x18\x01 \x01(\x09R\x07ctename\x124\x0A\x0Daliascolnames\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x0Daliascolnames\x12B\x0A\x0Fctematerialized\x18\x03 \x01(\x0E2\x18.pg_query.CTEMaterializeR\x0Fctematerialized\x12*\x0A\x08ctequery\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x08ctequery\x12?\x0A\x0Dsearch_clause\x18\x05 \x01(\x0B2\x19.pg_query.CTESearchClauseR\x0Dsearch_clause\x12<\x0A\x0Ccycle_clause\x18\x06 \x01(\x0B2\x18.pg_query.CTECycleClauseR\x0Ccycle_clause\x12\x1A\x0A\x08location\x18\x07 \x01(\x05R\x08location\x12\"\x0A\x0Ccterecursive\x18\x08 \x01(\x08R\x0Ccterecursive\x12 \x0A\x0Bcterefcount\x18\x09 \x01(\x05R\x0Bcterefcount\x120\x0A\x0Bctecolnames\x18\x0A \x03(\x0B2\x0E.pg_query.NodeR\x0Bctecolnames\x120\x0A\x0Bctecoltypes\x18\x0B \x03(\x0B2\x0E.pg_query.NodeR\x0Bctecoltypes\x124\x0A\x0Dctecoltypmods\x18\x0C \x03(\x0B2\x0E.pg_query.NodeR\x0Dctecoltypmods\x12:\x0A\x10ctecolcollations\x18\x0D \x03(\x0B2\x0E.pg_query.NodeR\x10ctecolcollations\"\xBD\x02\x0A\x0FMergeWhenClause\x127\x0A\x0Amatch_kind\x18\x01 \x01(\x0E2\x18.pg_query.MergeMatchKindR\x09matchKind\x124\x0A\x0Ccommand_type\x18\x02 \x01(\x0E2\x11.pg_query.CmdTypeR\x0BcommandType\x124\x0A\x08override\x18\x03 \x01(\x0E2\x18.pg_query.OverridingKindR\x08override\x12,\x0A\x09condition\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x09condition\x12/\x0A\x0Btarget_list\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x0AtargetList\x12&\x0A\x06values\x18\x06 \x03(\x0B2\x0E.pg_query.NodeR\x06values\"Y\x0A\x11TriggerTransition\x12\x12\x0A\x04name\x18\x01 \x01(\x09R\x04name\x12\x15\x0A\x06is_new\x18\x02 \x01(\x08R\x05isNew\x12\x19\x0A\x08is_table\x18\x03 \x01(\x08R\x07isTable\"t\x0A\x0AJsonOutput\x12/\x0A\x09type_name\x18\x01 \x01(\x0B2\x12.pg_query.TypeNameR\x08typeName\x125\x0A\x09returning\x18\x02 \x01(\x0B2\x17.pg_query.JsonReturningR\x09returning\"M\x0A\x0CJsonArgument\x12)\x0A\x03val\x18\x01 \x01(\x0B2\x17.pg_query.JsonValueExprR\x03val\x12\x12\x0A\x04name\x18\x02 \x01(\x09R\x04name\"\xFA\x03\x0A\x0CJsonFuncExpr\x12\$\x0A\x02op\x18\x01 \x01(\x0E2\x14.pg_query.JsonExprOpR\x02op\x12 \x0A\x0Bcolumn_name\x18\x02 \x01(\x09R\x0Bcolumn_name\x12;\x0A\x0Ccontext_item\x18\x03 \x01(\x0B2\x17.pg_query.JsonValueExprR\x0Ccontext_item\x12*\x0A\x08pathspec\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x08pathspec\x12(\x0A\x07passing\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x07passing\x12,\x0A\x06output\x18\x06 \x01(\x0B2\x14.pg_query.JsonOutputR\x06output\x122\x0A\x08on_empty\x18\x07 \x01(\x0B2\x16.pg_query.JsonBehaviorR\x08on_empty\x122\x0A\x08on_error\x18\x08 \x01(\x0B2\x16.pg_query.JsonBehaviorR\x08on_error\x12/\x0A\x07wrapper\x18\x09 \x01(\x0E2\x15.pg_query.JsonWrapperR\x07wrapper\x12,\x0A\x06quotes\x18\x0A \x01(\x0E2\x14.pg_query.JsonQuotesR\x06quotes\x12\x1A\x0A\x08location\x18\x0B \x01(\x05R\x08location\"\x91\x01\x0A\x11JsonTablePathSpec\x12&\x0A\x06string\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x06string\x12\x12\x0A\x04name\x18\x02 \x01(\x09R\x04name\x12\$\x0A\x0Dname_location\x18\x03 \x01(\x05R\x0Dname_location\x12\x1A\x0A\x08location\x18\x04 \x01(\x05R\x08location\"\xE6\x02\x0A\x09JsonTable\x12;\x0A\x0Ccontext_item\x18\x01 \x01(\x0B2\x17.pg_query.JsonValueExprR\x0Ccontext_item\x127\x0A\x08pathspec\x18\x02 \x01(\x0B2\x1B.pg_query.JsonTablePathSpecR\x08pathspec\x12(\x0A\x07passing\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x07passing\x12(\x0A\x07columns\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x07columns\x122\x0A\x08on_error\x18\x05 \x01(\x0B2\x16.pg_query.JsonBehaviorR\x08on_error\x12%\x0A\x05alias\x18\x06 \x01(\x0B2\x0F.pg_query.AliasR\x05alias\x12\x18\x0A\x07lateral\x18\x07 \x01(\x08R\x07lateral\x12\x1A\x0A\x08location\x18\x08 \x01(\x05R\x08location\"\x83\x04\x0A\x0FJsonTableColumn\x127\x0A\x07coltype\x18\x01 \x01(\x0E2\x1D.pg_query.JsonTableColumnTypeR\x07coltype\x12\x12\x0A\x04name\x18\x02 \x01(\x09R\x04name\x12/\x0A\x09type_name\x18\x03 \x01(\x0B2\x12.pg_query.TypeNameR\x08typeName\x127\x0A\x08pathspec\x18\x04 \x01(\x0B2\x1B.pg_query.JsonTablePathSpecR\x08pathspec\x12,\x0A\x06format\x18\x05 \x01(\x0B2\x14.pg_query.JsonFormatR\x06format\x12/\x0A\x07wrapper\x18\x06 \x01(\x0E2\x15.pg_query.JsonWrapperR\x07wrapper\x12,\x0A\x06quotes\x18\x07 \x01(\x0E2\x14.pg_query.JsonQuotesR\x06quotes\x12(\x0A\x07columns\x18\x08 \x03(\x0B2\x0E.pg_query.NodeR\x07columns\x122\x0A\x08on_empty\x18\x09 \x01(\x0B2\x16.pg_query.JsonBehaviorR\x08on_empty\x122\x0A\x08on_error\x18\x0A \x01(\x0B2\x16.pg_query.JsonBehaviorR\x08on_error\x12\x1A\x0A\x08location\x18\x0B \x01(\x05R\x08location\"_\x0A\x0CJsonKeyValue\x12 \x0A\x03key\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03key\x12-\x0A\x05value\x18\x02 \x01(\x0B2\x17.pg_query.JsonValueExprR\x05value\"\xA8\x01\x0A\x0DJsonParseExpr\x12+\x0A\x04expr\x18\x01 \x01(\x0B2\x17.pg_query.JsonValueExprR\x04expr\x12,\x0A\x06output\x18\x02 \x01(\x0B2\x14.pg_query.JsonOutputR\x06output\x12 \x0A\x0Bunique_keys\x18\x03 \x01(\x08R\x0Bunique_keys\x12\x1A\x0A\x08location\x18\x04 \x01(\x05R\x08location\"~\x0A\x0EJsonScalarExpr\x12\"\x0A\x04expr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x04expr\x12,\x0A\x06output\x18\x02 \x01(\x0B2\x14.pg_query.JsonOutputR\x06output\x12\x1A\x0A\x08location\x18\x03 \x01(\x05R\x08location\"\x8A\x01\x0A\x11JsonSerializeExpr\x12+\x0A\x04expr\x18\x01 \x01(\x0B2\x17.pg_query.JsonValueExprR\x04expr\x12,\x0A\x06output\x18\x02 \x01(\x0B2\x14.pg_query.JsonOutputR\x06output\x12\x1A\x0A\x08location\x18\x03 \x01(\x05R\x08location\"\xC7\x01\x0A\x15JsonObjectConstructor\x12\$\x0A\x05exprs\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x05exprs\x12,\x0A\x06output\x18\x02 \x01(\x0B2\x14.pg_query.JsonOutputR\x06output\x12&\x0A\x0Eabsent_on_null\x18\x03 \x01(\x08R\x0Eabsent_on_null\x12\x16\x0A\x06unique\x18\x04 \x01(\x08R\x06unique\x12\x1A\x0A\x08location\x18\x05 \x01(\x05R\x08location\"\xAE\x01\x0A\x14JsonArrayConstructor\x12\$\x0A\x05exprs\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x05exprs\x12,\x0A\x06output\x18\x02 \x01(\x0B2\x14.pg_query.JsonOutputR\x06output\x12&\x0A\x0Eabsent_on_null\x18\x03 \x01(\x08R\x0Eabsent_on_null\x12\x1A\x0A\x08location\x18\x04 \x01(\x05R\x08location\"\xE1\x01\x0A\x19JsonArrayQueryConstructor\x12\$\x0A\x05query\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x05query\x12,\x0A\x06output\x18\x02 \x01(\x0B2\x14.pg_query.JsonOutputR\x06output\x12,\x0A\x06format\x18\x03 \x01(\x0B2\x14.pg_query.JsonFormatR\x06format\x12&\x0A\x0Eabsent_on_null\x18\x04 \x01(\x08R\x0Eabsent_on_null\x12\x1A\x0A\x08location\x18\x05 \x01(\x05R\x08location\"\xE5\x01\x0A\x12JsonAggConstructor\x12,\x0A\x06output\x18\x01 \x01(\x0B2\x14.pg_query.JsonOutputR\x06output\x12.\x0A\x0Aagg_filter\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x0Aagg_filter\x12,\x0A\x09agg_order\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x09agg_order\x12'\x0A\x04over\x18\x04 \x01(\x0B2\x13.pg_query.WindowDefR\x04over\x12\x1A\x0A\x08location\x18\x05 \x01(\x05R\x08location\"\xB9\x01\x0A\x0DJsonObjectAgg\x12>\x0A\x0Bconstructor\x18\x01 \x01(\x0B2\x1C.pg_query.JsonAggConstructorR\x0Bconstructor\x12(\x0A\x03arg\x18\x02 \x01(\x0B2\x16.pg_query.JsonKeyValueR\x03arg\x12&\x0A\x0Eabsent_on_null\x18\x03 \x01(\x08R\x0Eabsent_on_null\x12\x16\x0A\x06unique\x18\x04 \x01(\x08R\x06unique\"\xA1\x01\x0A\x0CJsonArrayAgg\x12>\x0A\x0Bconstructor\x18\x01 \x01(\x0B2\x1C.pg_query.JsonAggConstructorR\x0Bconstructor\x12)\x0A\x03arg\x18\x02 \x01(\x0B2\x17.pg_query.JsonValueExprR\x03arg\x12&\x0A\x0Eabsent_on_null\x18\x03 \x01(\x08R\x0Eabsent_on_null\"o\x0A\x07RawStmt\x12\"\x0A\x04stmt\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x04stmt\x12\$\x0A\x0Dstmt_location\x18\x02 \x01(\x05R\x0Dstmt_location\x12\x1A\x0A\x08stmt_len\x18\x03 \x01(\x05R\x08stmt_len\"\xFF\x02\x0A\x0AInsertStmt\x12.\x0A\x08relation\x18\x01 \x01(\x0B2\x12.pg_query.RangeVarR\x08relation\x12\"\x0A\x04cols\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x04cols\x12/\x0A\x0Bselect_stmt\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x0AselectStmt\x12H\x0A\x12on_conflict_clause\x18\x04 \x01(\x0B2\x1A.pg_query.OnConflictClauseR\x10onConflictClause\x125\x0A\x0Ereturning_list\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x0DreturningList\x125\x0A\x0Bwith_clause\x18\x06 \x01(\x0B2\x14.pg_query.WithClauseR\x0AwithClause\x124\x0A\x08override\x18\x07 \x01(\x0E2\x18.pg_query.OverridingKindR\x08override\"\x90\x02\x0A\x0ADeleteStmt\x12.\x0A\x08relation\x18\x01 \x01(\x0B2\x12.pg_query.RangeVarR\x08relation\x121\x0A\x0Cusing_clause\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x0BusingClause\x121\x0A\x0Cwhere_clause\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x0BwhereClause\x125\x0A\x0Ereturning_list\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x0DreturningList\x125\x0A\x0Bwith_clause\x18\x05 \x01(\x0B2\x14.pg_query.WithClauseR\x0AwithClause\"\xBF\x02\x0A\x0AUpdateStmt\x12.\x0A\x08relation\x18\x01 \x01(\x0B2\x12.pg_query.RangeVarR\x08relation\x12/\x0A\x0Btarget_list\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x0AtargetList\x121\x0A\x0Cwhere_clause\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x0BwhereClause\x12/\x0A\x0Bfrom_clause\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x0AfromClause\x125\x0A\x0Ereturning_list\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x0DreturningList\x125\x0A\x0Bwith_clause\x18\x06 \x01(\x0B2\x14.pg_query.WithClauseR\x0AwithClause\"\xD7\x02\x0A\x09MergeStmt\x12.\x0A\x08relation\x18\x01 \x01(\x0B2\x12.pg_query.RangeVarR\x08relation\x127\x0A\x0Fsource_relation\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x0EsourceRelation\x125\x0A\x0Ejoin_condition\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x0DjoinCondition\x12<\x0A\x12merge_when_clauses\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x10mergeWhenClauses\x125\x0A\x0Ereturning_list\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x0DreturningList\x125\x0A\x0Bwith_clause\x18\x06 \x01(\x0B2\x14.pg_query.WithClauseR\x0AwithClause\"\xD3\x07\x0A\x0ASelectStmt\x127\x0A\x0Fdistinct_clause\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x0EdistinctClause\x125\x0A\x0Binto_clause\x18\x02 \x01(\x0B2\x14.pg_query.IntoClauseR\x0AintoClause\x12/\x0A\x0Btarget_list\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x0AtargetList\x12/\x0A\x0Bfrom_clause\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x0AfromClause\x121\x0A\x0Cwhere_clause\x18\x05 \x01(\x0B2\x0E.pg_query.NodeR\x0BwhereClause\x121\x0A\x0Cgroup_clause\x18\x06 \x03(\x0B2\x0E.pg_query.NodeR\x0BgroupClause\x12%\x0A\x0Egroup_distinct\x18\x07 \x01(\x08R\x0DgroupDistinct\x123\x0A\x0Dhaving_clause\x18\x08 \x01(\x0B2\x0E.pg_query.NodeR\x0ChavingClause\x123\x0A\x0Dwindow_clause\x18\x09 \x03(\x0B2\x0E.pg_query.NodeR\x0CwindowClause\x121\x0A\x0Cvalues_lists\x18\x0A \x03(\x0B2\x0E.pg_query.NodeR\x0BvaluesLists\x12/\x0A\x0Bsort_clause\x18\x0B \x03(\x0B2\x0E.pg_query.NodeR\x0AsortClause\x121\x0A\x0Climit_offset\x18\x0C \x01(\x0B2\x0E.pg_query.NodeR\x0BlimitOffset\x12/\x0A\x0Blimit_count\x18\x0D \x01(\x0B2\x0E.pg_query.NodeR\x0AlimitCount\x128\x0A\x0Climit_option\x18\x0E \x01(\x0E2\x15.pg_query.LimitOptionR\x0BlimitOption\x125\x0A\x0Elocking_clause\x18\x0F \x03(\x0B2\x0E.pg_query.NodeR\x0DlockingClause\x125\x0A\x0Bwith_clause\x18\x10 \x01(\x0B2\x14.pg_query.WithClauseR\x0AwithClause\x12&\x0A\x02op\x18\x11 \x01(\x0E2\x16.pg_query.SetOperationR\x02op\x12\x10\x0A\x03all\x18\x12 \x01(\x08R\x03all\x12(\x0A\x04larg\x18\x13 \x01(\x0B2\x14.pg_query.SelectStmtR\x04larg\x12(\x0A\x04rarg\x18\x14 \x01(\x0B2\x14.pg_query.SelectStmtR\x04rarg\"\xDE\x02\x0A\x10SetOperationStmt\x12&\x0A\x02op\x18\x01 \x01(\x0E2\x16.pg_query.SetOperationR\x02op\x12\x10\x0A\x03all\x18\x02 \x01(\x08R\x03all\x12\"\x0A\x04larg\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x04larg\x12\"\x0A\x04rarg\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x04rarg\x12+\x0A\x09col_types\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x08colTypes\x12/\x0A\x0Bcol_typmods\x18\x06 \x03(\x0B2\x0E.pg_query.NodeR\x0AcolTypmods\x125\x0A\x0Ecol_collations\x18\x07 \x03(\x0B2\x0E.pg_query.NodeR\x0DcolCollations\x123\x0A\x0Dgroup_clauses\x18\x08 \x03(\x0B2\x0E.pg_query.NodeR\x0CgroupClauses\":\x0A\x0AReturnStmt\x12,\x0A\x09returnval\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x09returnval\"\xB0\x01\x0A\x0CPLAssignStmt\x12\x12\x0A\x04name\x18\x01 \x01(\x09R\x04name\x120\x0A\x0Bindirection\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x0Bindirection\x12\x16\x0A\x06nnames\x18\x03 \x01(\x05R\x06nnames\x12&\x0A\x03val\x18\x04 \x01(\x0B2\x14.pg_query.SelectStmtR\x03val\x12\x1A\x0A\x08location\x18\x05 \x01(\x05R\x08location\"\xB9\x01\x0A\x10CreateSchemaStmt\x12\x1E\x0A\x0Aschemaname\x18\x01 \x01(\x09R\x0Aschemaname\x12.\x0A\x08authrole\x18\x02 \x01(\x0B2\x12.pg_query.RoleSpecR\x08authrole\x12/\x0A\x0Bschema_elts\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x0AschemaElts\x12\$\x0A\x0Dif_not_exists\x18\x04 \x01(\x08R\x0Dif_not_exists\"\xB4\x01\x0A\x0EAlterTableStmt\x12.\x0A\x08relation\x18\x01 \x01(\x0B2\x12.pg_query.RangeVarR\x08relation\x12\"\x0A\x04cmds\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x04cmds\x12.\x0A\x07objtype\x18\x03 \x01(\x0E2\x14.pg_query.ObjectTypeR\x07objtype\x12\x1E\x0A\x0Amissing_ok\x18\x04 \x01(\x08R\x0Amissing_ok\"O\x0A\x13ReplicaIdentityStmt\x12\$\x0A\x0Didentity_type\x18\x01 \x01(\x09R\x0Didentity_type\x12\x12\x0A\x04name\x18\x02 \x01(\x09R\x04name\"\xA9\x02\x0A\x0DAlterTableCmd\x122\x0A\x07subtype\x18\x01 \x01(\x0E2\x18.pg_query.AlterTableTypeR\x07subtype\x12\x12\x0A\x04name\x18\x02 \x01(\x09R\x04name\x12\x10\x0A\x03num\x18\x03 \x01(\x05R\x03num\x12.\x0A\x08newowner\x18\x04 \x01(\x0B2\x12.pg_query.RoleSpecR\x08newowner\x12 \x0A\x03def\x18\x05 \x01(\x0B2\x0E.pg_query.NodeR\x03def\x122\x0A\x08behavior\x18\x06 \x01(\x0E2\x16.pg_query.DropBehaviorR\x08behavior\x12\x1E\x0A\x0Amissing_ok\x18\x07 \x01(\x08R\x0Amissing_ok\x12\x18\x0A\x07recurse\x18\x08 \x01(\x08R\x07recurse\"@\x0A\x12AlterCollationStmt\x12*\x0A\x08collname\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x08collname\"\xE2\x01\x0A\x0FAlterDomainStmt\x12\x18\x0A\x07subtype\x18\x01 \x01(\x09R\x07subtype\x12+\x0A\x09type_name\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x08typeName\x12\x12\x0A\x04name\x18\x03 \x01(\x09R\x04name\x12 \x0A\x03def\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x03def\x122\x0A\x08behavior\x18\x05 \x01(\x0E2\x16.pg_query.DropBehaviorR\x08behavior\x12\x1E\x0A\x0Amissing_ok\x18\x06 \x01(\x08R\x0Amissing_ok\"\x9A\x03\x0A\x09GrantStmt\x12\x1A\x0A\x08is_grant\x18\x01 \x01(\x08R\x08is_grant\x125\x0A\x08targtype\x18\x02 \x01(\x0E2\x19.pg_query.GrantTargetTypeR\x08targtype\x12.\x0A\x07objtype\x18\x03 \x01(\x0E2\x14.pg_query.ObjectTypeR\x07objtype\x12(\x0A\x07objects\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x07objects\x12.\x0A\x0Aprivileges\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x0Aprivileges\x12*\x0A\x08grantees\x18\x06 \x03(\x0B2\x0E.pg_query.NodeR\x08grantees\x12\"\x0A\x0Cgrant_option\x18\x07 \x01(\x08R\x0Cgrant_option\x12,\x0A\x07grantor\x18\x08 \x01(\x0B2\x12.pg_query.RoleSpecR\x07grantor\x122\x0A\x08behavior\x18\x09 \x01(\x0E2\x16.pg_query.DropBehaviorR\x08behavior\"\xC2\x01\x0A\x0EObjectWithArgs\x12(\x0A\x07objname\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x07objname\x12(\x0A\x07objargs\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x07objargs\x120\x0A\x0Bobjfuncargs\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x0Bobjfuncargs\x12*\x0A\x10args_unspecified\x18\x04 \x01(\x08R\x10args_unspecified\"N\x0A\x0AAccessPriv\x12\x1C\x0A\x09priv_name\x18\x01 \x01(\x09R\x09priv_name\x12\"\x0A\x04cols\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x04cols\"\x9B\x02\x0A\x0DGrantRoleStmt\x124\x0A\x0Dgranted_roles\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x0Dgranted_roles\x124\x0A\x0Dgrantee_roles\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x0Dgrantee_roles\x12\x1A\x0A\x08is_grant\x18\x03 \x01(\x08R\x08is_grant\x12 \x0A\x03opt\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x03opt\x12,\x0A\x07grantor\x18\x05 \x01(\x0B2\x12.pg_query.RoleSpecR\x07grantor\x122\x0A\x08behavior\x18\x06 \x01(\x0E2\x16.pg_query.DropBehaviorR\x08behavior\"s\x0A\x1AAlterDefaultPrivilegesStmt\x12(\x0A\x07options\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x07options\x12+\x0A\x06action\x18\x02 \x01(\x0B2\x13.pg_query.GrantStmtR\x06action\"\xBD\x02\x0A\x08CopyStmt\x12.\x0A\x08relation\x18\x01 \x01(\x0B2\x12.pg_query.RangeVarR\x08relation\x12\$\x0A\x05query\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x05query\x12(\x0A\x07attlist\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x07attlist\x12\x18\x0A\x07is_from\x18\x04 \x01(\x08R\x07is_from\x12\x1E\x0A\x0Ais_program\x18\x05 \x01(\x08R\x0Ais_program\x12\x1A\x0A\x08filename\x18\x06 \x01(\x09R\x08filename\x12(\x0A\x07options\x18\x07 \x03(\x0B2\x0E.pg_query.NodeR\x07options\x121\x0A\x0Cwhere_clause\x18\x08 \x01(\x0B2\x0E.pg_query.NodeR\x0BwhereClause\"\x94\x01\x0A\x0FVariableSetStmt\x12-\x0A\x04kind\x18\x01 \x01(\x0E2\x19.pg_query.VariableSetKindR\x04kind\x12\x12\x0A\x04name\x18\x02 \x01(\x09R\x04name\x12\"\x0A\x04args\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x04args\x12\x1A\x0A\x08is_local\x18\x04 \x01(\x08R\x08is_local\"&\x0A\x10VariableShowStmt\x12\x12\x0A\x04name\x18\x01 \x01(\x09R\x04name\"\xCB\x04\x0A\x0ACreateStmt\x12.\x0A\x08relation\x18\x01 \x01(\x0B2\x12.pg_query.RangeVarR\x08relation\x12-\x0A\x0Atable_elts\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x09tableElts\x123\x0A\x0Dinh_relations\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x0CinhRelations\x12:\x0A\x09partbound\x18\x04 \x01(\x0B2\x1C.pg_query.PartitionBoundSpecR\x09partbound\x123\x0A\x08partspec\x18\x05 \x01(\x0B2\x17.pg_query.PartitionSpecR\x08partspec\x123\x0A\x0Bof_typename\x18\x06 \x01(\x0B2\x12.pg_query.TypeNameR\x0AofTypename\x120\x0A\x0Bconstraints\x18\x07 \x03(\x0B2\x0E.pg_query.NodeR\x0Bconstraints\x12(\x0A\x07options\x18\x08 \x03(\x0B2\x0E.pg_query.NodeR\x07options\x124\x0A\x08oncommit\x18\x09 \x01(\x0E2\x18.pg_query.OnCommitActionR\x08oncommit\x12&\x0A\x0Etablespacename\x18\x0A \x01(\x09R\x0Etablespacename\x12#\x0A\x0Daccess_method\x18\x0B \x01(\x09R\x0CaccessMethod\x12\$\x0A\x0Dif_not_exists\x18\x0C \x01(\x08R\x0Dif_not_exists\"\xFA\x09\x0A\x0AConstraint\x12.\x0A\x07contype\x18\x01 \x01(\x0E2\x14.pg_query.ConstrTypeR\x07contype\x12\x18\x0A\x07conname\x18\x02 \x01(\x09R\x07conname\x12\x1E\x0A\x0Adeferrable\x18\x03 \x01(\x08R\x0Adeferrable\x12\"\x0A\x0Cinitdeferred\x18\x04 \x01(\x08R\x0Cinitdeferred\x12(\x0A\x0Fskip_validation\x18\x05 \x01(\x08R\x0Fskip_validation\x12(\x0A\x0Finitially_valid\x18\x06 \x01(\x08R\x0Finitially_valid\x12\$\x0A\x0Dis_no_inherit\x18\x07 \x01(\x08R\x0Dis_no_inherit\x12*\x0A\x08raw_expr\x18\x08 \x01(\x0B2\x0E.pg_query.NodeR\x08raw_expr\x12 \x0A\x0Bcooked_expr\x18\x09 \x01(\x09R\x0Bcooked_expr\x12&\x0A\x0Egenerated_when\x18\x0A \x01(\x09R\x0Egenerated_when\x12\x1A\x0A\x08inhcount\x18\x0B \x01(\x05R\x08inhcount\x12.\x0A\x12nulls_not_distinct\x18\x0C \x01(\x08R\x12nulls_not_distinct\x12\"\x0A\x04keys\x18\x0D \x03(\x0B2\x0E.pg_query.NodeR\x04keys\x12,\x0A\x09including\x18\x0E \x03(\x0B2\x0E.pg_query.NodeR\x09including\x12.\x0A\x0Aexclusions\x18\x0F \x03(\x0B2\x0E.pg_query.NodeR\x0Aexclusions\x12(\x0A\x07options\x18\x10 \x03(\x0B2\x0E.pg_query.NodeR\x07options\x12\x1C\x0A\x09indexname\x18\x11 \x01(\x09R\x09indexname\x12\x1E\x0A\x0Aindexspace\x18\x12 \x01(\x09R\x0Aindexspace\x122\x0A\x14reset_default_tblspc\x18\x13 \x01(\x08R\x14reset_default_tblspc\x12\$\x0A\x0Daccess_method\x18\x14 \x01(\x09R\x0Daccess_method\x122\x0A\x0Cwhere_clause\x18\x15 \x01(\x0B2\x0E.pg_query.NodeR\x0Cwhere_clause\x12,\x0A\x07pktable\x18\x16 \x01(\x0B2\x12.pg_query.RangeVarR\x07pktable\x12*\x0A\x08fk_attrs\x18\x17 \x03(\x0B2\x0E.pg_query.NodeR\x08fk_attrs\x12*\x0A\x08pk_attrs\x18\x18 \x03(\x0B2\x0E.pg_query.NodeR\x08pk_attrs\x12\"\x0A\x0Cfk_matchtype\x18\x19 \x01(\x09R\x0Cfk_matchtype\x12\$\x0A\x0Dfk_upd_action\x18\x1A \x01(\x09R\x0Dfk_upd_action\x12\$\x0A\x0Dfk_del_action\x18\x1B \x01(\x09R\x0Dfk_del_action\x128\x0A\x0Ffk_del_set_cols\x18\x1C \x03(\x0B2\x0E.pg_query.NodeR\x0Ffk_del_set_cols\x124\x0A\x0Dold_conpfeqop\x18\x1D \x03(\x0B2\x0E.pg_query.NodeR\x0Dold_conpfeqop\x12(\x0A\x0Fold_pktable_oid\x18\x1E \x01(\x0DR\x0Fold_pktable_oid\x12\x1A\x0A\x08location\x18\x1F \x01(\x05R\x08location\"\xAE\x01\x0A\x14CreateTableSpaceStmt\x12&\x0A\x0Etablespacename\x18\x01 \x01(\x09R\x0Etablespacename\x12(\x0A\x05owner\x18\x02 \x01(\x0B2\x12.pg_query.RoleSpecR\x05owner\x12\x1A\x0A\x08location\x18\x03 \x01(\x09R\x08location\x12(\x0A\x07options\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x07options\"\\\x0A\x12DropTableSpaceStmt\x12&\x0A\x0Etablespacename\x18\x01 \x01(\x09R\x0Etablespacename\x12\x1E\x0A\x0Amissing_ok\x18\x02 \x01(\x08R\x0Amissing_ok\"\x89\x01\x0A\x1AAlterTableSpaceOptionsStmt\x12&\x0A\x0Etablespacename\x18\x01 \x01(\x09R\x0Etablespacename\x12(\x0A\x07options\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x07options\x12\x19\x0A\x08is_reset\x18\x03 \x01(\x08R\x07isReset\"\xE7\x01\x0A\x15AlterTableMoveAllStmt\x120\x0A\x13orig_tablespacename\x18\x01 \x01(\x09R\x13orig_tablespacename\x12.\x0A\x07objtype\x18\x02 \x01(\x0E2\x14.pg_query.ObjectTypeR\x07objtype\x12\$\x0A\x05roles\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x05roles\x12.\x0A\x12new_tablespacename\x18\x04 \x01(\x09R\x12new_tablespacename\x12\x16\x0A\x06nowait\x18\x05 \x01(\x08R\x06nowait\"\x7F\x0A\x13CreateExtensionStmt\x12\x18\x0A\x07extname\x18\x01 \x01(\x09R\x07extname\x12\$\x0A\x0Dif_not_exists\x18\x02 \x01(\x08R\x0Dif_not_exists\x12(\x0A\x07options\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x07options\"X\x0A\x12AlterExtensionStmt\x12\x18\x0A\x07extname\x18\x01 \x01(\x09R\x07extname\x12(\x0A\x07options\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x07options\"\xA6\x01\x0A\x1AAlterExtensionContentsStmt\x12\x18\x0A\x07extname\x18\x01 \x01(\x09R\x07extname\x12\x16\x0A\x06action\x18\x02 \x01(\x05R\x06action\x12.\x0A\x07objtype\x18\x03 \x01(\x0E2\x14.pg_query.ObjectTypeR\x07objtype\x12&\x0A\x06object\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x06object\"\x87\x01\x0A\x0DCreateFdwStmt\x12\x18\x0A\x07fdwname\x18\x01 \x01(\x09R\x07fdwname\x122\x0A\x0Cfunc_options\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x0Cfunc_options\x12(\x0A\x07options\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x07options\"\x86\x01\x0A\x0CAlterFdwStmt\x12\x18\x0A\x07fdwname\x18\x01 \x01(\x09R\x07fdwname\x122\x0A\x0Cfunc_options\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x0Cfunc_options\x12(\x0A\x07options\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x07options\"\xDD\x01\x0A\x17CreateForeignServerStmt\x12\x1E\x0A\x0Aservername\x18\x01 \x01(\x09R\x0Aservername\x12\x1E\x0A\x0Aservertype\x18\x02 \x01(\x09R\x0Aservertype\x12\x18\x0A\x07version\x18\x03 \x01(\x09R\x07version\x12\x18\x0A\x07fdwname\x18\x04 \x01(\x09R\x07fdwname\x12\$\x0A\x0Dif_not_exists\x18\x05 \x01(\x08R\x0Dif_not_exists\x12(\x0A\x07options\x18\x06 \x03(\x0B2\x0E.pg_query.NodeR\x07options\"\x9E\x01\x0A\x16AlterForeignServerStmt\x12\x1E\x0A\x0Aservername\x18\x01 \x01(\x09R\x0Aservername\x12\x18\x0A\x07version\x18\x02 \x01(\x09R\x07version\x12(\x0A\x07options\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x07options\x12 \x0A\x0Bhas_version\x18\x04 \x01(\x08R\x0Bhas_version\"\x91\x01\x0A\x16CreateForeignTableStmt\x12-\x0A\x09base_stmt\x18\x01 \x01(\x0B2\x14.pg_query.CreateStmtR\x04base\x12\x1E\x0A\x0Aservername\x18\x02 \x01(\x09R\x0Aservername\x12(\x0A\x07options\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x07options\"\xAF\x01\x0A\x15CreateUserMappingStmt\x12&\x0A\x04user\x18\x01 \x01(\x0B2\x12.pg_query.RoleSpecR\x04user\x12\x1E\x0A\x0Aservername\x18\x02 \x01(\x09R\x0Aservername\x12\$\x0A\x0Dif_not_exists\x18\x03 \x01(\x08R\x0Dif_not_exists\x12(\x0A\x07options\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x07options\"\x88\x01\x0A\x14AlterUserMappingStmt\x12&\x0A\x04user\x18\x01 \x01(\x0B2\x12.pg_query.RoleSpecR\x04user\x12\x1E\x0A\x0Aservername\x18\x02 \x01(\x09R\x0Aservername\x12(\x0A\x07options\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x07options\"}\x0A\x13DropUserMappingStmt\x12&\x0A\x04user\x18\x01 \x01(\x0B2\x12.pg_query.RoleSpecR\x04user\x12\x1E\x0A\x0Aservername\x18\x02 \x01(\x09R\x0Aservername\x12\x1E\x0A\x0Amissing_ok\x18\x03 \x01(\x08R\x0Amissing_ok\"\xA0\x02\x0A\x17ImportForeignSchemaStmt\x12 \x0A\x0Bserver_name\x18\x01 \x01(\x09R\x0Bserver_name\x12\$\x0A\x0Dremote_schema\x18\x02 \x01(\x09R\x0Dremote_schema\x12\"\x0A\x0Clocal_schema\x18\x03 \x01(\x09R\x0Clocal_schema\x12?\x0A\x09list_type\x18\x04 \x01(\x0E2!.pg_query.ImportForeignSchemaTypeR\x09list_type\x12.\x0A\x0Atable_list\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x0Atable_list\x12(\x0A\x07options\x18\x06 \x03(\x0B2\x0E.pg_query.NodeR\x07options\"\x94\x02\x0A\x10CreatePolicyStmt\x12 \x0A\x0Bpolicy_name\x18\x01 \x01(\x09R\x0Bpolicy_name\x12(\x0A\x05table\x18\x02 \x01(\x0B2\x12.pg_query.RangeVarR\x05table\x12\x1A\x0A\x08cmd_name\x18\x03 \x01(\x09R\x08cmd_name\x12\x1E\x0A\x0Apermissive\x18\x04 \x01(\x08R\x0Apermissive\x12\$\x0A\x05roles\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x05roles\x12\"\x0A\x04qual\x18\x06 \x01(\x0B2\x0E.pg_query.NodeR\x04qual\x12.\x0A\x0Awith_check\x18\x07 \x01(\x0B2\x0E.pg_query.NodeR\x0Awith_check\"\xD7\x01\x0A\x0FAlterPolicyStmt\x12 \x0A\x0Bpolicy_name\x18\x01 \x01(\x09R\x0Bpolicy_name\x12(\x0A\x05table\x18\x02 \x01(\x0B2\x12.pg_query.RangeVarR\x05table\x12\$\x0A\x05roles\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x05roles\x12\"\x0A\x04qual\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x04qual\x12.\x0A\x0Awith_check\x18\x05 \x01(\x0B2\x0E.pg_query.NodeR\x0Awith_check\"r\x0A\x0CCreateAmStmt\x12\x16\x0A\x06amname\x18\x01 \x01(\x09R\x06amname\x122\x0A\x0Chandler_name\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x0Chandler_name\x12\x16\x0A\x06amtype\x18\x03 \x01(\x09R\x06amtype\"\xB6\x04\x0A\x0ECreateTrigStmt\x12\x18\x0A\x07replace\x18\x01 \x01(\x08R\x07replace\x12\"\x0A\x0Cisconstraint\x18\x02 \x01(\x08R\x0Cisconstraint\x12\x1A\x0A\x08trigname\x18\x03 \x01(\x09R\x08trigname\x12.\x0A\x08relation\x18\x04 \x01(\x0B2\x12.pg_query.RangeVarR\x08relation\x12*\x0A\x08funcname\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x08funcname\x12\"\x0A\x04args\x18\x06 \x03(\x0B2\x0E.pg_query.NodeR\x04args\x12\x10\x0A\x03row\x18\x07 \x01(\x08R\x03row\x12\x16\x0A\x06timing\x18\x08 \x01(\x05R\x06timing\x12\x16\x0A\x06events\x18\x09 \x01(\x05R\x06events\x12(\x0A\x07columns\x18\x0A \x03(\x0B2\x0E.pg_query.NodeR\x07columns\x12/\x0A\x0Bwhen_clause\x18\x0B \x01(\x0B2\x0E.pg_query.NodeR\x0AwhenClause\x127\x0A\x0Ftransition_rels\x18\x0C \x03(\x0B2\x0E.pg_query.NodeR\x0EtransitionRels\x12\x1E\x0A\x0Adeferrable\x18\x0D \x01(\x08R\x0Adeferrable\x12\"\x0A\x0Cinitdeferred\x18\x0E \x01(\x08R\x0Cinitdeferred\x120\x0A\x09constrrel\x18\x0F \x01(\x0B2\x12.pg_query.RangeVarR\x09constrrel\"\xAB\x01\x0A\x13CreateEventTrigStmt\x12\x1A\x0A\x08trigname\x18\x01 \x01(\x09R\x08trigname\x12\x1C\x0A\x09eventname\x18\x02 \x01(\x09R\x09eventname\x12.\x0A\x0Awhenclause\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x0Awhenclause\x12*\x0A\x08funcname\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x08funcname\"N\x0A\x12AlterEventTrigStmt\x12\x1A\x0A\x08trigname\x18\x01 \x01(\x09R\x08trigname\x12\x1C\x0A\x09tgenabled\x18\x02 \x01(\x09R\x09tgenabled\"\xED\x01\x0A\x0FCreatePLangStmt\x12\x18\x0A\x07replace\x18\x01 \x01(\x08R\x07replace\x12\x16\x0A\x06plname\x18\x02 \x01(\x09R\x06plname\x12,\x0A\x09plhandler\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x09plhandler\x12*\x0A\x08plinline\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x08plinline\x120\x0A\x0Bplvalidator\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x0Bplvalidator\x12\x1C\x0A\x09pltrusted\x18\x06 \x01(\x08R\x09pltrusted\"\x84\x01\x0A\x0ECreateRoleStmt\x124\x0A\x09stmt_type\x18\x01 \x01(\x0E2\x16.pg_query.RoleStmtTypeR\x09stmt_type\x12\x12\x0A\x04role\x18\x02 \x01(\x09R\x04role\x12(\x0A\x07options\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x07options\"y\x0A\x0DAlterRoleStmt\x12&\x0A\x04role\x18\x01 \x01(\x0B2\x12.pg_query.RoleSpecR\x04role\x12(\x0A\x07options\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x07options\x12\x16\x0A\x06action\x18\x03 \x01(\x05R\x06action\"\x8B\x01\x0A\x10AlterRoleSetStmt\x12&\x0A\x04role\x18\x01 \x01(\x0B2\x12.pg_query.RoleSpecR\x04role\x12\x1A\x0A\x08database\x18\x02 \x01(\x09R\x08database\x123\x0A\x07setstmt\x18\x03 \x01(\x0B2\x19.pg_query.VariableSetStmtR\x07setstmt\"T\x0A\x0CDropRoleStmt\x12\$\x0A\x05roles\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x05roles\x12\x1E\x0A\x0Amissing_ok\x18\x02 \x01(\x08R\x0Amissing_ok\"\xCE\x01\x0A\x0DCreateSeqStmt\x12.\x0A\x08sequence\x18\x01 \x01(\x0B2\x12.pg_query.RangeVarR\x08sequence\x12(\x0A\x07options\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x07options\x12\x19\x0A\x08owner_id\x18\x03 \x01(\x0DR\x07ownerId\x12\"\x0A\x0Cfor_identity\x18\x04 \x01(\x08R\x0Cfor_identity\x12\$\x0A\x0Dif_not_exists\x18\x05 \x01(\x08R\x0Dif_not_exists\"\xAC\x01\x0A\x0CAlterSeqStmt\x12.\x0A\x08sequence\x18\x01 \x01(\x0B2\x12.pg_query.RangeVarR\x08sequence\x12(\x0A\x07options\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x07options\x12\"\x0A\x0Cfor_identity\x18\x03 \x01(\x08R\x0Cfor_identity\x12\x1E\x0A\x0Amissing_ok\x18\x04 \x01(\x08R\x0Amissing_ok\"\x92\x02\x0A\x0ADefineStmt\x12(\x0A\x04kind\x18\x01 \x01(\x0E2\x14.pg_query.ObjectTypeR\x04kind\x12\x1A\x0A\x08oldstyle\x18\x02 \x01(\x08R\x08oldstyle\x12*\x0A\x08defnames\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x08defnames\x12\"\x0A\x04args\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x04args\x12.\x0A\x0Adefinition\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x0Adefinition\x12\$\x0A\x0Dif_not_exists\x18\x06 \x01(\x08R\x0Dif_not_exists\x12\x18\x0A\x07replace\x18\x07 \x01(\x08R\x07replace\"\xDF\x01\x0A\x10CreateDomainStmt\x12.\x0A\x0Adomainname\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x0Adomainname\x12/\x0A\x09type_name\x18\x02 \x01(\x0B2\x12.pg_query.TypeNameR\x08typeName\x128\x0A\x0Bcoll_clause\x18\x03 \x01(\x0B2\x17.pg_query.CollateClauseR\x0AcollClause\x120\x0A\x0Bconstraints\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x0Bconstraints\"\x86\x02\x0A\x11CreateOpClassStmt\x120\x0A\x0Bopclassname\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x0Bopclassname\x122\x0A\x0Copfamilyname\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x0Copfamilyname\x12\x16\x0A\x06amname\x18\x03 \x01(\x09R\x06amname\x12.\x0A\x08datatype\x18\x04 \x01(\x0B2\x12.pg_query.TypeNameR\x08datatype\x12\$\x0A\x05items\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x05items\x12\x1D\x0A\x0Ais_default\x18\x06 \x01(\x08R\x09isDefault\"\x8D\x02\x0A\x11CreateOpClassItem\x12\x1A\x0A\x08itemtype\x18\x01 \x01(\x05R\x08itemtype\x12,\x0A\x04name\x18\x02 \x01(\x0B2\x18.pg_query.ObjectWithArgsR\x04name\x12\x16\x0A\x06number\x18\x03 \x01(\x05R\x06number\x122\x0A\x0Corder_family\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x0Corder_family\x12.\x0A\x0Aclass_args\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x0Aclass_args\x122\x0A\x0Astoredtype\x18\x06 \x01(\x0B2\x12.pg_query.TypeNameR\x0Astoredtype\"`\x0A\x12CreateOpFamilyStmt\x122\x0A\x0Copfamilyname\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x0Copfamilyname\x12\x16\x0A\x06amname\x18\x02 \x01(\x09R\x06amname\"\x9E\x01\x0A\x11AlterOpFamilyStmt\x122\x0A\x0Copfamilyname\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x0Copfamilyname\x12\x16\x0A\x06amname\x18\x02 \x01(\x09R\x06amname\x12\x17\x0A\x07is_drop\x18\x03 \x01(\x08R\x06isDrop\x12\$\x0A\x05items\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x05items\"\xDF\x01\x0A\x08DropStmt\x12(\x0A\x07objects\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x07objects\x125\x0A\x0Bremove_type\x18\x02 \x01(\x0E2\x14.pg_query.ObjectTypeR\x0AremoveType\x122\x0A\x08behavior\x18\x03 \x01(\x0E2\x16.pg_query.DropBehaviorR\x08behavior\x12\x1E\x0A\x0Amissing_ok\x18\x04 \x01(\x08R\x0Amissing_ok\x12\x1E\x0A\x0Aconcurrent\x18\x05 \x01(\x08R\x0Aconcurrent\"\x94\x01\x0A\x0CTruncateStmt\x12,\x0A\x09relations\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x09relations\x12\"\x0A\x0Crestart_seqs\x18\x02 \x01(\x08R\x0Crestart_seqs\x122\x0A\x08behavior\x18\x03 \x01(\x0E2\x16.pg_query.DropBehaviorR\x08behavior\"\x7F\x0A\x0BCommentStmt\x12.\x0A\x07objtype\x18\x01 \x01(\x0E2\x14.pg_query.ObjectTypeR\x07objtype\x12&\x0A\x06object\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x06object\x12\x18\x0A\x07comment\x18\x03 \x01(\x09R\x07comment\"\x98\x01\x0A\x0CSecLabelStmt\x12.\x0A\x07objtype\x18\x01 \x01(\x0E2\x14.pg_query.ObjectTypeR\x07objtype\x12&\x0A\x06object\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x06object\x12\x1A\x0A\x08provider\x18\x03 \x01(\x09R\x08provider\x12\x14\x0A\x05label\x18\x04 \x01(\x09R\x05label\"s\x0A\x11DeclareCursorStmt\x12\x1E\x0A\x0Aportalname\x18\x01 \x01(\x09R\x0Aportalname\x12\x18\x0A\x07options\x18\x02 \x01(\x05R\x07options\x12\$\x0A\x05query\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x05query\"1\x0A\x0FClosePortalStmt\x12\x1E\x0A\x0Aportalname\x18\x01 \x01(\x09R\x0Aportalname\"\x96\x01\x0A\x09FetchStmt\x126\x0A\x09direction\x18\x01 \x01(\x0E2\x18.pg_query.FetchDirectionR\x09direction\x12\x19\x0A\x08how_many\x18\x02 \x01(\x03R\x07howMany\x12\x1E\x0A\x0Aportalname\x18\x03 \x01(\x09R\x0Aportalname\x12\x16\x0A\x06ismove\x18\x04 \x01(\x08R\x06ismove\"\xDC\x07\x0A\x09IndexStmt\x12\x18\x0A\x07idxname\x18\x01 \x01(\x09R\x07idxname\x12.\x0A\x08relation\x18\x02 \x01(\x0B2\x12.pg_query.RangeVarR\x08relation\x12#\x0A\x0Daccess_method\x18\x03 \x01(\x09R\x0CaccessMethod\x12\x1F\x0A\x0Btable_space\x18\x04 \x01(\x09R\x0AtableSpace\x121\x0A\x0Cindex_params\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x0BindexParams\x12D\x0A\x16index_including_params\x18\x06 \x03(\x0B2\x0E.pg_query.NodeR\x14indexIncludingParams\x12(\x0A\x07options\x18\x07 \x03(\x0B2\x0E.pg_query.NodeR\x07options\x121\x0A\x0Cwhere_clause\x18\x08 \x01(\x0B2\x0E.pg_query.NodeR\x0BwhereClause\x128\x0A\x10exclude_op_names\x18\x09 \x03(\x0B2\x0E.pg_query.NodeR\x0EexcludeOpNames\x12\x1E\x0A\x0Aidxcomment\x18\x0A \x01(\x09R\x0Aidxcomment\x12\x1B\x0A\x09index_oid\x18\x0B \x01(\x0DR\x08indexOid\x12\x1D\x0A\x0Aold_number\x18\x0C \x01(\x0DR\x09oldNumber\x12(\x0A\x10old_create_subid\x18\x0D \x01(\x0DR\x0EoldCreateSubid\x12C\x0A\x1Eold_first_relfilelocator_subid\x18\x0E \x01(\x0DR\x1BoldFirstRelfilelocatorSubid\x12\x16\x0A\x06unique\x18\x0F \x01(\x08R\x06unique\x12.\x0A\x12nulls_not_distinct\x18\x10 \x01(\x08R\x12nulls_not_distinct\x12\x18\x0A\x07primary\x18\x11 \x01(\x08R\x07primary\x12\"\x0A\x0Cisconstraint\x18\x12 \x01(\x08R\x0Cisconstraint\x12\x1E\x0A\x0Adeferrable\x18\x13 \x01(\x08R\x0Adeferrable\x12\"\x0A\x0Cinitdeferred\x18\x14 \x01(\x08R\x0Cinitdeferred\x12 \x0A\x0Btransformed\x18\x15 \x01(\x08R\x0Btransformed\x12\x1E\x0A\x0Aconcurrent\x18\x16 \x01(\x08R\x0Aconcurrent\x12\$\x0A\x0Dif_not_exists\x18\x17 \x01(\x08R\x0Dif_not_exists\x122\x0A\x14reset_default_tblspc\x18\x18 \x01(\x08R\x14reset_default_tblspc\"\xA9\x02\x0A\x0FCreateStatsStmt\x12*\x0A\x08defnames\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x08defnames\x12.\x0A\x0Astat_types\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x0Astat_types\x12\$\x0A\x05exprs\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x05exprs\x12,\x0A\x09relations\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x09relations\x12\x1E\x0A\x0Astxcomment\x18\x05 \x01(\x09R\x0Astxcomment\x12 \x0A\x0Btransformed\x18\x06 \x01(\x08R\x0Btransformed\x12\$\x0A\x0Dif_not_exists\x18\x07 \x01(\x08R\x0Dif_not_exists\"C\x0A\x09StatsElem\x12\x12\x0A\x04name\x18\x01 \x01(\x09R\x04name\x12\"\x0A\x04expr\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x04expr\"\x92\x01\x0A\x0EAlterStatsStmt\x12*\x0A\x08defnames\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x08defnames\x124\x0A\x0Dstxstattarget\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x0Dstxstattarget\x12\x1E\x0A\x0Amissing_ok\x18\x03 \x01(\x08R\x0Amissing_ok\"\xB9\x02\x0A\x12CreateFunctionStmt\x12\"\x0A\x0Cis_procedure\x18\x01 \x01(\x08R\x0Cis_procedure\x12\x18\x0A\x07replace\x18\x02 \x01(\x08R\x07replace\x12*\x0A\x08funcname\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x08funcname\x12.\x0A\x0Aparameters\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x0Aparameters\x123\x0A\x0Breturn_type\x18\x05 \x01(\x0B2\x12.pg_query.TypeNameR\x0AreturnType\x12(\x0A\x07options\x18\x06 \x03(\x0B2\x0E.pg_query.NodeR\x07options\x12*\x0A\x08sql_body\x18\x07 \x01(\x0B2\x0E.pg_query.NodeR\x08sql_body\"\xB5\x01\x0A\x11FunctionParameter\x12\x12\x0A\x04name\x18\x01 \x01(\x09R\x04name\x12-\x0A\x08arg_type\x18\x02 \x01(\x0B2\x12.pg_query.TypeNameR\x07argType\x123\x0A\x04mode\x18\x03 \x01(\x0E2\x1F.pg_query.FunctionParameterModeR\x04mode\x12(\x0A\x07defexpr\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x07defexpr\"\x9B\x01\x0A\x11AlterFunctionStmt\x12.\x0A\x07objtype\x18\x01 \x01(\x0E2\x14.pg_query.ObjectTypeR\x07objtype\x12,\x0A\x04func\x18\x02 \x01(\x0B2\x18.pg_query.ObjectWithArgsR\x04func\x12(\x0A\x07actions\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x07actions\",\x0A\x06DoStmt\x12\"\x0A\x04args\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x04args\"\x8E\x01\x0A\x0FInlineCodeBlock\x12 \x0A\x0Bsource_text\x18\x01 \x01(\x09R\x0Bsource_text\x12\x19\x0A\x08lang_oid\x18\x02 \x01(\x0DR\x07langOid\x12&\x0A\x0Flang_is_trusted\x18\x03 \x01(\x08R\x0DlangIsTrusted\x12\x16\x0A\x06atomic\x18\x04 \x01(\x08R\x06atomic\"\x94\x01\x0A\x08CallStmt\x12.\x0A\x08funccall\x18\x01 \x01(\x0B2\x12.pg_query.FuncCallR\x08funccall\x12.\x0A\x08funcexpr\x18\x02 \x01(\x0B2\x12.pg_query.FuncExprR\x08funcexpr\x12(\x0A\x07outargs\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x07outargs\"%\x0A\x0BCallContext\x12\x16\x0A\x06atomic\x18\x01 \x01(\x08R\x06atomic\"\xDE\x02\x0A\x0ARenameStmt\x125\x0A\x0Brename_type\x18\x01 \x01(\x0E2\x14.pg_query.ObjectTypeR\x0ArenameType\x129\x0A\x0Drelation_type\x18\x02 \x01(\x0E2\x14.pg_query.ObjectTypeR\x0CrelationType\x12.\x0A\x08relation\x18\x03 \x01(\x0B2\x12.pg_query.RangeVarR\x08relation\x12&\x0A\x06object\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x06object\x12\x18\x0A\x07subname\x18\x05 \x01(\x09R\x07subname\x12\x18\x0A\x07newname\x18\x06 \x01(\x09R\x07newname\x122\x0A\x08behavior\x18\x07 \x01(\x0E2\x16.pg_query.DropBehaviorR\x08behavior\x12\x1E\x0A\x0Amissing_ok\x18\x08 \x01(\x08R\x0Amissing_ok\"\xEB\x01\x0A\x16AlterObjectDependsStmt\x125\x0A\x0Bobject_type\x18\x01 \x01(\x0E2\x14.pg_query.ObjectTypeR\x0AobjectType\x12.\x0A\x08relation\x18\x02 \x01(\x0B2\x12.pg_query.RangeVarR\x08relation\x12&\x0A\x06object\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x06object\x12*\x0A\x07extname\x18\x04 \x01(\x0B2\x10.pg_query.StringR\x07extname\x12\x16\x0A\x06remove\x18\x05 \x01(\x08R\x06remove\"\xE4\x01\x0A\x15AlterObjectSchemaStmt\x125\x0A\x0Bobject_type\x18\x01 \x01(\x0E2\x14.pg_query.ObjectTypeR\x0AobjectType\x12.\x0A\x08relation\x18\x02 \x01(\x0B2\x12.pg_query.RangeVarR\x08relation\x12&\x0A\x06object\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x06object\x12\x1C\x0A\x09newschema\x18\x04 \x01(\x09R\x09newschema\x12\x1E\x0A\x0Amissing_ok\x18\x05 \x01(\x08R\x0Amissing_ok\"\xCF\x01\x0A\x0EAlterOwnerStmt\x125\x0A\x0Bobject_type\x18\x01 \x01(\x0E2\x14.pg_query.ObjectTypeR\x0AobjectType\x12.\x0A\x08relation\x18\x02 \x01(\x0B2\x12.pg_query.RangeVarR\x08relation\x12&\x0A\x06object\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x06object\x12.\x0A\x08newowner\x18\x04 \x01(\x0B2\x12.pg_query.RoleSpecR\x08newowner\"s\x0A\x11AlterOperatorStmt\x124\x0A\x08opername\x18\x01 \x01(\x0B2\x18.pg_query.ObjectWithArgsR\x08opername\x12(\x0A\x07options\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x07options\"f\x0A\x0DAlterTypeStmt\x12+\x0A\x09type_name\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x08typeName\x12(\x0A\x07options\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x07options\"\x90\x02\x0A\x08RuleStmt\x12.\x0A\x08relation\x18\x01 \x01(\x0B2\x12.pg_query.RangeVarR\x08relation\x12\x1A\x0A\x08rulename\x18\x02 \x01(\x09R\x08rulename\x121\x0A\x0Cwhere_clause\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x0BwhereClause\x12'\x0A\x05event\x18\x04 \x01(\x0E2\x11.pg_query.CmdTypeR\x05event\x12\x18\x0A\x07instead\x18\x05 \x01(\x08R\x07instead\x12(\x0A\x07actions\x18\x06 \x03(\x0B2\x0E.pg_query.NodeR\x07actions\x12\x18\x0A\x07replace\x18\x07 \x01(\x08R\x07replace\"L\x0A\x0ANotifyStmt\x12\$\x0A\x0Dconditionname\x18\x01 \x01(\x09R\x0Dconditionname\x12\x18\x0A\x07payload\x18\x02 \x01(\x09R\x07payload\"2\x0A\x0AListenStmt\x12\$\x0A\x0Dconditionname\x18\x01 \x01(\x09R\x0Dconditionname\"4\x0A\x0CUnlistenStmt\x12\$\x0A\x0Dconditionname\x18\x01 \x01(\x09R\x0Dconditionname\"\xDA\x01\x0A\x0FTransactionStmt\x121\x0A\x04kind\x18\x01 \x01(\x0E2\x1D.pg_query.TransactionStmtKindR\x04kind\x12(\x0A\x07options\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x07options\x12&\x0A\x0Esavepoint_name\x18\x03 \x01(\x09R\x0Esavepoint_name\x12\x10\x0A\x03gid\x18\x04 \x01(\x09R\x03gid\x12\x14\x0A\x05chain\x18\x05 \x01(\x08R\x05chain\x12\x1A\x0A\x08location\x18\x06 \x01(\x05R\x08location\"q\x0A\x11CompositeTypeStmt\x12,\x0A\x07typevar\x18\x01 \x01(\x0B2\x12.pg_query.RangeVarR\x07typevar\x12.\x0A\x0Acoldeflist\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x0Acoldeflist\"a\x0A\x0ECreateEnumStmt\x12+\x0A\x09type_name\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x08typeName\x12\"\x0A\x04vals\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x04vals\"f\x0A\x0FCreateRangeStmt\x12+\x0A\x09type_name\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x08typeName\x12&\x0A\x06params\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x06params\"\xF5\x01\x0A\x0DAlterEnumStmt\x12+\x0A\x09type_name\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x08typeName\x12\x17\x0A\x07old_val\x18\x02 \x01(\x09R\x06oldVal\x12\x17\x0A\x07new_val\x18\x03 \x01(\x09R\x06newVal\x12(\x0A\x10new_val_neighbor\x18\x04 \x01(\x09R\x0EnewValNeighbor\x12'\x0A\x10new_val_is_after\x18\x05 \x01(\x08R\x0DnewValIsAfter\x122\x0A\x16skip_if_new_val_exists\x18\x06 \x01(\x08R\x12skipIfNewValExists\"\x8D\x02\x0A\x08ViewStmt\x12&\x0A\x04view\x18\x01 \x01(\x0B2\x12.pg_query.RangeVarR\x04view\x12(\x0A\x07aliases\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x07aliases\x12\$\x0A\x05query\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x05query\x12\x18\x0A\x07replace\x18\x04 \x01(\x08R\x07replace\x12(\x0A\x07options\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x07options\x12E\x0A\x11with_check_option\x18\x06 \x01(\x0E2\x19.pg_query.ViewCheckOptionR\x0FwithCheckOption\"&\x0A\x08LoadStmt\x12\x1A\x0A\x08filename\x18\x01 \x01(\x09R\x08filename\"P\x0A\x0CCreatedbStmt\x12\x16\x0A\x06dbname\x18\x01 \x01(\x09R\x06dbname\x12(\x0A\x07options\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x07options\"U\x0A\x11AlterDatabaseStmt\x12\x16\x0A\x06dbname\x18\x01 \x01(\x09R\x06dbname\x12(\x0A\x07options\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x07options\"6\x0A\x1CAlterDatabaseRefreshCollStmt\x12\x16\x0A\x06dbname\x18\x01 \x01(\x09R\x06dbname\"c\x0A\x14AlterDatabaseSetStmt\x12\x16\x0A\x06dbname\x18\x01 \x01(\x09R\x06dbname\x123\x0A\x07setstmt\x18\x02 \x01(\x0B2\x19.pg_query.VariableSetStmtR\x07setstmt\"n\x0A\x0ADropdbStmt\x12\x16\x0A\x06dbname\x18\x01 \x01(\x09R\x06dbname\x12\x1E\x0A\x0Amissing_ok\x18\x02 \x01(\x08R\x0Amissing_ok\x12(\x0A\x07options\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x07options\"F\x0A\x0FAlterSystemStmt\x123\x0A\x07setstmt\x18\x01 \x01(\x0B2\x19.pg_query.VariableSetStmtR\x07setstmt\"\x83\x01\x0A\x0BClusterStmt\x12.\x0A\x08relation\x18\x01 \x01(\x0B2\x12.pg_query.RangeVarR\x08relation\x12\x1C\x0A\x09indexname\x18\x02 \x01(\x09R\x09indexname\x12&\x0A\x06params\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x06params\"~\x0A\x0AVacuumStmt\x12(\x0A\x07options\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x07options\x12\"\x0A\x04rels\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x04rels\x12\"\x0A\x0Cis_vacuumcmd\x18\x03 \x01(\x08R\x0Cis_vacuumcmd\"|\x0A\x0EVacuumRelation\x12.\x0A\x08relation\x18\x01 \x01(\x0B2\x12.pg_query.RangeVarR\x08relation\x12\x10\x0A\x03oid\x18\x02 \x01(\x0DR\x03oid\x12(\x0A\x07va_cols\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x07va_cols\"]\x0A\x0BExplainStmt\x12\$\x0A\x05query\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x05query\x12(\x0A\x07options\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x07options\"\xE1\x01\x0A\x11CreateTableAsStmt\x12\$\x0A\x05query\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x05query\x12(\x0A\x04into\x18\x02 \x01(\x0B2\x14.pg_query.IntoClauseR\x04into\x12.\x0A\x07objtype\x18\x03 \x01(\x0E2\x14.pg_query.ObjectTypeR\x07objtype\x12&\x0A\x0Eis_select_into\x18\x04 \x01(\x08R\x0Eis_select_into\x12\$\x0A\x0Dif_not_exists\x18\x05 \x01(\x08R\x0Dif_not_exists\"\x81\x01\x0A\x12RefreshMatViewStmt\x12\x1E\x0A\x0Aconcurrent\x18\x01 \x01(\x08R\x0Aconcurrent\x12\x1B\x0A\x09skip_data\x18\x02 \x01(\x08R\x08skipData\x12.\x0A\x08relation\x18\x03 \x01(\x0B2\x12.pg_query.RangeVarR\x08relation\"\x10\x0A\x0ECheckPointStmt\"<\x0A\x0BDiscardStmt\x12-\x0A\x06target\x18\x01 \x01(\x0E2\x15.pg_query.DiscardModeR\x06target\"d\x0A\x08LockStmt\x12,\x0A\x09relations\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x09relations\x12\x12\x0A\x04mode\x18\x02 \x01(\x05R\x04mode\x12\x16\x0A\x06nowait\x18\x03 \x01(\x08R\x06nowait\"b\x0A\x12ConstraintsSetStmt\x120\x0A\x0Bconstraints\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x0Bconstraints\x12\x1A\x0A\x08deferred\x18\x02 \x01(\x08R\x08deferred\"\xAA\x01\x0A\x0BReindexStmt\x12/\x0A\x04kind\x18\x01 \x01(\x0E2\x1B.pg_query.ReindexObjectTypeR\x04kind\x12.\x0A\x08relation\x18\x02 \x01(\x0B2\x12.pg_query.RangeVarR\x08relation\x12\x12\x0A\x04name\x18\x03 \x01(\x09R\x04name\x12&\x0A\x06params\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x06params\"\xEA\x01\x0A\x14CreateConversionStmt\x128\x0A\x0Fconversion_name\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x0Fconversion_name\x12,\x0A\x11for_encoding_name\x18\x02 \x01(\x09R\x11for_encoding_name\x12*\x0A\x10to_encoding_name\x18\x03 \x01(\x09R\x10to_encoding_name\x12,\x0A\x09func_name\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x09func_name\x12\x10\x0A\x03def\x18\x05 \x01(\x08R\x03def\"\xF1\x01\x0A\x0ECreateCastStmt\x122\x0A\x0Asourcetype\x18\x01 \x01(\x0B2\x12.pg_query.TypeNameR\x0Asourcetype\x122\x0A\x0Atargettype\x18\x02 \x01(\x0B2\x12.pg_query.TypeNameR\x0Atargettype\x12,\x0A\x04func\x18\x03 \x01(\x0B2\x18.pg_query.ObjectWithArgsR\x04func\x123\x0A\x07context\x18\x04 \x01(\x0E2\x19.pg_query.CoercionContextR\x07context\x12\x14\x0A\x05inout\x18\x05 \x01(\x08R\x05inout\"\xD9\x01\x0A\x13CreateTransformStmt\x12\x18\x0A\x07replace\x18\x01 \x01(\x08R\x07replace\x120\x0A\x09type_name\x18\x02 \x01(\x0B2\x12.pg_query.TypeNameR\x09type_name\x12\x12\x0A\x04lang\x18\x03 \x01(\x09R\x04lang\x122\x0A\x07fromsql\x18\x04 \x01(\x0B2\x18.pg_query.ObjectWithArgsR\x07fromsql\x12.\x0A\x05tosql\x18\x05 \x01(\x0B2\x18.pg_query.ObjectWithArgsR\x05tosql\"s\x0A\x0BPrepareStmt\x12\x12\x0A\x04name\x18\x01 \x01(\x09R\x04name\x12*\x0A\x08argtypes\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x08argtypes\x12\$\x0A\x05query\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x05query\"I\x0A\x0BExecuteStmt\x12\x12\x0A\x04name\x18\x01 \x01(\x09R\x04name\x12&\x0A\x06params\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x06params\"V\x0A\x0EDeallocateStmt\x12\x12\x0A\x04name\x18\x01 \x01(\x09R\x04name\x12\x14\x0A\x05isall\x18\x02 \x01(\x08R\x05isall\x12\x1A\x0A\x08location\x18\x03 \x01(\x05R\x08location\"i\x0A\x0DDropOwnedStmt\x12\$\x0A\x05roles\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x05roles\x122\x0A\x08behavior\x18\x02 \x01(\x0E2\x16.pg_query.DropBehaviorR\x08behavior\"g\x0A\x11ReassignOwnedStmt\x12\$\x0A\x05roles\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x05roles\x12,\x0A\x07newrole\x18\x02 \x01(\x0B2\x12.pg_query.RoleSpecR\x07newrole\"m\x0A\x15AlterTSDictionaryStmt\x12*\x0A\x08dictname\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x08dictname\x12(\x0A\x07options\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x07options\"\x9F\x02\x0A\x18AlterTSConfigurationStmt\x12/\x0A\x04kind\x18\x01 \x01(\x0E2\x1B.pg_query.AlterTSConfigTypeR\x04kind\x12(\x0A\x07cfgname\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x07cfgname\x12,\x0A\x09tokentype\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x09tokentype\x12\$\x0A\x05dicts\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x05dicts\x12\x1A\x0A\x08override\x18\x05 \x01(\x08R\x08override\x12\x18\x0A\x07replace\x18\x06 \x01(\x08R\x07replace\x12\x1E\x0A\x0Amissing_ok\x18\x07 \x01(\x08R\x0Amissing_ok\"\x9F\x01\x0A\x10PublicationTable\x12.\x0A\x08relation\x18\x01 \x01(\x0B2\x12.pg_query.RangeVarR\x08relation\x121\x0A\x0Cwhere_clause\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x0BwhereClause\x12(\x0A\x07columns\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x07columns\"\xBE\x01\x0A\x12PublicationObjSpec\x12@\x0A\x0Apubobjtype\x18\x01 \x01(\x0E2 .pg_query.PublicationObjSpecTypeR\x0Apubobjtype\x12\x12\x0A\x04name\x18\x02 \x01(\x09R\x04name\x126\x0A\x08pubtable\x18\x03 \x01(\x0B2\x1A.pg_query.PublicationTableR\x08pubtable\x12\x1A\x0A\x08location\x18\x04 \x01(\x05R\x08location\"\xB3\x01\x0A\x15CreatePublicationStmt\x12\x18\x0A\x07pubname\x18\x01 \x01(\x09R\x07pubname\x12(\x0A\x07options\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x07options\x12.\x0A\x0Apubobjects\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x0Apubobjects\x12&\x0A\x0Efor_all_tables\x18\x04 \x01(\x08R\x0Efor_all_tables\"\xEC\x01\x0A\x14AlterPublicationStmt\x12\x18\x0A\x07pubname\x18\x01 \x01(\x09R\x07pubname\x12(\x0A\x07options\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x07options\x12.\x0A\x0Apubobjects\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x0Apubobjects\x12&\x0A\x0Efor_all_tables\x18\x04 \x01(\x08R\x0Efor_all_tables\x128\x0A\x06action\x18\x05 \x01(\x0E2 .pg_query.AlterPublicationActionR\x06action\"\xAA\x01\x0A\x16CreateSubscriptionStmt\x12\x18\x0A\x07subname\x18\x01 \x01(\x09R\x07subname\x12\x1A\x0A\x08conninfo\x18\x02 \x01(\x09R\x08conninfo\x120\x0A\x0Bpublication\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x0Bpublication\x12(\x0A\x07options\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x07options\"\xDE\x01\x0A\x15AlterSubscriptionStmt\x123\x0A\x04kind\x18\x01 \x01(\x0E2\x1F.pg_query.AlterSubscriptionTypeR\x04kind\x12\x18\x0A\x07subname\x18\x02 \x01(\x09R\x07subname\x12\x1A\x0A\x08conninfo\x18\x03 \x01(\x09R\x08conninfo\x120\x0A\x0Bpublication\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x0Bpublication\x12(\x0A\x07options\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x07options\"\x84\x01\x0A\x14DropSubscriptionStmt\x12\x18\x0A\x07subname\x18\x01 \x01(\x09R\x07subname\x12\x1E\x0A\x0Amissing_ok\x18\x02 \x01(\x08R\x0Amissing_ok\x122\x0A\x08behavior\x18\x03 \x01(\x0E2\x16.pg_query.DropBehaviorR\x08behavior\"t\x0A\x09ScanToken\x12\x0D\x0A\x05start\x18\x01 \x01(\x05\x12\x0B\x0A\x03end\x18\x02 \x01(\x05\x12\x1E\x0A\x05token\x18\x04 \x01(\x0E2\x0F.pg_query.Token\x12+\x0A\x0Ckeyword_kind\x18\x05 \x01(\x0E2\x15.pg_query.KeywordKind*\x9B\x01\x0A\x0BQuerySource\x12\x1A\x0A\x16QUERY_SOURCE_UNDEFINED\x10\x00\x12\x11\x0A\x0DQSRC_ORIGINAL\x10\x01\x12\x0F\x0A\x0BQSRC_PARSER\x10\x02\x12\x15\x0A\x11QSRC_INSTEAD_RULE\x10\x03\x12\x1A\x0A\x16QSRC_QUAL_INSTEAD_RULE\x10\x04\x12\x19\x0A\x15QSRC_NON_INSTEAD_RULE\x10\x05*m\x0A\x09SortByDir\x12\x19\x0A\x15SORT_BY_DIR_UNDEFINED\x10\x00\x12\x12\x0A\x0ESORTBY_DEFAULT\x10\x01\x12\x0E\x0A\x0ASORTBY_ASC\x10\x02\x12\x0F\x0A\x0BSORTBY_DESC\x10\x03\x12\x10\x0A\x0CSORTBY_USING\x10\x04*s\x0A\x0BSortByNulls\x12\x1B\x0A\x17SORT_BY_NULLS_UNDEFINED\x10\x00\x12\x18\x0A\x14SORTBY_NULLS_DEFAULT\x10\x01\x12\x16\x0A\x12SORTBY_NULLS_FIRST\x10\x02\x12\x15\x0A\x11SORTBY_NULLS_LAST\x10\x03*~\x0A\x0DSetQuantifier\x12\x1C\x0A\x18SET_QUANTIFIER_UNDEFINED\x10\x00\x12\x1A\x0A\x16SET_QUANTIFIER_DEFAULT\x10\x01\x12\x16\x0A\x12SET_QUANTIFIER_ALL\x10\x02\x12\x1B\x0A\x17SET_QUANTIFIER_DISTINCT\x10\x03*\xB6\x02\x0A\x0BA_Expr_Kind\x12\x19\x0A\x15A_EXPR_KIND_UNDEFINED\x10\x00\x12\x0C\x0A\x08AEXPR_OP\x10\x01\x12\x10\x0A\x0CAEXPR_OP_ANY\x10\x02\x12\x10\x0A\x0CAEXPR_OP_ALL\x10\x03\x12\x12\x0A\x0EAEXPR_DISTINCT\x10\x04\x12\x16\x0A\x12AEXPR_NOT_DISTINCT\x10\x05\x12\x10\x0A\x0CAEXPR_NULLIF\x10\x06\x12\x0C\x0A\x08AEXPR_IN\x10\x07\x12\x0E\x0A\x0AAEXPR_LIKE\x10\x08\x12\x0F\x0A\x0BAEXPR_ILIKE\x10\x09\x12\x11\x0A\x0DAEXPR_SIMILAR\x10\x0A\x12\x11\x0A\x0DAEXPR_BETWEEN\x10\x0B\x12\x15\x0A\x11AEXPR_NOT_BETWEEN\x10\x0C\x12\x15\x0A\x11AEXPR_BETWEEN_SYM\x10\x0D\x12\x19\x0A\x15AEXPR_NOT_BETWEEN_SYM\x10\x0E*\xA8\x01\x0A\x0CRoleSpecType\x12\x1C\x0A\x18ROLE_SPEC_TYPE_UNDEFINED\x10\x00\x12\x14\x0A\x10ROLESPEC_CSTRING\x10\x01\x12\x19\x0A\x15ROLESPEC_CURRENT_ROLE\x10\x02\x12\x19\x0A\x15ROLESPEC_CURRENT_USER\x10\x03\x12\x19\x0A\x15ROLESPEC_SESSION_USER\x10\x04\x12\x13\x0A\x0FROLESPEC_PUBLIC\x10\x05*\xF4\x02\x0A\x0FTableLikeOption\x12\x1F\x0A\x1BTABLE_LIKE_OPTION_UNDEFINED\x10\x00\x12\x1E\x0A\x1ACREATE_TABLE_LIKE_COMMENTS\x10\x01\x12!\x0A\x1DCREATE_TABLE_LIKE_COMPRESSION\x10\x02\x12!\x0A\x1DCREATE_TABLE_LIKE_CONSTRAINTS\x10\x03\x12\x1E\x0A\x1ACREATE_TABLE_LIKE_DEFAULTS\x10\x04\x12\x1F\x0A\x1BCREATE_TABLE_LIKE_GENERATED\x10\x05\x12\x1E\x0A\x1ACREATE_TABLE_LIKE_IDENTITY\x10\x06\x12\x1D\x0A\x19CREATE_TABLE_LIKE_INDEXES\x10\x07\x12 \x0A\x1CCREATE_TABLE_LIKE_STATISTICS\x10\x08\x12\x1D\x0A\x19CREATE_TABLE_LIKE_STORAGE\x10\x09\x12\x19\x0A\x15CREATE_TABLE_LIKE_ALL\x10\x0A*v\x0A\x0DDefElemAction\x12\x1D\x0A\x19DEF_ELEM_ACTION_UNDEFINED\x10\x00\x12\x12\x0A\x0EDEFELEM_UNSPEC\x10\x01\x12\x0F\x0A\x0BDEFELEM_SET\x10\x02\x12\x0F\x0A\x0BDEFELEM_ADD\x10\x03\x12\x10\x0A\x0CDEFELEM_DROP\x10\x04*\x8D\x01\x0A\x11PartitionStrategy\x12 \x0A\x1CPARTITION_STRATEGY_UNDEFINED\x10\x00\x12\x1B\x0A\x17PARTITION_STRATEGY_LIST\x10\x01\x12\x1C\x0A\x18PARTITION_STRATEGY_RANGE\x10\x02\x12\x1B\x0A\x17PARTITION_STRATEGY_HASH\x10\x03*\xAC\x01\x0A\x17PartitionRangeDatumKind\x12(\x0A\$PARTITION_RANGE_DATUM_KIND_UNDEFINED\x10\x00\x12\"\x0A\x1EPARTITION_RANGE_DATUM_MINVALUE\x10\x01\x12\x1F\x0A\x1BPARTITION_RANGE_DATUM_VALUE\x10\x02\x12\"\x0A\x1EPARTITION_RANGE_DATUM_MAXVALUE\x10\x03*\xBD\x01\x0A\x07RTEKind\x12\x15\x0A\x11RTEKIND_UNDEFINED\x10\x00\x12\x10\x0A\x0CRTE_RELATION\x10\x01\x12\x10\x0A\x0CRTE_SUBQUERY\x10\x02\x12\x0C\x0A\x08RTE_JOIN\x10\x03\x12\x10\x0A\x0CRTE_FUNCTION\x10\x04\x12\x11\x0A\x0DRTE_TABLEFUNC\x10\x05\x12\x0E\x0A\x0ARTE_VALUES\x10\x06\x12\x0B\x0A\x07RTE_CTE\x10\x07\x12\x17\x0A\x13RTE_NAMEDTUPLESTORE\x10\x08\x12\x0E\x0A\x0ARTE_RESULT\x10\x09*\xC4\x01\x0A\x07WCOKind\x12\x15\x0A\x11WCOKIND_UNDEFINED\x10\x00\x12\x12\x0A\x0EWCO_VIEW_CHECK\x10\x01\x12\x18\x0A\x14WCO_RLS_INSERT_CHECK\x10\x02\x12\x18\x0A\x14WCO_RLS_UPDATE_CHECK\x10\x03\x12\x1A\x0A\x16WCO_RLS_CONFLICT_CHECK\x10\x04\x12\x1E\x0A\x1AWCO_RLS_MERGE_UPDATE_CHECK\x10\x05\x12\x1E\x0A\x1AWCO_RLS_MERGE_DELETE_CHECK\x10\x06*\xAA\x01\x0A\x0FGroupingSetKind\x12\x1F\x0A\x1BGROUPING_SET_KIND_UNDEFINED\x10\x00\x12\x16\x0A\x12GROUPING_SET_EMPTY\x10\x01\x12\x17\x0A\x13GROUPING_SET_SIMPLE\x10\x02\x12\x17\x0A\x13GROUPING_SET_ROLLUP\x10\x03\x12\x15\x0A\x11GROUPING_SET_CUBE\x10\x04\x12\x15\x0A\x11GROUPING_SET_SETS\x10\x05*|\x0A\x0ECTEMaterialize\x12\x1C\x0A\x18CTEMATERIALIZE_UNDEFINED\x10\x00\x12\x19\x0A\x15CTEMaterializeDefault\x10\x01\x12\x18\x0A\x14CTEMaterializeAlways\x10\x02\x12\x17\x0A\x13CTEMaterializeNever\x10\x03*e\x0A\x0AJsonQuotes\x12\x19\x0A\x15JSON_QUOTES_UNDEFINED\x10\x00\x12\x14\x0A\x10JS_QUOTES_UNSPEC\x10\x01\x12\x12\x0A\x0EJS_QUOTES_KEEP\x10\x02\x12\x12\x0A\x0EJS_QUOTES_OMIT\x10\x03*\x97\x01\x0A\x13JsonTableColumnType\x12\$\x0A JSON_TABLE_COLUMN_TYPE_UNDEFINED\x10\x00\x12\x16\x0A\x12JTC_FOR_ORDINALITY\x10\x01\x12\x0F\x0A\x0BJTC_REGULAR\x10\x02\x12\x0E\x0A\x0AJTC_EXISTS\x10\x03\x12\x11\x0A\x0DJTC_FORMATTED\x10\x04\x12\x0E\x0A\x0AJTC_NESTED\x10\x05*s\x0A\x0CSetOperation\x12\x1B\x0A\x17SET_OPERATION_UNDEFINED\x10\x00\x12\x0E\x0A\x0ASETOP_NONE\x10\x01\x12\x0F\x0A\x0BSETOP_UNION\x10\x02\x12\x13\x0A\x0FSETOP_INTERSECT\x10\x03\x12\x10\x0A\x0CSETOP_EXCEPT\x10\x04*\x99\x09\x0A\x0AObjectType\x12\x19\x0A\x15OBJECT_TYPE_UNDEFINED\x10\x00\x12\x18\x0A\x14OBJECT_ACCESS_METHOD\x10\x01\x12\x14\x0A\x10OBJECT_AGGREGATE\x10\x02\x12\x0F\x0A\x0BOBJECT_AMOP\x10\x03\x12\x11\x0A\x0DOBJECT_AMPROC\x10\x04\x12\x14\x0A\x10OBJECT_ATTRIBUTE\x10\x05\x12\x0F\x0A\x0BOBJECT_CAST\x10\x06\x12\x11\x0A\x0DOBJECT_COLUMN\x10\x07\x12\x14\x0A\x10OBJECT_COLLATION\x10\x08\x12\x15\x0A\x11OBJECT_CONVERSION\x10\x09\x12\x13\x0A\x0FOBJECT_DATABASE\x10\x0A\x12\x12\x0A\x0EOBJECT_DEFAULT\x10\x0B\x12\x11\x0A\x0DOBJECT_DEFACL\x10\x0C\x12\x11\x0A\x0DOBJECT_DOMAIN\x10\x0D\x12\x18\x0A\x14OBJECT_DOMCONSTRAINT\x10\x0E\x12\x18\x0A\x14OBJECT_EVENT_TRIGGER\x10\x0F\x12\x14\x0A\x10OBJECT_EXTENSION\x10\x10\x12\x0E\x0A\x0AOBJECT_FDW\x10\x11\x12\x19\x0A\x15OBJECT_FOREIGN_SERVER\x10\x12\x12\x18\x0A\x14OBJECT_FOREIGN_TABLE\x10\x13\x12\x13\x0A\x0FOBJECT_FUNCTION\x10\x14\x12\x10\x0A\x0COBJECT_INDEX\x10\x15\x12\x13\x0A\x0FOBJECT_LANGUAGE\x10\x16\x12\x16\x0A\x12OBJECT_LARGEOBJECT\x10\x17\x12\x12\x0A\x0EOBJECT_MATVIEW\x10\x18\x12\x12\x0A\x0EOBJECT_OPCLASS\x10\x19\x12\x13\x0A\x0FOBJECT_OPERATOR\x10\x1A\x12\x13\x0A\x0FOBJECT_OPFAMILY\x10\x1B\x12\x18\x0A\x14OBJECT_PARAMETER_ACL\x10\x1C\x12\x11\x0A\x0DOBJECT_POLICY\x10\x1D\x12\x14\x0A\x10OBJECT_PROCEDURE\x10\x1E\x12\x16\x0A\x12OBJECT_PUBLICATION\x10\x1F\x12 \x0A\x1COBJECT_PUBLICATION_NAMESPACE\x10 \x12\x1A\x0A\x16OBJECT_PUBLICATION_REL\x10!\x12\x0F\x0A\x0BOBJECT_ROLE\x10\"\x12\x12\x0A\x0EOBJECT_ROUTINE\x10#\x12\x0F\x0A\x0BOBJECT_RULE\x10\$\x12\x11\x0A\x0DOBJECT_SCHEMA\x10%\x12\x13\x0A\x0FOBJECT_SEQUENCE\x10&\x12\x17\x0A\x13OBJECT_SUBSCRIPTION\x10'\x12\x18\x0A\x14OBJECT_STATISTIC_EXT\x10(\x12\x18\x0A\x14OBJECT_TABCONSTRAINT\x10)\x12\x10\x0A\x0COBJECT_TABLE\x10*\x12\x15\x0A\x11OBJECT_TABLESPACE\x10+\x12\x14\x0A\x10OBJECT_TRANSFORM\x10,\x12\x12\x0A\x0EOBJECT_TRIGGER\x10-\x12\x1A\x0A\x16OBJECT_TSCONFIGURATION\x10.\x12\x17\x0A\x13OBJECT_TSDICTIONARY\x10/\x12\x13\x0A\x0FOBJECT_TSPARSER\x100\x12\x15\x0A\x11OBJECT_TSTEMPLATE\x101\x12\x0F\x0A\x0BOBJECT_TYPE\x102\x12\x17\x0A\x13OBJECT_USER_MAPPING\x103\x12\x0F\x0A\x0BOBJECT_VIEW\x104*P\x0A\x0CDropBehavior\x12\x1B\x0A\x17DROP_BEHAVIOR_UNDEFINED\x10\x00\x12\x11\x0A\x0DDROP_RESTRICT\x10\x01\x12\x10\x0A\x0CDROP_CASCADE\x10\x02*\x8C\x0C\x0A\x0EAlterTableType\x12\x1E\x0A\x1AALTER_TABLE_TYPE_UNDEFINED\x10\x00\x12\x10\x0A\x0CAT_AddColumn\x10\x01\x12\x16\x0A\x12AT_AddColumnToView\x10\x02\x12\x14\x0A\x10AT_ColumnDefault\x10\x03\x12\x1A\x0A\x16AT_CookedColumnDefault\x10\x04\x12\x12\x0A\x0EAT_DropNotNull\x10\x05\x12\x11\x0A\x0DAT_SetNotNull\x10\x06\x12\x14\x0A\x10AT_SetExpression\x10\x07\x12\x15\x0A\x11AT_DropExpression\x10\x08\x12\x13\x0A\x0FAT_CheckNotNull\x10\x09\x12\x14\x0A\x10AT_SetStatistics\x10\x0A\x12\x11\x0A\x0DAT_SetOptions\x10\x0B\x12\x13\x0A\x0FAT_ResetOptions\x10\x0C\x12\x11\x0A\x0DAT_SetStorage\x10\x0D\x12\x15\x0A\x11AT_SetCompression\x10\x0E\x12\x11\x0A\x0DAT_DropColumn\x10\x0F\x12\x0F\x0A\x0BAT_AddIndex\x10\x10\x12\x11\x0A\x0DAT_ReAddIndex\x10\x11\x12\x14\x0A\x10AT_AddConstraint\x10\x12\x12\x16\x0A\x12AT_ReAddConstraint\x10\x13\x12\x1C\x0A\x18AT_ReAddDomainConstraint\x10\x14\x12\x16\x0A\x12AT_AlterConstraint\x10\x15\x12\x19\x0A\x15AT_ValidateConstraint\x10\x16\x12\x19\x0A\x15AT_AddIndexConstraint\x10\x17\x12\x15\x0A\x11AT_DropConstraint\x10\x18\x12\x13\x0A\x0FAT_ReAddComment\x10\x19\x12\x16\x0A\x12AT_AlterColumnType\x10\x1A\x12 \x0A\x1CAT_AlterColumnGenericOptions\x10\x1B\x12\x12\x0A\x0EAT_ChangeOwner\x10\x1C\x12\x10\x0A\x0CAT_ClusterOn\x10\x1D\x12\x12\x0A\x0EAT_DropCluster\x10\x1E\x12\x10\x0A\x0CAT_SetLogged\x10\x1F\x12\x12\x0A\x0EAT_SetUnLogged\x10 \x12\x0F\x0A\x0BAT_DropOids\x10!\x12\x16\x0A\x12AT_SetAccessMethod\x10\"\x12\x14\x0A\x10AT_SetTableSpace\x10#\x12\x14\x0A\x10AT_SetRelOptions\x10\$\x12\x16\x0A\x12AT_ResetRelOptions\x10%\x12\x18\x0A\x14AT_ReplaceRelOptions\x10&\x12\x11\x0A\x0DAT_EnableTrig\x10'\x12\x17\x0A\x13AT_EnableAlwaysTrig\x10(\x12\x18\x0A\x14AT_EnableReplicaTrig\x10)\x12\x12\x0A\x0EAT_DisableTrig\x10*\x12\x14\x0A\x10AT_EnableTrigAll\x10+\x12\x15\x0A\x11AT_DisableTrigAll\x10,\x12\x15\x0A\x11AT_EnableTrigUser\x10-\x12\x16\x0A\x12AT_DisableTrigUser\x10.\x12\x11\x0A\x0DAT_EnableRule\x10/\x12\x17\x0A\x13AT_EnableAlwaysRule\x100\x12\x18\x0A\x14AT_EnableReplicaRule\x101\x12\x12\x0A\x0EAT_DisableRule\x102\x12\x11\x0A\x0DAT_AddInherit\x103\x12\x12\x0A\x0EAT_DropInherit\x104\x12\x0C\x0A\x08AT_AddOf\x105\x12\x0D\x0A\x09AT_DropOf\x106\x12\x16\x0A\x12AT_ReplicaIdentity\x107\x12\x18\x0A\x14AT_EnableRowSecurity\x108\x12\x19\x0A\x15AT_DisableRowSecurity\x109\x12\x17\x0A\x13AT_ForceRowSecurity\x10:\x12\x19\x0A\x15AT_NoForceRowSecurity\x10;\x12\x15\x0A\x11AT_GenericOptions\x10<\x12\x16\x0A\x12AT_AttachPartition\x10=\x12\x16\x0A\x12AT_DetachPartition\x10>\x12\x1E\x0A\x1AAT_DetachPartitionFinalize\x10?\x12\x12\x0A\x0EAT_AddIdentity\x10@\x12\x12\x0A\x0EAT_SetIdentity\x10A\x12\x13\x0A\x0FAT_DropIdentity\x10B\x12\x16\x0A\x12AT_ReAddStatistics\x10C*\x80\x01\x0A\x0FGrantTargetType\x12\x1F\x0A\x1BGRANT_TARGET_TYPE_UNDEFINED\x10\x00\x12\x15\x0A\x11ACL_TARGET_OBJECT\x10\x01\x12\x1C\x0A\x18ACL_TARGET_ALL_IN_SCHEMA\x10\x02\x12\x17\x0A\x13ACL_TARGET_DEFAULTS\x10\x03*\xA4\x01\x0A\x0FVariableSetKind\x12\x1F\x0A\x1BVARIABLE_SET_KIND_UNDEFINED\x10\x00\x12\x11\x0A\x0DVAR_SET_VALUE\x10\x01\x12\x13\x0A\x0FVAR_SET_DEFAULT\x10\x02\x12\x13\x0A\x0FVAR_SET_CURRENT\x10\x03\x12\x11\x0A\x0DVAR_SET_MULTI\x10\x04\x12\x0D\x0A\x09VAR_RESET\x10\x05\x12\x11\x0A\x0DVAR_RESET_ALL\x10\x06*\xDF\x02\x0A\x0AConstrType\x12\x19\x0A\x15CONSTR_TYPE_UNDEFINED\x10\x00\x12\x0F\x0A\x0BCONSTR_NULL\x10\x01\x12\x12\x0A\x0ECONSTR_NOTNULL\x10\x02\x12\x12\x0A\x0ECONSTR_DEFAULT\x10\x03\x12\x13\x0A\x0FCONSTR_IDENTITY\x10\x04\x12\x14\x0A\x10CONSTR_GENERATED\x10\x05\x12\x10\x0A\x0CCONSTR_CHECK\x10\x06\x12\x12\x0A\x0ECONSTR_PRIMARY\x10\x07\x12\x11\x0A\x0DCONSTR_UNIQUE\x10\x08\x12\x14\x0A\x10CONSTR_EXCLUSION\x10\x09\x12\x12\x0A\x0ECONSTR_FOREIGN\x10\x0A\x12\x1A\x0A\x16CONSTR_ATTR_DEFERRABLE\x10\x0B\x12\x1E\x0A\x1ACONSTR_ATTR_NOT_DEFERRABLE\x10\x0C\x12\x18\x0A\x14CONSTR_ATTR_DEFERRED\x10\x0D\x12\x19\x0A\x15CONSTR_ATTR_IMMEDIATE\x10\x0E*\x9C\x01\x0A\x17ImportForeignSchemaType\x12(\x0A\$IMPORT_FOREIGN_SCHEMA_TYPE_UNDEFINED\x10\x00\x12\x19\x0A\x15FDW_IMPORT_SCHEMA_ALL\x10\x01\x12\x1E\x0A\x1AFDW_IMPORT_SCHEMA_LIMIT_TO\x10\x02\x12\x1C\x0A\x18FDW_IMPORT_SCHEMA_EXCEPT\x10\x03*f\x0A\x0CRoleStmtType\x12\x1C\x0A\x18ROLE_STMT_TYPE_UNDEFINED\x10\x00\x12\x11\x0A\x0DROLESTMT_ROLE\x10\x01\x12\x11\x0A\x0DROLESTMT_USER\x10\x02\x12\x12\x0A\x0EROLESTMT_GROUP\x10\x03*~\x0A\x0EFetchDirection\x12\x1D\x0A\x19FETCH_DIRECTION_UNDEFINED\x10\x00\x12\x11\x0A\x0DFETCH_FORWARD\x10\x01\x12\x12\x0A\x0EFETCH_BACKWARD\x10\x02\x12\x12\x0A\x0EFETCH_ABSOLUTE\x10\x03\x12\x12\x0A\x0EFETCH_RELATIVE\x10\x04*\xC2\x01\x0A\x15FunctionParameterMode\x12%\x0A!FUNCTION_PARAMETER_MODE_UNDEFINED\x10\x00\x12\x11\x0A\x0DFUNC_PARAM_IN\x10\x01\x12\x12\x0A\x0EFUNC_PARAM_OUT\x10\x02\x12\x14\x0A\x10FUNC_PARAM_INOUT\x10\x03\x12\x17\x0A\x13FUNC_PARAM_VARIADIC\x10\x04\x12\x14\x0A\x10FUNC_PARAM_TABLE\x10\x05\x12\x16\x0A\x12FUNC_PARAM_DEFAULT\x10\x06*\xBE\x02\x0A\x13TransactionStmtKind\x12#\x0A\x1FTRANSACTION_STMT_KIND_UNDEFINED\x10\x00\x12\x14\x0A\x10TRANS_STMT_BEGIN\x10\x01\x12\x14\x0A\x10TRANS_STMT_START\x10\x02\x12\x15\x0A\x11TRANS_STMT_COMMIT\x10\x03\x12\x17\x0A\x13TRANS_STMT_ROLLBACK\x10\x04\x12\x18\x0A\x14TRANS_STMT_SAVEPOINT\x10\x05\x12\x16\x0A\x12TRANS_STMT_RELEASE\x10\x06\x12\x1A\x0A\x16TRANS_STMT_ROLLBACK_TO\x10\x07\x12\x16\x0A\x12TRANS_STMT_PREPARE\x10\x08\x12\x1E\x0A\x1ATRANS_STMT_COMMIT_PREPARED\x10\x09\x12 \x0A\x1CTRANS_STMT_ROLLBACK_PREPARED\x10\x0A*z\x0A\x0FViewCheckOption\x12\x1F\x0A\x1BVIEW_CHECK_OPTION_UNDEFINED\x10\x00\x12\x13\x0A\x0FNO_CHECK_OPTION\x10\x01\x12\x16\x0A\x12LOCAL_CHECK_OPTION\x10\x02\x12\x19\x0A\x15CASCADED_CHECK_OPTION\x10\x03*v\x0A\x0BDiscardMode\x12\x1A\x0A\x16DISCARD_MODE_UNDEFINED\x10\x00\x12\x0F\x0A\x0BDISCARD_ALL\x10\x01\x12\x11\x0A\x0DDISCARD_PLANS\x10\x02\x12\x15\x0A\x11DISCARD_SEQUENCES\x10\x03\x12\x10\x0A\x0CDISCARD_TEMP\x10\x04*\xBD\x01\x0A\x11ReindexObjectType\x12!\x0A\x1DREINDEX_OBJECT_TYPE_UNDEFINED\x10\x00\x12\x18\x0A\x14REINDEX_OBJECT_INDEX\x10\x01\x12\x18\x0A\x14REINDEX_OBJECT_TABLE\x10\x02\x12\x19\x0A\x15REINDEX_OBJECT_SCHEMA\x10\x03\x12\x19\x0A\x15REINDEX_OBJECT_SYSTEM\x10\x04\x12\x1B\x0A\x17REINDEX_OBJECT_DATABASE\x10\x05*\xEF\x01\x0A\x11AlterTSConfigType\x12!\x0A\x1DALTER_TSCONFIG_TYPE_UNDEFINED\x10\x00\x12\x1E\x0A\x1AALTER_TSCONFIG_ADD_MAPPING\x10\x01\x12*\x0A&ALTER_TSCONFIG_ALTER_MAPPING_FOR_TOKEN\x10\x02\x12\x1F\x0A\x1BALTER_TSCONFIG_REPLACE_DICT\x10\x03\x12)\x0A%ALTER_TSCONFIG_REPLACE_DICT_FOR_TOKEN\x10\x04\x12\x1F\x0A\x1BALTER_TSCONFIG_DROP_MAPPING\x10\x05*\xCA\x01\x0A\x16PublicationObjSpecType\x12'\x0A#PUBLICATION_OBJ_SPEC_TYPE_UNDEFINED\x10\x00\x12\x18\x0A\x14PUBLICATIONOBJ_TABLE\x10\x01\x12#\x0A\x1FPUBLICATIONOBJ_TABLES_IN_SCHEMA\x10\x02\x12'\x0A#PUBLICATIONOBJ_TABLES_IN_CUR_SCHEMA\x10\x03\x12\x1F\x0A\x1BPUBLICATIONOBJ_CONTINUATION\x10\x04*z\x0A\x16AlterPublicationAction\x12&\x0A\"ALTER_PUBLICATION_ACTION_UNDEFINED\x10\x00\x12\x11\x0A\x0DAP_AddObjects\x10\x01\x12\x12\x0A\x0EAP_DropObjects\x10\x02\x12\x11\x0A\x0DAP_SetObjects\x10\x03*\xD7\x02\x0A\x15AlterSubscriptionType\x12%\x0A!ALTER_SUBSCRIPTION_TYPE_UNDEFINED\x10\x00\x12\x1E\x0A\x1AALTER_SUBSCRIPTION_OPTIONS\x10\x01\x12!\x0A\x1DALTER_SUBSCRIPTION_CONNECTION\x10\x02\x12&\x0A\"ALTER_SUBSCRIPTION_SET_PUBLICATION\x10\x03\x12&\x0A\"ALTER_SUBSCRIPTION_ADD_PUBLICATION\x10\x04\x12'\x0A#ALTER_SUBSCRIPTION_DROP_PUBLICATION\x10\x05\x12\x1E\x0A\x1AALTER_SUBSCRIPTION_REFRESH\x10\x06\x12\x1E\x0A\x1AALTER_SUBSCRIPTION_ENABLED\x10\x07\x12\x1B\x0A\x17ALTER_SUBSCRIPTION_SKIP\x10\x08*\x7F\x0A\x0EOverridingKind\x12\x1D\x0A\x19OVERRIDING_KIND_UNDEFINED\x10\x00\x12\x16\x0A\x12OVERRIDING_NOT_SET\x10\x01\x12\x19\x0A\x15OVERRIDING_USER_VALUE\x10\x02\x12\x1B\x0A\x17OVERRIDING_SYSTEM_VALUE\x10\x03*\x8C\x01\x0A\x0EOnCommitAction\x12\x1E\x0A\x1AON_COMMIT_ACTION_UNDEFINED\x10\x00\x12\x11\x0A\x0DONCOMMIT_NOOP\x10\x01\x12\x1A\x0A\x16ONCOMMIT_PRESERVE_ROWS\x10\x02\x12\x18\x0A\x14ONCOMMIT_DELETE_ROWS\x10\x03\x12\x11\x0A\x0DONCOMMIT_DROP\x10\x04*T\x0A\x0DTableFuncType\x12\x1D\x0A\x19TABLE_FUNC_TYPE_UNDEFINED\x10\x00\x12\x10\x0A\x0CTFT_XMLTABLE\x10\x01\x12\x12\x0A\x0ETFT_JSON_TABLE\x10\x02*o\x0A\x09ParamKind\x12\x18\x0A\x14PARAM_KIND_UNDEFINED\x10\x00\x12\x10\x0A\x0CPARAM_EXTERN\x10\x01\x12\x0E\x0A\x0APARAM_EXEC\x10\x02\x12\x11\x0A\x0DPARAM_SUBLINK\x10\x03\x12\x13\x0A\x0FPARAM_MULTIEXPR\x10\x04*\x8E\x01\x0A\x0FCoercionContext\x12\x1E\x0A\x1ACOERCION_CONTEXT_UNDEFINED\x10\x00\x12\x15\x0A\x11COERCION_IMPLICIT\x10\x01\x12\x17\x0A\x13COERCION_ASSIGNMENT\x10\x02\x12\x14\x0A\x10COERCION_PLPGSQL\x10\x03\x12\x15\x0A\x11COERCION_EXPLICIT\x10\x04*\x90\x01\x0A\x0CCoercionForm\x12\x1B\x0A\x17COERCION_FORM_UNDEFINED\x10\x00\x12\x18\x0A\x14COERCE_EXPLICIT_CALL\x10\x01\x12\x18\x0A\x14COERCE_EXPLICIT_CAST\x10\x02\x12\x18\x0A\x14COERCE_IMPLICIT_CAST\x10\x03\x12\x15\x0A\x11COERCE_SQL_SYNTAX\x10\x04*U\x0A\x0CBoolExprType\x12\x1C\x0A\x18BOOL_EXPR_TYPE_UNDEFINED\x10\x00\x12\x0C\x0A\x08AND_EXPR\x10\x01\x12\x0B\x0A\x07OR_EXPR\x10\x02\x12\x0C\x0A\x08NOT_EXPR\x10\x03*\xC5\x01\x0A\x0BSubLinkType\x12\x1B\x0A\x17SUB_LINK_TYPE_UNDEFINED\x10\x00\x12\x12\x0A\x0EEXISTS_SUBLINK\x10\x01\x12\x0F\x0A\x0BALL_SUBLINK\x10\x02\x12\x0F\x0A\x0BANY_SUBLINK\x10\x03\x12\x16\x0A\x12ROWCOMPARE_SUBLINK\x10\x04\x12\x10\x0A\x0CEXPR_SUBLINK\x10\x05\x12\x15\x0A\x11MULTIEXPR_SUBLINK\x10\x06\x12\x11\x0A\x0DARRAY_SUBLINK\x10\x07\x12\x0F\x0A\x0BCTE_SUBLINK\x10\x08*\xA2\x01\x0A\x0ERowCompareType\x12\x1E\x0A\x1AROW_COMPARE_TYPE_UNDEFINED\x10\x00\x12\x11\x0A\x0DROWCOMPARE_LT\x10\x01\x12\x11\x0A\x0DROWCOMPARE_LE\x10\x02\x12\x11\x0A\x0DROWCOMPARE_EQ\x10\x03\x12\x11\x0A\x0DROWCOMPARE_GE\x10\x04\x12\x11\x0A\x0DROWCOMPARE_GT\x10\x05\x12\x11\x0A\x0DROWCOMPARE_NE\x10\x06*C\x0A\x08MinMaxOp\x12\x18\x0A\x14MIN_MAX_OP_UNDEFINED\x10\x00\x12\x0F\x0A\x0BIS_GREATEST\x10\x01\x12\x0C\x0A\x08IS_LEAST\x10\x02*\xAD\x03\x0A\x12SQLValueFunctionOp\x12\"\x0A\x1ESQLVALUE_FUNCTION_OP_UNDEFINED\x10\x00\x12\x16\x0A\x12SVFOP_CURRENT_DATE\x10\x01\x12\x16\x0A\x12SVFOP_CURRENT_TIME\x10\x02\x12\x18\x0A\x14SVFOP_CURRENT_TIME_N\x10\x03\x12\x1B\x0A\x17SVFOP_CURRENT_TIMESTAMP\x10\x04\x12\x1D\x0A\x19SVFOP_CURRENT_TIMESTAMP_N\x10\x05\x12\x13\x0A\x0FSVFOP_LOCALTIME\x10\x06\x12\x15\x0A\x11SVFOP_LOCALTIME_N\x10\x07\x12\x18\x0A\x14SVFOP_LOCALTIMESTAMP\x10\x08\x12\x1A\x0A\x16SVFOP_LOCALTIMESTAMP_N\x10\x09\x12\x16\x0A\x12SVFOP_CURRENT_ROLE\x10\x0A\x12\x16\x0A\x12SVFOP_CURRENT_USER\x10\x0B\x12\x0E\x0A\x0ASVFOP_USER\x10\x0C\x12\x16\x0A\x12SVFOP_SESSION_USER\x10\x0D\x12\x19\x0A\x15SVFOP_CURRENT_CATALOG\x10\x0E\x12\x18\x0A\x14SVFOP_CURRENT_SCHEMA\x10\x0F*\xB2\x01\x0A\x09XmlExprOp\x12\x19\x0A\x15XML_EXPR_OP_UNDEFINED\x10\x00\x12\x10\x0A\x0CIS_XMLCONCAT\x10\x01\x12\x11\x0A\x0DIS_XMLELEMENT\x10\x02\x12\x10\x0A\x0CIS_XMLFOREST\x10\x03\x12\x0F\x0A\x0BIS_XMLPARSE\x10\x04\x12\x0C\x0A\x08IS_XMLPI\x10\x05\x12\x0E\x0A\x0AIS_XMLROOT\x10\x06\x12\x13\x0A\x0FIS_XMLSERIALIZE\x10\x07\x12\x0F\x0A\x0BIS_DOCUMENT\x10\x08*]\x0A\x0DXmlOptionType\x12\x1D\x0A\x19XML_OPTION_TYPE_UNDEFINED\x10\x00\x12\x16\x0A\x12XMLOPTION_DOCUMENT\x10\x01\x12\x15\x0A\x11XMLOPTION_CONTENT\x10\x02*t\x0A\x0CJsonEncoding\x12\x1B\x0A\x17JSON_ENCODING_UNDEFINED\x10\x00\x12\x12\x0A\x0EJS_ENC_DEFAULT\x10\x01\x12\x0F\x0A\x0BJS_ENC_UTF8\x10\x02\x12\x10\x0A\x0CJS_ENC_UTF16\x10\x03\x12\x10\x0A\x0CJS_ENC_UTF32\x10\x04*p\x0A\x0EJsonFormatType\x12\x1E\x0A\x1AJSON_FORMAT_TYPE_UNDEFINED\x10\x00\x12\x15\x0A\x11JS_FORMAT_DEFAULT\x10\x01\x12\x12\x0A\x0EJS_FORMAT_JSON\x10\x02\x12\x13\x0A\x0FJS_FORMAT_JSONB\x10\x03*\xE8\x01\x0A\x13JsonConstructorType\x12#\x0A\x1FJSON_CONSTRUCTOR_TYPE_UNDEFINED\x10\x00\x12\x16\x0A\x12JSCTOR_JSON_OBJECT\x10\x01\x12\x15\x0A\x11JSCTOR_JSON_ARRAY\x10\x02\x12\x19\x0A\x15JSCTOR_JSON_OBJECTAGG\x10\x03\x12\x18\x0A\x14JSCTOR_JSON_ARRAYAGG\x10\x04\x12\x15\x0A\x11JSCTOR_JSON_PARSE\x10\x05\x12\x16\x0A\x12JSCTOR_JSON_SCALAR\x10\x06\x12\x19\x0A\x15JSCTOR_JSON_SERIALIZE\x10\x07*z\x0A\x0DJsonValueType\x12\x1D\x0A\x19JSON_VALUE_TYPE_UNDEFINED\x10\x00\x12\x0F\x0A\x0BJS_TYPE_ANY\x10\x01\x12\x12\x0A\x0EJS_TYPE_OBJECT\x10\x02\x12\x11\x0A\x0DJS_TYPE_ARRAY\x10\x03\x12\x12\x0A\x0EJS_TYPE_SCALAR\x10\x04*s\x0A\x0BJsonWrapper\x12\x1A\x0A\x16JSON_WRAPPER_UNDEFINED\x10\x00\x12\x0E\x0A\x0AJSW_UNSPEC\x10\x01\x12\x0C\x0A\x08JSW_NONE\x10\x02\x12\x13\x0A\x0FJSW_CONDITIONAL\x10\x03\x12\x15\x0A\x11JSW_UNCONDITIONAL\x10\x04*\xA4\x02\x0A\x10JsonBehaviorType\x12 \x0A\x1CJSON_BEHAVIOR_TYPE_UNDEFINED\x10\x00\x12\x16\x0A\x12JSON_BEHAVIOR_NULL\x10\x01\x12\x17\x0A\x13JSON_BEHAVIOR_ERROR\x10\x02\x12\x17\x0A\x13JSON_BEHAVIOR_EMPTY\x10\x03\x12\x16\x0A\x12JSON_BEHAVIOR_TRUE\x10\x04\x12\x17\x0A\x13JSON_BEHAVIOR_FALSE\x10\x05\x12\x19\x0A\x15JSON_BEHAVIOR_UNKNOWN\x10\x06\x12\x1D\x0A\x19JSON_BEHAVIOR_EMPTY_ARRAY\x10\x07\x12\x1E\x0A\x1AJSON_BEHAVIOR_EMPTY_OBJECT\x10\x08\x12\x19\x0A\x15JSON_BEHAVIOR_DEFAULT\x10\x09*u\x0A\x0AJsonExprOp\x12\x1A\x0A\x16JSON_EXPR_OP_UNDEFINED\x10\x00\x12\x12\x0A\x0EJSON_EXISTS_OP\x10\x01\x12\x11\x0A\x0DJSON_QUERY_OP\x10\x02\x12\x11\x0A\x0DJSON_VALUE_OP\x10\x03\x12\x11\x0A\x0DJSON_TABLE_OP\x10\x04*J\x0A\x0CNullTestType\x12\x1C\x0A\x18NULL_TEST_TYPE_UNDEFINED\x10\x00\x12\x0B\x0A\x07IS_NULL\x10\x01\x12\x0F\x0A\x0BIS_NOT_NULL\x10\x02*\x8E\x01\x0A\x0CBoolTestType\x12\x1C\x0A\x18BOOL_TEST_TYPE_UNDEFINED\x10\x00\x12\x0B\x0A\x07IS_TRUE\x10\x01\x12\x0F\x0A\x0BIS_NOT_TRUE\x10\x02\x12\x0C\x0A\x08IS_FALSE\x10\x03\x12\x10\x0A\x0CIS_NOT_FALSE\x10\x04\x12\x0E\x0A\x0AIS_UNKNOWN\x10\x05\x12\x12\x0A\x0EIS_NOT_UNKNOWN\x10\x06*\x94\x01\x0A\x0EMergeMatchKind\x12\x1E\x0A\x1AMERGE_MATCH_KIND_UNDEFINED\x10\x00\x12\x16\x0A\x12MERGE_WHEN_MATCHED\x10\x01\x12\$\x0A MERGE_WHEN_NOT_MATCHED_BY_SOURCE\x10\x02\x12\$\x0A MERGE_WHEN_NOT_MATCHED_BY_TARGET\x10\x03*\xA3\x01\x0A\x07CmdType\x12\x16\x0A\x12CMD_TYPE_UNDEFINED\x10\x00\x12\x0F\x0A\x0BCMD_UNKNOWN\x10\x01\x12\x0E\x0A\x0ACMD_SELECT\x10\x02\x12\x0E\x0A\x0ACMD_UPDATE\x10\x03\x12\x0E\x0A\x0ACMD_INSERT\x10\x04\x12\x0E\x0A\x0ACMD_DELETE\x10\x05\x12\x0D\x0A\x09CMD_MERGE\x10\x06\x12\x0F\x0A\x0BCMD_UTILITY\x10\x07\x12\x0F\x0A\x0BCMD_NOTHING\x10\x08*\xC2\x01\x0A\x08JoinType\x12\x17\x0A\x13JOIN_TYPE_UNDEFINED\x10\x00\x12\x0E\x0A\x0AJOIN_INNER\x10\x01\x12\x0D\x0A\x09JOIN_LEFT\x10\x02\x12\x0D\x0A\x09JOIN_FULL\x10\x03\x12\x0E\x0A\x0AJOIN_RIGHT\x10\x04\x12\x0D\x0A\x09JOIN_SEMI\x10\x05\x12\x0D\x0A\x09JOIN_ANTI\x10\x06\x12\x13\x0A\x0FJOIN_RIGHT_ANTI\x10\x07\x12\x15\x0A\x11JOIN_UNIQUE_OUTER\x10\x08\x12\x15\x0A\x11JOIN_UNIQUE_INNER\x10\x09*g\x0A\x0BAggStrategy\x12\x1A\x0A\x16AGG_STRATEGY_UNDEFINED\x10\x00\x12\x0D\x0A\x09AGG_PLAIN\x10\x01\x12\x0E\x0A\x0AAGG_SORTED\x10\x02\x12\x0E\x0A\x0AAGG_HASHED\x10\x03\x12\x0D\x0A\x09AGG_MIXED\x10\x04*r\x0A\x08AggSplit\x12\x17\x0A\x13AGG_SPLIT_UNDEFINED\x10\x00\x12\x13\x0A\x0FAGGSPLIT_SIMPLE\x10\x01\x12\x1B\x0A\x17AGGSPLIT_INITIAL_SERIAL\x10\x02\x12\x1B\x0A\x17AGGSPLIT_FINAL_DESERIAL\x10\x03*\x86\x01\x0A\x08SetOpCmd\x12\x18\x0A\x14SET_OP_CMD_UNDEFINED\x10\x00\x12\x16\x0A\x12SETOPCMD_INTERSECT\x10\x01\x12\x1A\x0A\x16SETOPCMD_INTERSECT_ALL\x10\x02\x12\x13\x0A\x0FSETOPCMD_EXCEPT\x10\x03\x12\x17\x0A\x13SETOPCMD_EXCEPT_ALL\x10\x04*R\x0A\x0DSetOpStrategy\x12\x1D\x0A\x19SET_OP_STRATEGY_UNDEFINED\x10\x00\x12\x10\x0A\x0CSETOP_SORTED\x10\x01\x12\x10\x0A\x0CSETOP_HASHED\x10\x02*x\x0A\x10OnConflictAction\x12 \x0A\x1CON_CONFLICT_ACTION_UNDEFINED\x10\x00\x12\x13\x0A\x0FONCONFLICT_NONE\x10\x01\x12\x16\x0A\x12ONCONFLICT_NOTHING\x10\x02\x12\x15\x0A\x11ONCONFLICT_UPDATE\x10\x03*w\x0A\x0BLimitOption\x12\x1A\x0A\x16LIMIT_OPTION_UNDEFINED\x10\x00\x12\x18\x0A\x14LIMIT_OPTION_DEFAULT\x10\x01\x12\x16\x0A\x12LIMIT_OPTION_COUNT\x10\x02\x12\x1A\x0A\x16LIMIT_OPTION_WITH_TIES\x10\x03*\x98\x01\x0A\x12LockClauseStrength\x12\"\x0A\x1ELOCK_CLAUSE_STRENGTH_UNDEFINED\x10\x00\x12\x0C\x0A\x08LCS_NONE\x10\x01\x12\x13\x0A\x0FLCS_FORKEYSHARE\x10\x02\x12\x10\x0A\x0CLCS_FORSHARE\x10\x03\x12\x16\x0A\x12LCS_FORNOKEYUPDATE\x10\x04\x12\x11\x0A\x0DLCS_FORUPDATE\x10\x05*h\x0A\x0ELockWaitPolicy\x12\x1E\x0A\x1ALOCK_WAIT_POLICY_UNDEFINED\x10\x00\x12\x11\x0A\x0DLockWaitBlock\x10\x01\x12\x10\x0A\x0CLockWaitSkip\x10\x02\x12\x11\x0A\x0DLockWaitError\x10\x03*\x8E\x01\x0A\x0DLockTupleMode\x12\x1D\x0A\x19LOCK_TUPLE_MODE_UNDEFINED\x10\x00\x12\x15\x0A\x11LockTupleKeyShare\x10\x01\x12\x12\x0A\x0ELockTupleShare\x10\x02\x12\x1B\x0A\x17LockTupleNoKeyExclusive\x10\x03\x12\x16\x0A\x12LockTupleExclusive\x10\x04*}\x0A\x0BKeywordKind\x12\x0E\x0A\x0ANO_KEYWORD\x10\x00\x12\x16\x0A\x12UNRESERVED_KEYWORD\x10\x01\x12\x14\x0A\x10COL_NAME_KEYWORD\x10\x02\x12\x1A\x0A\x16TYPE_FUNC_NAME_KEYWORD\x10\x03\x12\x14\x0A\x10RESERVED_KEYWORD\x10\x04*\xE8;\x0A\x05Token\x12\x07\x0A\x03NUL\x10\x00\x12\x0C\x0A\x08ASCII_36\x10\$\x12\x0C\x0A\x08ASCII_37\x10%\x12\x0C\x0A\x08ASCII_40\x10(\x12\x0C\x0A\x08ASCII_41\x10)\x12\x0C\x0A\x08ASCII_42\x10*\x12\x0C\x0A\x08ASCII_43\x10+\x12\x0C\x0A\x08ASCII_44\x10,\x12\x0C\x0A\x08ASCII_45\x10-\x12\x0C\x0A\x08ASCII_46\x10.\x12\x0C\x0A\x08ASCII_47\x10/\x12\x0C\x0A\x08ASCII_58\x10:\x12\x0C\x0A\x08ASCII_59\x10;\x12\x0C\x0A\x08ASCII_60\x10<\x12\x0C\x0A\x08ASCII_61\x10=\x12\x0C\x0A\x08ASCII_62\x10>\x12\x0C\x0A\x08ASCII_63\x10?\x12\x0C\x0A\x08ASCII_91\x10[\x12\x0C\x0A\x08ASCII_92\x10\\\x12\x0C\x0A\x08ASCII_93\x10]\x12\x0C\x0A\x08ASCII_94\x10^\x12\x0A\x0A\x05IDENT\x10\x82\x02\x12\x0B\x0A\x06UIDENT\x10\x83\x02\x12\x0B\x0A\x06FCONST\x10\x84\x02\x12\x0B\x0A\x06SCONST\x10\x85\x02\x12\x0C\x0A\x07USCONST\x10\x86\x02\x12\x0B\x0A\x06BCONST\x10\x87\x02\x12\x0B\x0A\x06XCONST\x10\x88\x02\x12\x07\x0A\x02Op\x10\x89\x02\x12\x0B\x0A\x06ICONST\x10\x8A\x02\x12\x0A\x0A\x05PARAM\x10\x8B\x02\x12\x0D\x0A\x08TYPECAST\x10\x8C\x02\x12\x0C\x0A\x07DOT_DOT\x10\x8D\x02\x12\x11\x0A\x0CCOLON_EQUALS\x10\x8E\x02\x12\x13\x0A\x0EEQUALS_GREATER\x10\x8F\x02\x12\x10\x0A\x0BLESS_EQUALS\x10\x90\x02\x12\x13\x0A\x0EGREATER_EQUALS\x10\x91\x02\x12\x0F\x0A\x0ANOT_EQUALS\x10\x92\x02\x12\x10\x0A\x0BSQL_COMMENT\x10\x93\x02\x12\x0E\x0A\x09C_COMMENT\x10\x94\x02\x12\x0C\x0A\x07ABORT_P\x10\x95\x02\x12\x0B\x0A\x06ABSENT\x10\x96\x02\x12\x0F\x0A\x0AABSOLUTE_P\x10\x97\x02\x12\x0B\x0A\x06ACCESS\x10\x98\x02\x12\x0B\x0A\x06ACTION\x10\x99\x02\x12\x0A\x0A\x05ADD_P\x10\x9A\x02\x12\x0A\x0A\x05ADMIN\x10\x9B\x02\x12\x0A\x0A\x05AFTER\x10\x9C\x02\x12\x0E\x0A\x09AGGREGATE\x10\x9D\x02\x12\x08\x0A\x03ALL\x10\x9E\x02\x12\x09\x0A\x04ALSO\x10\x9F\x02\x12\x0A\x0A\x05ALTER\x10\xA0\x02\x12\x0B\x0A\x06ALWAYS\x10\xA1\x02\x12\x0C\x0A\x07ANALYSE\x10\xA2\x02\x12\x0C\x0A\x07ANALYZE\x10\xA3\x02\x12\x08\x0A\x03AND\x10\xA4\x02\x12\x08\x0A\x03ANY\x10\xA5\x02\x12\x0A\x0A\x05ARRAY\x10\xA6\x02\x12\x07\x0A\x02AS\x10\xA7\x02\x12\x08\x0A\x03ASC\x10\xA8\x02\x12\x0F\x0A\x0AASENSITIVE\x10\xA9\x02\x12\x0E\x0A\x09ASSERTION\x10\xAA\x02\x12\x0F\x0A\x0AASSIGNMENT\x10\xAB\x02\x12\x0F\x0A\x0AASYMMETRIC\x10\xAC\x02\x12\x0B\x0A\x06ATOMIC\x10\xAD\x02\x12\x07\x0A\x02AT\x10\xAE\x02\x12\x0B\x0A\x06ATTACH\x10\xAF\x02\x12\x0E\x0A\x09ATTRIBUTE\x10\xB0\x02\x12\x12\x0A\x0DAUTHORIZATION\x10\xB1\x02\x12\x0D\x0A\x08BACKWARD\x10\xB2\x02\x12\x0B\x0A\x06BEFORE\x10\xB3\x02\x12\x0C\x0A\x07BEGIN_P\x10\xB4\x02\x12\x0C\x0A\x07BETWEEN\x10\xB5\x02\x12\x0B\x0A\x06BIGINT\x10\xB6\x02\x12\x0B\x0A\x06BINARY\x10\xB7\x02\x12\x08\x0A\x03BIT\x10\xB8\x02\x12\x0E\x0A\x09BOOLEAN_P\x10\xB9\x02\x12\x09\x0A\x04BOTH\x10\xBA\x02\x12\x0C\x0A\x07BREADTH\x10\xBB\x02\x12\x07\x0A\x02BY\x10\xBC\x02\x12\x0A\x0A\x05CACHE\x10\xBD\x02\x12\x09\x0A\x04CALL\x10\xBE\x02\x12\x0B\x0A\x06CALLED\x10\xBF\x02\x12\x0C\x0A\x07CASCADE\x10\xC0\x02\x12\x0D\x0A\x08CASCADED\x10\xC1\x02\x12\x09\x0A\x04CASE\x10\xC2\x02\x12\x09\x0A\x04CAST\x10\xC3\x02\x12\x0E\x0A\x09CATALOG_P\x10\xC4\x02\x12\x0A\x0A\x05CHAIN\x10\xC5\x02\x12\x0B\x0A\x06CHAR_P\x10\xC6\x02\x12\x0E\x0A\x09CHARACTER\x10\xC7\x02\x12\x14\x0A\x0FCHARACTERISTICS\x10\xC8\x02\x12\x0A\x0A\x05CHECK\x10\xC9\x02\x12\x0F\x0A\x0ACHECKPOINT\x10\xCA\x02\x12\x0A\x0A\x05CLASS\x10\xCB\x02\x12\x0A\x0A\x05CLOSE\x10\xCC\x02\x12\x0C\x0A\x07CLUSTER\x10\xCD\x02\x12\x0D\x0A\x08COALESCE\x10\xCE\x02\x12\x0C\x0A\x07COLLATE\x10\xCF\x02\x12\x0E\x0A\x09COLLATION\x10\xD0\x02\x12\x0B\x0A\x06COLUMN\x10\xD1\x02\x12\x0C\x0A\x07COLUMNS\x10\xD2\x02\x12\x0C\x0A\x07COMMENT\x10\xD3\x02\x12\x0D\x0A\x08COMMENTS\x10\xD4\x02\x12\x0B\x0A\x06COMMIT\x10\xD5\x02\x12\x0E\x0A\x09COMMITTED\x10\xD6\x02\x12\x10\x0A\x0BCOMPRESSION\x10\xD7\x02\x12\x11\x0A\x0CCONCURRENTLY\x10\xD8\x02\x12\x10\x0A\x0BCONDITIONAL\x10\xD9\x02\x12\x12\x0A\x0DCONFIGURATION\x10\xDA\x02\x12\x0D\x0A\x08CONFLICT\x10\xDB\x02\x12\x0F\x0A\x0ACONNECTION\x10\xDC\x02\x12\x0F\x0A\x0ACONSTRAINT\x10\xDD\x02\x12\x10\x0A\x0BCONSTRAINTS\x10\xDE\x02\x12\x0E\x0A\x09CONTENT_P\x10\xDF\x02\x12\x0F\x0A\x0ACONTINUE_P\x10\xE0\x02\x12\x11\x0A\x0CCONVERSION_P\x10\xE1\x02\x12\x09\x0A\x04COPY\x10\xE2\x02\x12\x09\x0A\x04COST\x10\xE3\x02\x12\x0B\x0A\x06CREATE\x10\xE4\x02\x12\x0A\x0A\x05CROSS\x10\xE5\x02\x12\x08\x0A\x03CSV\x10\xE6\x02\x12\x09\x0A\x04CUBE\x10\xE7\x02\x12\x0E\x0A\x09CURRENT_P\x10\xE8\x02\x12\x14\x0A\x0FCURRENT_CATALOG\x10\xE9\x02\x12\x11\x0A\x0CCURRENT_DATE\x10\xEA\x02\x12\x11\x0A\x0CCURRENT_ROLE\x10\xEB\x02\x12\x13\x0A\x0ECURRENT_SCHEMA\x10\xEC\x02\x12\x11\x0A\x0CCURRENT_TIME\x10\xED\x02\x12\x16\x0A\x11CURRENT_TIMESTAMP\x10\xEE\x02\x12\x11\x0A\x0CCURRENT_USER\x10\xEF\x02\x12\x0B\x0A\x06CURSOR\x10\xF0\x02\x12\x0A\x0A\x05CYCLE\x10\xF1\x02\x12\x0B\x0A\x06DATA_P\x10\xF2\x02\x12\x0D\x0A\x08DATABASE\x10\xF3\x02\x12\x0A\x0A\x05DAY_P\x10\xF4\x02\x12\x0F\x0A\x0ADEALLOCATE\x10\xF5\x02\x12\x08\x0A\x03DEC\x10\xF6\x02\x12\x0E\x0A\x09DECIMAL_P\x10\xF7\x02\x12\x0C\x0A\x07DECLARE\x10\xF8\x02\x12\x0C\x0A\x07DEFAULT\x10\xF9\x02\x12\x0D\x0A\x08DEFAULTS\x10\xFA\x02\x12\x0F\x0A\x0ADEFERRABLE\x10\xFB\x02\x12\x0D\x0A\x08DEFERRED\x10\xFC\x02\x12\x0C\x0A\x07DEFINER\x10\xFD\x02\x12\x0D\x0A\x08DELETE_P\x10\xFE\x02\x12\x0E\x0A\x09DELIMITER\x10\xFF\x02\x12\x0F\x0A\x0ADELIMITERS\x10\x80\x03\x12\x0C\x0A\x07DEPENDS\x10\x81\x03\x12\x0A\x0A\x05DEPTH\x10\x82\x03\x12\x09\x0A\x04DESC\x10\x83\x03\x12\x0B\x0A\x06DETACH\x10\x84\x03\x12\x0F\x0A\x0ADICTIONARY\x10\x85\x03\x12\x0E\x0A\x09DISABLE_P\x10\x86\x03\x12\x0C\x0A\x07DISCARD\x10\x87\x03\x12\x0D\x0A\x08DISTINCT\x10\x88\x03\x12\x07\x0A\x02DO\x10\x89\x03\x12\x0F\x0A\x0ADOCUMENT_P\x10\x8A\x03\x12\x0D\x0A\x08DOMAIN_P\x10\x8B\x03\x12\x0D\x0A\x08DOUBLE_P\x10\x8C\x03\x12\x09\x0A\x04DROP\x10\x8D\x03\x12\x09\x0A\x04EACH\x10\x8E\x03\x12\x09\x0A\x04ELSE\x10\x8F\x03\x12\x0C\x0A\x07EMPTY_P\x10\x90\x03\x12\x0D\x0A\x08ENABLE_P\x10\x91\x03\x12\x0D\x0A\x08ENCODING\x10\x92\x03\x12\x0E\x0A\x09ENCRYPTED\x10\x93\x03\x12\x0A\x0A\x05END_P\x10\x94\x03\x12\x0B\x0A\x06ENUM_P\x10\x95\x03\x12\x0C\x0A\x07ERROR_P\x10\x96\x03\x12\x0B\x0A\x06ESCAPE\x10\x97\x03\x12\x0A\x0A\x05EVENT\x10\x98\x03\x12\x0B\x0A\x06EXCEPT\x10\x99\x03\x12\x0C\x0A\x07EXCLUDE\x10\x9A\x03\x12\x0E\x0A\x09EXCLUDING\x10\x9B\x03\x12\x0E\x0A\x09EXCLUSIVE\x10\x9C\x03\x12\x0C\x0A\x07EXECUTE\x10\x9D\x03\x12\x0B\x0A\x06EXISTS\x10\x9E\x03\x12\x0C\x0A\x07EXPLAIN\x10\x9F\x03\x12\x0F\x0A\x0AEXPRESSION\x10\xA0\x03\x12\x0E\x0A\x09EXTENSION\x10\xA1\x03\x12\x0D\x0A\x08EXTERNAL\x10\xA2\x03\x12\x0C\x0A\x07EXTRACT\x10\xA3\x03\x12\x0C\x0A\x07FALSE_P\x10\xA4\x03\x12\x0B\x0A\x06FAMILY\x10\xA5\x03\x12\x0A\x0A\x05FETCH\x10\xA6\x03\x12\x0B\x0A\x06FILTER\x10\xA7\x03\x12\x0D\x0A\x08FINALIZE\x10\xA8\x03\x12\x0C\x0A\x07FIRST_P\x10\xA9\x03\x12\x0C\x0A\x07FLOAT_P\x10\xAA\x03\x12\x0E\x0A\x09FOLLOWING\x10\xAB\x03\x12\x08\x0A\x03FOR\x10\xAC\x03\x12\x0A\x0A\x05FORCE\x10\xAD\x03\x12\x0C\x0A\x07FOREIGN\x10\xAE\x03\x12\x0B\x0A\x06FORMAT\x10\xAF\x03\x12\x0C\x0A\x07FORWARD\x10\xB0\x03\x12\x0B\x0A\x06FREEZE\x10\xB1\x03\x12\x09\x0A\x04FROM\x10\xB2\x03\x12\x09\x0A\x04FULL\x10\xB3\x03\x12\x0D\x0A\x08FUNCTION\x10\xB4\x03\x12\x0E\x0A\x09FUNCTIONS\x10\xB5\x03\x12\x0E\x0A\x09GENERATED\x10\xB6\x03\x12\x0B\x0A\x06GLOBAL\x10\xB7\x03\x12\x0A\x0A\x05GRANT\x10\xB8\x03\x12\x0C\x0A\x07GRANTED\x10\xB9\x03\x12\x0D\x0A\x08GREATEST\x10\xBA\x03\x12\x0C\x0A\x07GROUP_P\x10\xBB\x03\x12\x0D\x0A\x08GROUPING\x10\xBC\x03\x12\x0B\x0A\x06GROUPS\x10\xBD\x03\x12\x0C\x0A\x07HANDLER\x10\xBE\x03\x12\x0B\x0A\x06HAVING\x10\xBF\x03\x12\x0D\x0A\x08HEADER_P\x10\xC0\x03\x12\x09\x0A\x04HOLD\x10\xC1\x03\x12\x0B\x0A\x06HOUR_P\x10\xC2\x03\x12\x0F\x0A\x0AIDENTITY_P\x10\xC3\x03\x12\x09\x0A\x04IF_P\x10\xC4\x03\x12\x0A\x0A\x05ILIKE\x10\xC5\x03\x12\x0E\x0A\x09IMMEDIATE\x10\xC6\x03\x12\x0E\x0A\x09IMMUTABLE\x10\xC7\x03\x12\x0F\x0A\x0AIMPLICIT_P\x10\xC8\x03\x12\x0D\x0A\x08IMPORT_P\x10\xC9\x03\x12\x09\x0A\x04IN_P\x10\xCA\x03\x12\x0C\x0A\x07INCLUDE\x10\xCB\x03\x12\x0E\x0A\x09INCLUDING\x10\xCC\x03\x12\x0E\x0A\x09INCREMENT\x10\xCD\x03\x12\x0B\x0A\x06INDENT\x10\xCE\x03\x12\x0A\x0A\x05INDEX\x10\xCF\x03\x12\x0C\x0A\x07INDEXES\x10\xD0\x03\x12\x0C\x0A\x07INHERIT\x10\xD1\x03\x12\x0D\x0A\x08INHERITS\x10\xD2\x03\x12\x0E\x0A\x09INITIALLY\x10\xD3\x03\x12\x0D\x0A\x08INLINE_P\x10\xD4\x03\x12\x0C\x0A\x07INNER_P\x10\xD5\x03\x12\x0A\x0A\x05INOUT\x10\xD6\x03\x12\x0C\x0A\x07INPUT_P\x10\xD7\x03\x12\x10\x0A\x0BINSENSITIVE\x10\xD8\x03\x12\x0B\x0A\x06INSERT\x10\xD9\x03\x12\x0C\x0A\x07INSTEAD\x10\xDA\x03\x12\x0A\x0A\x05INT_P\x10\xDB\x03\x12\x0C\x0A\x07INTEGER\x10\xDC\x03\x12\x0E\x0A\x09INTERSECT\x10\xDD\x03\x12\x0D\x0A\x08INTERVAL\x10\xDE\x03\x12\x09\x0A\x04INTO\x10\xDF\x03\x12\x0C\x0A\x07INVOKER\x10\xE0\x03\x12\x07\x0A\x02IS\x10\xE1\x03\x12\x0B\x0A\x06ISNULL\x10\xE2\x03\x12\x0E\x0A\x09ISOLATION\x10\xE3\x03\x12\x09\x0A\x04JOIN\x10\xE4\x03\x12\x09\x0A\x04JSON\x10\xE5\x03\x12\x0F\x0A\x0AJSON_ARRAY\x10\xE6\x03\x12\x12\x0A\x0DJSON_ARRAYAGG\x10\xE7\x03\x12\x10\x0A\x0BJSON_EXISTS\x10\xE8\x03\x12\x10\x0A\x0BJSON_OBJECT\x10\xE9\x03\x12\x13\x0A\x0EJSON_OBJECTAGG\x10\xEA\x03\x12\x0F\x0A\x0AJSON_QUERY\x10\xEB\x03\x12\x10\x0A\x0BJSON_SCALAR\x10\xEC\x03\x12\x13\x0A\x0EJSON_SERIALIZE\x10\xED\x03\x12\x0F\x0A\x0AJSON_TABLE\x10\xEE\x03\x12\x0F\x0A\x0AJSON_VALUE\x10\xEF\x03\x12\x09\x0A\x04KEEP\x10\xF0\x03\x12\x08\x0A\x03KEY\x10\xF1\x03\x12\x09\x0A\x04KEYS\x10\xF2\x03\x12\x0A\x0A\x05LABEL\x10\xF3\x03\x12\x0D\x0A\x08LANGUAGE\x10\xF4\x03\x12\x0C\x0A\x07LARGE_P\x10\xF5\x03\x12\x0B\x0A\x06LAST_P\x10\xF6\x03\x12\x0E\x0A\x09LATERAL_P\x10\xF7\x03\x12\x0C\x0A\x07LEADING\x10\xF8\x03\x12\x0E\x0A\x09LEAKPROOF\x10\xF9\x03\x12\x0A\x0A\x05LEAST\x10\xFA\x03\x12\x09\x0A\x04LEFT\x10\xFB\x03\x12\x0A\x0A\x05LEVEL\x10\xFC\x03\x12\x09\x0A\x04LIKE\x10\xFD\x03\x12\x0A\x0A\x05LIMIT\x10\xFE\x03\x12\x0B\x0A\x06LISTEN\x10\xFF\x03\x12\x09\x0A\x04LOAD\x10\x80\x04\x12\x0A\x0A\x05LOCAL\x10\x81\x04\x12\x0E\x0A\x09LOCALTIME\x10\x82\x04\x12\x13\x0A\x0ELOCALTIMESTAMP\x10\x83\x04\x12\x0D\x0A\x08LOCATION\x10\x84\x04\x12\x0B\x0A\x06LOCK_P\x10\x85\x04\x12\x0B\x0A\x06LOCKED\x10\x86\x04\x12\x0B\x0A\x06LOGGED\x10\x87\x04\x12\x0C\x0A\x07MAPPING\x10\x88\x04\x12\x0A\x0A\x05MATCH\x10\x89\x04\x12\x0C\x0A\x07MATCHED\x10\x8A\x04\x12\x11\x0A\x0CMATERIALIZED\x10\x8B\x04\x12\x0D\x0A\x08MAXVALUE\x10\x8C\x04\x12\x0A\x0A\x05MERGE\x10\x8D\x04\x12\x11\x0A\x0CMERGE_ACTION\x10\x8E\x04\x12\x0B\x0A\x06METHOD\x10\x8F\x04\x12\x0D\x0A\x08MINUTE_P\x10\x90\x04\x12\x0D\x0A\x08MINVALUE\x10\x91\x04\x12\x09\x0A\x04MODE\x10\x92\x04\x12\x0C\x0A\x07MONTH_P\x10\x93\x04\x12\x09\x0A\x04MOVE\x10\x94\x04\x12\x0B\x0A\x06NAME_P\x10\x95\x04\x12\x0A\x0A\x05NAMES\x10\x96\x04\x12\x0D\x0A\x08NATIONAL\x10\x97\x04\x12\x0C\x0A\x07NATURAL\x10\x98\x04\x12\x0A\x0A\x05NCHAR\x10\x99\x04\x12\x0B\x0A\x06NESTED\x10\x9A\x04\x12\x08\x0A\x03NEW\x10\x9B\x04\x12\x09\x0A\x04NEXT\x10\x9C\x04\x12\x08\x0A\x03NFC\x10\x9D\x04\x12\x08\x0A\x03NFD\x10\x9E\x04\x12\x09\x0A\x04NFKC\x10\x9F\x04\x12\x09\x0A\x04NFKD\x10\xA0\x04\x12\x07\x0A\x02NO\x10\xA1\x04\x12\x09\x0A\x04NONE\x10\xA2\x04\x12\x0E\x0A\x09NORMALIZE\x10\xA3\x04\x12\x0F\x0A\x0ANORMALIZED\x10\xA4\x04\x12\x08\x0A\x03NOT\x10\xA5\x04\x12\x0C\x0A\x07NOTHING\x10\xA6\x04\x12\x0B\x0A\x06NOTIFY\x10\xA7\x04\x12\x0C\x0A\x07NOTNULL\x10\xA8\x04\x12\x0B\x0A\x06NOWAIT\x10\xA9\x04\x12\x0B\x0A\x06NULL_P\x10\xAA\x04\x12\x0B\x0A\x06NULLIF\x10\xAB\x04\x12\x0C\x0A\x07NULLS_P\x10\xAC\x04\x12\x0C\x0A\x07NUMERIC\x10\xAD\x04\x12\x0D\x0A\x08OBJECT_P\x10\xAE\x04\x12\x07\x0A\x02OF\x10\xAF\x04\x12\x08\x0A\x03OFF\x10\xB0\x04\x12\x0B\x0A\x06OFFSET\x10\xB1\x04\x12\x09\x0A\x04OIDS\x10\xB2\x04\x12\x08\x0A\x03OLD\x10\xB3\x04\x12\x09\x0A\x04OMIT\x10\xB4\x04\x12\x07\x0A\x02ON\x10\xB5\x04\x12\x09\x0A\x04ONLY\x10\xB6\x04\x12\x0D\x0A\x08OPERATOR\x10\xB7\x04\x12\x0B\x0A\x06OPTION\x10\xB8\x04\x12\x0C\x0A\x07OPTIONS\x10\xB9\x04\x12\x07\x0A\x02OR\x10\xBA\x04\x12\x0A\x0A\x05ORDER\x10\xBB\x04\x12\x0F\x0A\x0AORDINALITY\x10\xBC\x04\x12\x0B\x0A\x06OTHERS\x10\xBD\x04\x12\x0A\x0A\x05OUT_P\x10\xBE\x04\x12\x0C\x0A\x07OUTER_P\x10\xBF\x04\x12\x09\x0A\x04OVER\x10\xC0\x04\x12\x0D\x0A\x08OVERLAPS\x10\xC1\x04\x12\x0C\x0A\x07OVERLAY\x10\xC2\x04\x12\x0F\x0A\x0AOVERRIDING\x10\xC3\x04\x12\x0A\x0A\x05OWNED\x10\xC4\x04\x12\x0A\x0A\x05OWNER\x10\xC5\x04\x12\x0D\x0A\x08PARALLEL\x10\xC6\x04\x12\x0E\x0A\x09PARAMETER\x10\xC7\x04\x12\x0B\x0A\x06PARSER\x10\xC8\x04\x12\x0C\x0A\x07PARTIAL\x10\xC9\x04\x12\x0E\x0A\x09PARTITION\x10\xCA\x04\x12\x0C\x0A\x07PASSING\x10\xCB\x04\x12\x0D\x0A\x08PASSWORD\x10\xCC\x04\x12\x09\x0A\x04PATH\x10\xCD\x04\x12\x0C\x0A\x07PLACING\x10\xCE\x04\x12\x09\x0A\x04PLAN\x10\xCF\x04\x12\x0A\x0A\x05PLANS\x10\xD0\x04\x12\x0B\x0A\x06POLICY\x10\xD1\x04\x12\x0D\x0A\x08POSITION\x10\xD2\x04\x12\x0E\x0A\x09PRECEDING\x10\xD3\x04\x12\x0E\x0A\x09PRECISION\x10\xD4\x04\x12\x0D\x0A\x08PRESERVE\x10\xD5\x04\x12\x0C\x0A\x07PREPARE\x10\xD6\x04\x12\x0D\x0A\x08PREPARED\x10\xD7\x04\x12\x0C\x0A\x07PRIMARY\x10\xD8\x04\x12\x0A\x0A\x05PRIOR\x10\xD9\x04\x12\x0F\x0A\x0APRIVILEGES\x10\xDA\x04\x12\x0F\x0A\x0APROCEDURAL\x10\xDB\x04\x12\x0E\x0A\x09PROCEDURE\x10\xDC\x04\x12\x0F\x0A\x0APROCEDURES\x10\xDD\x04\x12\x0C\x0A\x07PROGRAM\x10\xDE\x04\x12\x10\x0A\x0BPUBLICATION\x10\xDF\x04\x12\x0A\x0A\x05QUOTE\x10\xE0\x04\x12\x0B\x0A\x06QUOTES\x10\xE1\x04\x12\x0A\x0A\x05RANGE\x10\xE2\x04\x12\x09\x0A\x04READ\x10\xE3\x04\x12\x09\x0A\x04REAL\x10\xE4\x04\x12\x0D\x0A\x08REASSIGN\x10\xE5\x04\x12\x0C\x0A\x07RECHECK\x10\xE6\x04\x12\x0E\x0A\x09RECURSIVE\x10\xE7\x04\x12\x0A\x0A\x05REF_P\x10\xE8\x04\x12\x0F\x0A\x0AREFERENCES\x10\xE9\x04\x12\x10\x0A\x0BREFERENCING\x10\xEA\x04\x12\x0C\x0A\x07REFRESH\x10\xEB\x04\x12\x0C\x0A\x07REINDEX\x10\xEC\x04\x12\x0F\x0A\x0ARELATIVE_P\x10\xED\x04\x12\x0C\x0A\x07RELEASE\x10\xEE\x04\x12\x0B\x0A\x06RENAME\x10\xEF\x04\x12\x0F\x0A\x0AREPEATABLE\x10\xF0\x04\x12\x0C\x0A\x07REPLACE\x10\xF1\x04\x12\x0C\x0A\x07REPLICA\x10\xF2\x04\x12\x0A\x0A\x05RESET\x10\xF3\x04\x12\x0C\x0A\x07RESTART\x10\xF4\x04\x12\x0D\x0A\x08RESTRICT\x10\xF5\x04\x12\x0B\x0A\x06RETURN\x10\xF6\x04\x12\x0E\x0A\x09RETURNING\x10\xF7\x04\x12\x0C\x0A\x07RETURNS\x10\xF8\x04\x12\x0B\x0A\x06REVOKE\x10\xF9\x04\x12\x0A\x0A\x05RIGHT\x10\xFA\x04\x12\x09\x0A\x04ROLE\x10\xFB\x04\x12\x0D\x0A\x08ROLLBACK\x10\xFC\x04\x12\x0B\x0A\x06ROLLUP\x10\xFD\x04\x12\x0C\x0A\x07ROUTINE\x10\xFE\x04\x12\x0D\x0A\x08ROUTINES\x10\xFF\x04\x12\x08\x0A\x03ROW\x10\x80\x05\x12\x09\x0A\x04ROWS\x10\x81\x05\x12\x09\x0A\x04RULE\x10\x82\x05\x12\x0E\x0A\x09SAVEPOINT\x10\x83\x05\x12\x0B\x0A\x06SCALAR\x10\x84\x05\x12\x0B\x0A\x06SCHEMA\x10\x85\x05\x12\x0C\x0A\x07SCHEMAS\x10\x86\x05\x12\x0B\x0A\x06SCROLL\x10\x87\x05\x12\x0B\x0A\x06SEARCH\x10\x88\x05\x12\x0D\x0A\x08SECOND_P\x10\x89\x05\x12\x0D\x0A\x08SECURITY\x10\x8A\x05\x12\x0B\x0A\x06SELECT\x10\x8B\x05\x12\x0D\x0A\x08SEQUENCE\x10\x8C\x05\x12\x0E\x0A\x09SEQUENCES\x10\x8D\x05\x12\x11\x0A\x0CSERIALIZABLE\x10\x8E\x05\x12\x0B\x0A\x06SERVER\x10\x8F\x05\x12\x0C\x0A\x07SESSION\x10\x90\x05\x12\x11\x0A\x0CSESSION_USER\x10\x91\x05\x12\x08\x0A\x03SET\x10\x92\x05\x12\x09\x0A\x04SETS\x10\x93\x05\x12\x0A\x0A\x05SETOF\x10\x94\x05\x12\x0A\x0A\x05SHARE\x10\x95\x05\x12\x09\x0A\x04SHOW\x10\x96\x05\x12\x0C\x0A\x07SIMILAR\x10\x97\x05\x12\x0B\x0A\x06SIMPLE\x10\x98\x05\x12\x09\x0A\x04SKIP\x10\x99\x05\x12\x0D\x0A\x08SMALLINT\x10\x9A\x05\x12\x0D\x0A\x08SNAPSHOT\x10\x9B\x05\x12\x09\x0A\x04SOME\x10\x9C\x05\x12\x0B\x0A\x06SOURCE\x10\x9D\x05\x12\x0A\x0A\x05SQL_P\x10\x9E\x05\x12\x0B\x0A\x06STABLE\x10\x9F\x05\x12\x11\x0A\x0CSTANDALONE_P\x10\xA0\x05\x12\x0A\x0A\x05START\x10\xA1\x05\x12\x0E\x0A\x09STATEMENT\x10\xA2\x05\x12\x0F\x0A\x0ASTATISTICS\x10\xA3\x05\x12\x0A\x0A\x05STDIN\x10\xA4\x05\x12\x0B\x0A\x06STDOUT\x10\xA5\x05\x12\x0C\x0A\x07STORAGE\x10\xA6\x05\x12\x0B\x0A\x06STORED\x10\xA7\x05\x12\x0D\x0A\x08STRICT_P\x10\xA8\x05\x12\x0D\x0A\x08STRING_P\x10\xA9\x05\x12\x0C\x0A\x07STRIP_P\x10\xAA\x05\x12\x11\x0A\x0CSUBSCRIPTION\x10\xAB\x05\x12\x0E\x0A\x09SUBSTRING\x10\xAC\x05\x12\x0C\x0A\x07SUPPORT\x10\xAD\x05\x12\x0E\x0A\x09SYMMETRIC\x10\xAE\x05\x12\x0A\x0A\x05SYSID\x10\xAF\x05\x12\x0D\x0A\x08SYSTEM_P\x10\xB0\x05\x12\x10\x0A\x0BSYSTEM_USER\x10\xB1\x05\x12\x0A\x0A\x05TABLE\x10\xB2\x05\x12\x0B\x0A\x06TABLES\x10\xB3\x05\x12\x10\x0A\x0BTABLESAMPLE\x10\xB4\x05\x12\x0F\x0A\x0ATABLESPACE\x10\xB5\x05\x12\x0B\x0A\x06TARGET\x10\xB6\x05\x12\x09\x0A\x04TEMP\x10\xB7\x05\x12\x0D\x0A\x08TEMPLATE\x10\xB8\x05\x12\x0E\x0A\x09TEMPORARY\x10\xB9\x05\x12\x0B\x0A\x06TEXT_P\x10\xBA\x05\x12\x09\x0A\x04THEN\x10\xBB\x05\x12\x09\x0A\x04TIES\x10\xBC\x05\x12\x09\x0A\x04TIME\x10\xBD\x05\x12\x0E\x0A\x09TIMESTAMP\x10\xBE\x05\x12\x07\x0A\x02TO\x10\xBF\x05\x12\x0D\x0A\x08TRAILING\x10\xC0\x05\x12\x10\x0A\x0BTRANSACTION\x10\xC1\x05\x12\x0E\x0A\x09TRANSFORM\x10\xC2\x05\x12\x0A\x0A\x05TREAT\x10\xC3\x05\x12\x0C\x0A\x07TRIGGER\x10\xC4\x05\x12\x09\x0A\x04TRIM\x10\xC5\x05\x12\x0B\x0A\x06TRUE_P\x10\xC6\x05\x12\x0D\x0A\x08TRUNCATE\x10\xC7\x05\x12\x0C\x0A\x07TRUSTED\x10\xC8\x05\x12\x0B\x0A\x06TYPE_P\x10\xC9\x05\x12\x0C\x0A\x07TYPES_P\x10\xCA\x05\x12\x0C\x0A\x07UESCAPE\x10\xCB\x05\x12\x0E\x0A\x09UNBOUNDED\x10\xCC\x05\x12\x12\x0A\x0DUNCONDITIONAL\x10\xCD\x05\x12\x10\x0A\x0BUNCOMMITTED\x10\xCE\x05\x12\x10\x0A\x0BUNENCRYPTED\x10\xCF\x05\x12\x0A\x0A\x05UNION\x10\xD0\x05\x12\x0B\x0A\x06UNIQUE\x10\xD1\x05\x12\x0C\x0A\x07UNKNOWN\x10\xD2\x05\x12\x0D\x0A\x08UNLISTEN\x10\xD3\x05\x12\x0D\x0A\x08UNLOGGED\x10\xD4\x05\x12\x0A\x0A\x05UNTIL\x10\xD5\x05\x12\x0B\x0A\x06UPDATE\x10\xD6\x05\x12\x09\x0A\x04USER\x10\xD7\x05\x12\x0A\x0A\x05USING\x10\xD8\x05\x12\x0B\x0A\x06VACUUM\x10\xD9\x05\x12\x0A\x0A\x05VALID\x10\xDA\x05\x12\x0D\x0A\x08VALIDATE\x10\xDB\x05\x12\x0E\x0A\x09VALIDATOR\x10\xDC\x05\x12\x0C\x0A\x07VALUE_P\x10\xDD\x05\x12\x0B\x0A\x06VALUES\x10\xDE\x05\x12\x0C\x0A\x07VARCHAR\x10\xDF\x05\x12\x0D\x0A\x08VARIADIC\x10\xE0\x05\x12\x0C\x0A\x07VARYING\x10\xE1\x05\x12\x0C\x0A\x07VERBOSE\x10\xE2\x05\x12\x0E\x0A\x09VERSION_P\x10\xE3\x05\x12\x09\x0A\x04VIEW\x10\xE4\x05\x12\x0A\x0A\x05VIEWS\x10\xE5\x05\x12\x0D\x0A\x08VOLATILE\x10\xE6\x05\x12\x09\x0A\x04WHEN\x10\xE7\x05\x12\x0A\x0A\x05WHERE\x10\xE8\x05\x12\x11\x0A\x0CWHITESPACE_P\x10\xE9\x05\x12\x0B\x0A\x06WINDOW\x10\xEA\x05\x12\x09\x0A\x04WITH\x10\xEB\x05\x12\x0B\x0A\x06WITHIN\x10\xEC\x05\x12\x0C\x0A\x07WITHOUT\x10\xED\x05\x12\x09\x0A\x04WORK\x10\xEE\x05\x12\x0C\x0A\x07WRAPPER\x10\xEF\x05\x12\x0A\x0A\x05WRITE\x10\xF0\x05\x12\x0A\x0A\x05XML_P\x10\xF1\x05\x12\x12\x0A\x0DXMLATTRIBUTES\x10\xF2\x05\x12\x0E\x0A\x09XMLCONCAT\x10\xF3\x05\x12\x0F\x0A\x0AXMLELEMENT\x10\xF4\x05\x12\x0E\x0A\x09XMLEXISTS\x10\xF5\x05\x12\x0E\x0A\x09XMLFOREST\x10\xF6\x05\x12\x12\x0A\x0DXMLNAMESPACES\x10\xF7\x05\x12\x0D\x0A\x08XMLPARSE\x10\xF8\x05\x12\x0A\x0A\x05XMLPI\x10\xF9\x05\x12\x0C\x0A\x07XMLROOT\x10\xFA\x05\x12\x11\x0A\x0CXMLSERIALIZE\x10\xFB\x05\x12\x0D\x0A\x08XMLTABLE\x10\xFC\x05\x12\x0B\x0A\x06YEAR_P\x10\xFD\x05\x12\x0A\x0A\x05YES_P\x10\xFE\x05\x12\x09\x0A\x04ZONE\x10\xFF\x05\x12\x0E\x0A\x09FORMAT_LA\x10\x80\x06\x12\x0B\x0A\x06NOT_LA\x10\x81\x06\x12\x0D\x0A\x08NULLS_LA\x10\x82\x06\x12\x0C\x0A\x07WITH_LA\x10\x83\x06\x12\x0F\x0A\x0AWITHOUT_LA\x10\x84\x06\x12\x13\x0A\x0EMODE_TYPE_NAME\x10\x85\x06\x12\x16\x0A\x11MODE_PLPGSQL_EXPR\x10\x86\x06\x12\x19\x0A\x14MODE_PLPGSQL_ASSIGN1\x10\x87\x06\x12\x19\x0A\x14MODE_PLPGSQL_ASSIGN2\x10\x88\x06\x12\x19\x0A\x14MODE_PLPGSQL_ASSIGN3\x10\x89\x06\x12\x0B\x0A\x06UMINUS\x10\x8A\x06B=\xCA\x02\x19Flow\\PgQuery\\Protobuf\\AST\xE2\x02\x1EFlow\\PgQuery\\Protobuf\\Metadatab\x06proto3",
+ "\x0A\x91\x85\x06\x0A\x0Epg_query.proto\x12\x08pg_query\"@\x0A\x0BParseResult\x12\x0F\x0A\x07version\x18\x01 \x01(\x05\x12 \x0A\x05stmts\x18\x02 \x03(\x0B2\x11.pg_query.RawStmt\"B\x0A\x0AScanResult\x12\x0F\x0A\x07version\x18\x01 \x01(\x05\x12#\x0A\x06tokens\x18\x02 \x03(\x0B2\x13.pg_query.ScanToken\"\xD5\x8E\x01\x0A\x04Node\x12'\x0A\x05alias\x18\x01 \x01(\x0B2\x0F.pg_query.AliasH\x00R\x05Alias\x121\x0A\x09range_var\x18\x02 \x01(\x0B2\x12.pg_query.RangeVarH\x00R\x08RangeVar\x124\x0A\x0Atable_func\x18\x03 \x01(\x0B2\x13.pg_query.TableFuncH\x00R\x09TableFunc\x127\x0A\x0Binto_clause\x18\x04 \x01(\x0B2\x14.pg_query.IntoClauseH\x00R\x0AIntoClause\x12!\x0A\x03var\x18\x05 \x01(\x0B2\x0D.pg_query.VarH\x00R\x03Var\x12'\x0A\x05param\x18\x06 \x01(\x0B2\x0F.pg_query.ParamH\x00R\x05Param\x12*\x0A\x06aggref\x18\x07 \x01(\x0B2\x10.pg_query.AggrefH\x00R\x06Aggref\x12=\x0A\x0Dgrouping_func\x18\x08 \x01(\x0B2\x16.pg_query.GroupingFuncH\x00R\x0CGroupingFunc\x127\x0A\x0Bwindow_func\x18\x09 \x01(\x0B2\x14.pg_query.WindowFuncH\x00R\x0AWindowFunc\x12]\x0A\x19window_func_run_condition\x18\x0A \x01(\x0B2 .pg_query.WindowFuncRunConditionH\x00R\x16WindowFuncRunCondition\x12J\x0A\x12merge_support_func\x18\x0B \x01(\x0B2\x1A.pg_query.MergeSupportFuncH\x00R\x10MergeSupportFunc\x12F\x0A\x10subscripting_ref\x18\x0C \x01(\x0B2\x19.pg_query.SubscriptingRefH\x00R\x0FSubscriptingRef\x121\x0A\x09func_expr\x18\x0D \x01(\x0B2\x12.pg_query.FuncExprH\x00R\x08FuncExpr\x12>\x0A\x0Enamed_arg_expr\x18\x0E \x01(\x0B2\x16.pg_query.NamedArgExprH\x00R\x0CNamedArgExpr\x12+\x0A\x07op_expr\x18\x0F \x01(\x0B2\x10.pg_query.OpExprH\x00R\x06OpExpr\x12=\x0A\x0Ddistinct_expr\x18\x10 \x01(\x0B2\x16.pg_query.DistinctExprH\x00R\x0CDistinctExpr\x128\x0A\x0Cnull_if_expr\x18\x11 \x01(\x0B2\x14.pg_query.NullIfExprH\x00R\x0ANullIfExpr\x12N\x0A\x14scalar_array_op_expr\x18\x12 \x01(\x0B2\x1B.pg_query.ScalarArrayOpExprH\x00R\x11ScalarArrayOpExpr\x121\x0A\x09bool_expr\x18\x13 \x01(\x0B2\x12.pg_query.BoolExprH\x00R\x08BoolExpr\x12.\x0A\x08sub_link\x18\x14 \x01(\x0B2\x11.pg_query.SubLinkH\x00R\x07SubLink\x12.\x0A\x08sub_plan\x18\x15 \x01(\x0B2\x11.pg_query.SubPlanH\x00R\x07SubPlan\x12P\x0A\x14alternative_sub_plan\x18\x16 \x01(\x0B2\x1C.pg_query.AlternativeSubPlanH\x00R\x12AlternativeSubPlan\x12:\x0A\x0Cfield_select\x18\x17 \x01(\x0B2\x15.pg_query.FieldSelectH\x00R\x0BFieldSelect\x127\x0A\x0Bfield_store\x18\x18 \x01(\x0B2\x14.pg_query.FieldStoreH\x00R\x0AFieldStore\x12:\x0A\x0Crelabel_type\x18\x19 \x01(\x0B2\x15.pg_query.RelabelTypeH\x00R\x0BRelabelType\x12;\x0A\x0Dcoerce_via_io\x18\x1A \x01(\x0B2\x15.pg_query.CoerceViaIOH\x00R\x0BCoerceViaIO\x12G\x0A\x11array_coerce_expr\x18\x1B \x01(\x0B2\x19.pg_query.ArrayCoerceExprH\x00R\x0FArrayCoerceExpr\x12P\x0A\x14convert_rowtype_expr\x18\x1C \x01(\x0B2\x1C.pg_query.ConvertRowtypeExprH\x00R\x12ConvertRowtypeExpr\x12:\x0A\x0Ccollate_expr\x18\x1D \x01(\x0B2\x15.pg_query.CollateExprH\x00R\x0BCollateExpr\x121\x0A\x09case_expr\x18\x1E \x01(\x0B2\x12.pg_query.CaseExprH\x00R\x08CaseExpr\x121\x0A\x09case_when\x18\x1F \x01(\x0B2\x12.pg_query.CaseWhenH\x00R\x08CaseWhen\x12>\x0A\x0Ecase_test_expr\x18 \x01(\x0B2\x16.pg_query.CaseTestExprH\x00R\x0CCaseTestExpr\x124\x0A\x0Aarray_expr\x18! \x01(\x0B2\x13.pg_query.ArrayExprH\x00R\x09ArrayExpr\x12.\x0A\x08row_expr\x18\" \x01(\x0B2\x11.pg_query.RowExprH\x00R\x07RowExpr\x12D\x0A\x10row_compare_expr\x18# \x01(\x0B2\x18.pg_query.RowCompareExprH\x00R\x0ERowCompareExpr\x12=\x0A\x0Dcoalesce_expr\x18\$ \x01(\x0B2\x16.pg_query.CoalesceExprH\x00R\x0CCoalesceExpr\x128\x0A\x0Cmin_max_expr\x18% \x01(\x0B2\x14.pg_query.MinMaxExprH\x00R\x0AMinMaxExpr\x12I\x0A\x11sqlvalue_function\x18& \x01(\x0B2\x1A.pg_query.SQLValueFunctionH\x00R\x10SQLValueFunction\x12.\x0A\x08xml_expr\x18' \x01(\x0B2\x11.pg_query.XmlExprH\x00R\x07XmlExpr\x127\x0A\x0Bjson_format\x18( \x01(\x0B2\x14.pg_query.JsonFormatH\x00R\x0AJsonFormat\x12@\x0A\x0Ejson_returning\x18) \x01(\x0B2\x17.pg_query.JsonReturningH\x00R\x0DJsonReturning\x12A\x0A\x0Fjson_value_expr\x18* \x01(\x0B2\x17.pg_query.JsonValueExprH\x00R\x0DJsonValueExpr\x12S\x0A\x15json_constructor_expr\x18+ \x01(\x0B2\x1D.pg_query.JsonConstructorExprH\x00R\x13JsonConstructorExpr\x12G\x0A\x11json_is_predicate\x18, \x01(\x0B2\x19.pg_query.JsonIsPredicateH\x00R\x0FJsonIsPredicate\x12=\x0A\x0Djson_behavior\x18- \x01(\x0B2\x16.pg_query.JsonBehaviorH\x00R\x0CJsonBehavior\x121\x0A\x09json_expr\x18. \x01(\x0B2\x12.pg_query.JsonExprH\x00R\x08JsonExpr\x12A\x0A\x0Fjson_table_path\x18/ \x01(\x0B2\x17.pg_query.JsonTablePathH\x00R\x0DJsonTablePath\x12N\x0A\x14json_table_path_scan\x180 \x01(\x0B2\x1B.pg_query.JsonTablePathScanH\x00R\x11JsonTablePathScan\x12W\x0A\x17json_table_sibling_join\x181 \x01(\x0B2\x1E.pg_query.JsonTableSiblingJoinH\x00R\x14JsonTableSiblingJoin\x121\x0A\x09null_test\x182 \x01(\x0B2\x12.pg_query.NullTestH\x00R\x08NullTest\x12:\x0A\x0Cboolean_test\x183 \x01(\x0B2\x15.pg_query.BooleanTestH\x00R\x0BBooleanTest\x12:\x0A\x0Cmerge_action\x184 \x01(\x0B2\x15.pg_query.MergeActionH\x00R\x0BMergeAction\x12D\x0A\x10coerce_to_domain\x185 \x01(\x0B2\x18.pg_query.CoerceToDomainH\x00R\x0ECoerceToDomain\x12T\x0A\x16coerce_to_domain_value\x186 \x01(\x0B2\x1D.pg_query.CoerceToDomainValueH\x00R\x13CoerceToDomainValue\x12>\x0A\x0Eset_to_default\x187 \x01(\x0B2\x16.pg_query.SetToDefaultH\x00R\x0CSetToDefault\x12A\x0A\x0Fcurrent_of_expr\x188 \x01(\x0B2\x17.pg_query.CurrentOfExprH\x00R\x0DCurrentOfExpr\x12A\x0A\x0Fnext_value_expr\x189 \x01(\x0B2\x17.pg_query.NextValueExprH\x00R\x0DNextValueExpr\x12@\x0A\x0Einference_elem\x18: \x01(\x0B2\x17.pg_query.InferenceElemH\x00R\x0DInferenceElem\x12:\x0A\x0Ctarget_entry\x18; \x01(\x0B2\x15.pg_query.TargetEntryH\x00R\x0BTargetEntry\x12;\x0A\x0Drange_tbl_ref\x18< \x01(\x0B2\x15.pg_query.RangeTblRefH\x00R\x0BRangeTblRef\x121\x0A\x09join_expr\x18= \x01(\x0B2\x12.pg_query.JoinExprH\x00R\x08JoinExpr\x121\x0A\x09from_expr\x18> \x01(\x0B2\x12.pg_query.FromExprH\x00R\x08FromExpr\x12D\x0A\x10on_conflict_expr\x18? \x01(\x0B2\x18.pg_query.OnConflictExprH\x00R\x0EOnConflictExpr\x12'\x0A\x05query\x18@ \x01(\x0B2\x0F.pg_query.QueryH\x00R\x05Query\x121\x0A\x09type_name\x18A \x01(\x0B2\x12.pg_query.TypeNameH\x00R\x08TypeName\x124\x0A\x0Acolumn_ref\x18B \x01(\x0B2\x13.pg_query.ColumnRefH\x00R\x09ColumnRef\x121\x0A\x09param_ref\x18C \x01(\x0B2\x12.pg_query.ParamRefH\x00R\x08ParamRef\x12*\x0A\x06a_expr\x18D \x01(\x0B2\x10.pg_query.A_ExprH\x00R\x06A_Expr\x121\x0A\x09type_cast\x18E \x01(\x0B2\x12.pg_query.TypeCastH\x00R\x08TypeCast\x12@\x0A\x0Ecollate_clause\x18F \x01(\x0B2\x17.pg_query.CollateClauseH\x00R\x0DCollateClause\x121\x0A\x09role_spec\x18G \x01(\x0B2\x12.pg_query.RoleSpecH\x00R\x08RoleSpec\x121\x0A\x09func_call\x18H \x01(\x0B2\x12.pg_query.FuncCallH\x00R\x08FuncCall\x12*\x0A\x06a_star\x18I \x01(\x0B2\x10.pg_query.A_StarH\x00R\x06A_Star\x123\x0A\x09a_indices\x18J \x01(\x0B2\x13.pg_query.A_IndicesH\x00R\x09A_Indices\x12?\x0A\x0Da_indirection\x18K \x01(\x0B2\x17.pg_query.A_IndirectionH\x00R\x0DA_Indirection\x12:\x0A\x0Ca_array_expr\x18L \x01(\x0B2\x15.pg_query.A_ArrayExprH\x00R\x0BA_ArrayExpr\x124\x0A\x0Ares_target\x18M \x01(\x0B2\x13.pg_query.ResTargetH\x00R\x09ResTarget\x12D\x0A\x10multi_assign_ref\x18N \x01(\x0B2\x18.pg_query.MultiAssignRefH\x00R\x0EMultiAssignRef\x12+\x0A\x07sort_by\x18O \x01(\x0B2\x10.pg_query.SortByH\x00R\x06SortBy\x124\x0A\x0Awindow_def\x18P \x01(\x0B2\x13.pg_query.WindowDefH\x00R\x09WindowDef\x12C\x0A\x0Frange_subselect\x18Q \x01(\x0B2\x18.pg_query.RangeSubselectH\x00R\x0ERangeSubselect\x12@\x0A\x0Erange_function\x18R \x01(\x0B2\x17.pg_query.RangeFunctionH\x00R\x0DRangeFunction\x12D\x0A\x10range_table_func\x18S \x01(\x0B2\x18.pg_query.RangeTableFuncH\x00R\x0ERangeTableFunc\x12N\x0A\x14range_table_func_col\x18T \x01(\x0B2\x1B.pg_query.RangeTableFuncColH\x00R\x11RangeTableFuncCol\x12J\x0A\x12range_table_sample\x18U \x01(\x0B2\x1A.pg_query.RangeTableSampleH\x00R\x10RangeTableSample\x124\x0A\x0Acolumn_def\x18V \x01(\x0B2\x13.pg_query.ColumnDefH\x00R\x09ColumnDef\x12G\x0A\x11table_like_clause\x18W \x01(\x0B2\x19.pg_query.TableLikeClauseH\x00R\x0FTableLikeClause\x124\x0A\x0Aindex_elem\x18X \x01(\x0B2\x13.pg_query.IndexElemH\x00R\x09IndexElem\x12.\x0A\x08def_elem\x18Y \x01(\x0B2\x11.pg_query.DefElemH\x00R\x07DefElem\x12@\x0A\x0Elocking_clause\x18Z \x01(\x0B2\x17.pg_query.LockingClauseH\x00R\x0DLockingClause\x12=\x0A\x0Dxml_serialize\x18[ \x01(\x0B2\x16.pg_query.XmlSerializeH\x00R\x0CXmlSerialize\x12@\x0A\x0Epartition_elem\x18\\ \x01(\x0B2\x17.pg_query.PartitionElemH\x00R\x0DPartitionElem\x12@\x0A\x0Epartition_spec\x18] \x01(\x0B2\x17.pg_query.PartitionSpecH\x00R\x0DPartitionSpec\x12P\x0A\x14partition_bound_spec\x18^ \x01(\x0B2\x1C.pg_query.PartitionBoundSpecH\x00R\x12PartitionBoundSpec\x12S\x0A\x15partition_range_datum\x18_ \x01(\x0B2\x1D.pg_query.PartitionRangeDatumH\x00R\x13PartitionRangeDatum\x12S\x0A\x15single_partition_spec\x18` \x01(\x0B2\x1D.pg_query.SinglePartitionSpecH\x00R\x13SinglePartitionSpec\x12=\x0A\x0Dpartition_cmd\x18a \x01(\x0B2\x16.pg_query.PartitionCmdH\x00R\x0CPartitionCmd\x12A\x0A\x0Frange_tbl_entry\x18b \x01(\x0B2\x17.pg_query.RangeTblEntryH\x00R\x0DRangeTblEntry\x12L\x0A\x12rtepermission_info\x18c \x01(\x0B2\x1B.pg_query.RTEPermissionInfoH\x00R\x11RTEPermissionInfo\x12J\x0A\x12range_tbl_function\x18d \x01(\x0B2\x1A.pg_query.RangeTblFunctionH\x00R\x10RangeTblFunction\x12M\x0A\x13table_sample_clause\x18e \x01(\x0B2\x1B.pg_query.TableSampleClauseH\x00R\x11TableSampleClause\x12G\x0A\x11with_check_option\x18f \x01(\x0B2\x19.pg_query.WithCheckOptionH\x00R\x0FWithCheckOption\x12G\x0A\x11sort_group_clause\x18g \x01(\x0B2\x19.pg_query.SortGroupClauseH\x00R\x0FSortGroupClause\x12:\x0A\x0Cgrouping_set\x18h \x01(\x0B2\x15.pg_query.GroupingSetH\x00R\x0BGroupingSet\x12=\x0A\x0Dwindow_clause\x18i \x01(\x0B2\x16.pg_query.WindowClauseH\x00R\x0CWindowClause\x12A\x0A\x0Frow_mark_clause\x18j \x01(\x0B2\x17.pg_query.RowMarkClauseH\x00R\x0DRowMarkClause\x127\x0A\x0Bwith_clause\x18k \x01(\x0B2\x14.pg_query.WithClauseH\x00R\x0AWithClause\x12:\x0A\x0Cinfer_clause\x18l \x01(\x0B2\x15.pg_query.InferClauseH\x00R\x0BInferClause\x12J\x0A\x12on_conflict_clause\x18m \x01(\x0B2\x1A.pg_query.OnConflictClauseH\x00R\x10OnConflictClause\x12F\x0A\x10ctesearch_clause\x18n \x01(\x0B2\x19.pg_query.CTESearchClauseH\x00R\x0FCTESearchClause\x12C\x0A\x0Fctecycle_clause\x18o \x01(\x0B2\x18.pg_query.CTECycleClauseH\x00R\x0ECTECycleClause\x12G\x0A\x11common_table_expr\x18p \x01(\x0B2\x19.pg_query.CommonTableExprH\x00R\x0FCommonTableExpr\x12G\x0A\x11merge_when_clause\x18q \x01(\x0B2\x19.pg_query.MergeWhenClauseH\x00R\x0FMergeWhenClause\x12L\x0A\x12trigger_transition\x18r \x01(\x0B2\x1B.pg_query.TriggerTransitionH\x00R\x11TriggerTransition\x127\x0A\x0Bjson_output\x18s \x01(\x0B2\x14.pg_query.JsonOutputH\x00R\x0AJsonOutput\x12=\x0A\x0Djson_argument\x18t \x01(\x0B2\x16.pg_query.JsonArgumentH\x00R\x0CJsonArgument\x12>\x0A\x0Ejson_func_expr\x18u \x01(\x0B2\x16.pg_query.JsonFuncExprH\x00R\x0CJsonFuncExpr\x12N\x0A\x14json_table_path_spec\x18v \x01(\x0B2\x1B.pg_query.JsonTablePathSpecH\x00R\x11JsonTablePathSpec\x124\x0A\x0Ajson_table\x18w \x01(\x0B2\x13.pg_query.JsonTableH\x00R\x09JsonTable\x12G\x0A\x11json_table_column\x18x \x01(\x0B2\x19.pg_query.JsonTableColumnH\x00R\x0FJsonTableColumn\x12>\x0A\x0Ejson_key_value\x18y \x01(\x0B2\x16.pg_query.JsonKeyValueH\x00R\x0CJsonKeyValue\x12A\x0A\x0Fjson_parse_expr\x18z \x01(\x0B2\x17.pg_query.JsonParseExprH\x00R\x0DJsonParseExpr\x12D\x0A\x10json_scalar_expr\x18{ \x01(\x0B2\x18.pg_query.JsonScalarExprH\x00R\x0EJsonScalarExpr\x12M\x0A\x13json_serialize_expr\x18| \x01(\x0B2\x1B.pg_query.JsonSerializeExprH\x00R\x11JsonSerializeExpr\x12Y\x0A\x17json_object_constructor\x18} \x01(\x0B2\x1F.pg_query.JsonObjectConstructorH\x00R\x15JsonObjectConstructor\x12V\x0A\x16json_array_constructor\x18~ \x01(\x0B2\x1E.pg_query.JsonArrayConstructorH\x00R\x14JsonArrayConstructor\x12f\x0A\x1Cjson_array_query_constructor\x18\x7F \x01(\x0B2#.pg_query.JsonArrayQueryConstructorH\x00R\x19JsonArrayQueryConstructor\x12Q\x0A\x14json_agg_constructor\x18\x80\x01 \x01(\x0B2\x1C.pg_query.JsonAggConstructorH\x00R\x12JsonAggConstructor\x12B\x0A\x0Fjson_object_agg\x18\x81\x01 \x01(\x0B2\x17.pg_query.JsonObjectAggH\x00R\x0DJsonObjectAgg\x12?\x0A\x0Ejson_array_agg\x18\x82\x01 \x01(\x0B2\x16.pg_query.JsonArrayAggH\x00R\x0CJsonArrayAgg\x12/\x0A\x08raw_stmt\x18\x83\x01 \x01(\x0B2\x11.pg_query.RawStmtH\x00R\x07RawStmt\x128\x0A\x0Binsert_stmt\x18\x84\x01 \x01(\x0B2\x14.pg_query.InsertStmtH\x00R\x0AInsertStmt\x128\x0A\x0Bdelete_stmt\x18\x85\x01 \x01(\x0B2\x14.pg_query.DeleteStmtH\x00R\x0ADeleteStmt\x128\x0A\x0Bupdate_stmt\x18\x86\x01 \x01(\x0B2\x14.pg_query.UpdateStmtH\x00R\x0AUpdateStmt\x125\x0A\x0Amerge_stmt\x18\x87\x01 \x01(\x0B2\x13.pg_query.MergeStmtH\x00R\x09MergeStmt\x128\x0A\x0Bselect_stmt\x18\x88\x01 \x01(\x0B2\x14.pg_query.SelectStmtH\x00R\x0ASelectStmt\x12K\x0A\x12set_operation_stmt\x18\x89\x01 \x01(\x0B2\x1A.pg_query.SetOperationStmtH\x00R\x10SetOperationStmt\x128\x0A\x0Breturn_stmt\x18\x8A\x01 \x01(\x0B2\x14.pg_query.ReturnStmtH\x00R\x0AReturnStmt\x12>\x0A\x0Dplassign_stmt\x18\x8B\x01 \x01(\x0B2\x16.pg_query.PLAssignStmtH\x00R\x0CPLAssignStmt\x12K\x0A\x12create_schema_stmt\x18\x8C\x01 \x01(\x0B2\x1A.pg_query.CreateSchemaStmtH\x00R\x10CreateSchemaStmt\x12E\x0A\x10alter_table_stmt\x18\x8D\x01 \x01(\x0B2\x18.pg_query.AlterTableStmtH\x00R\x0EAlterTableStmt\x12T\x0A\x15replica_identity_stmt\x18\x8E\x01 \x01(\x0B2\x1D.pg_query.ReplicaIdentityStmtH\x00R\x13ReplicaIdentityStmt\x12B\x0A\x0Falter_table_cmd\x18\x8F\x01 \x01(\x0B2\x17.pg_query.AlterTableCmdH\x00R\x0DAlterTableCmd\x12Q\x0A\x14alter_collation_stmt\x18\x90\x01 \x01(\x0B2\x1C.pg_query.AlterCollationStmtH\x00R\x12AlterCollationStmt\x12H\x0A\x11alter_domain_stmt\x18\x91\x01 \x01(\x0B2\x19.pg_query.AlterDomainStmtH\x00R\x0FAlterDomainStmt\x125\x0A\x0Agrant_stmt\x18\x92\x01 \x01(\x0B2\x13.pg_query.GrantStmtH\x00R\x09GrantStmt\x12E\x0A\x10object_with_args\x18\x93\x01 \x01(\x0B2\x18.pg_query.ObjectWithArgsH\x00R\x0EObjectWithArgs\x128\x0A\x0Baccess_priv\x18\x94\x01 \x01(\x0B2\x14.pg_query.AccessPrivH\x00R\x0AAccessPriv\x12B\x0A\x0Fgrant_role_stmt\x18\x95\x01 \x01(\x0B2\x17.pg_query.GrantRoleStmtH\x00R\x0DGrantRoleStmt\x12j\x0A\x1Dalter_default_privileges_stmt\x18\x96\x01 \x01(\x0B2\$.pg_query.AlterDefaultPrivilegesStmtH\x00R\x1AAlterDefaultPrivilegesStmt\x122\x0A\x09copy_stmt\x18\x97\x01 \x01(\x0B2\x12.pg_query.CopyStmtH\x00R\x08CopyStmt\x12H\x0A\x11variable_set_stmt\x18\x98\x01 \x01(\x0B2\x19.pg_query.VariableSetStmtH\x00R\x0FVariableSetStmt\x12K\x0A\x12variable_show_stmt\x18\x99\x01 \x01(\x0B2\x1A.pg_query.VariableShowStmtH\x00R\x10VariableShowStmt\x128\x0A\x0Bcreate_stmt\x18\x9A\x01 \x01(\x0B2\x14.pg_query.CreateStmtH\x00R\x0ACreateStmt\x127\x0A\x0Aconstraint\x18\x9B\x01 \x01(\x0B2\x14.pg_query.ConstraintH\x00R\x0AConstraint\x12X\x0A\x17create_table_space_stmt\x18\x9C\x01 \x01(\x0B2\x1E.pg_query.CreateTableSpaceStmtH\x00R\x14CreateTableSpaceStmt\x12R\x0A\x15drop_table_space_stmt\x18\x9D\x01 \x01(\x0B2\x1C.pg_query.DropTableSpaceStmtH\x00R\x12DropTableSpaceStmt\x12k\x0A\x1Ealter_table_space_options_stmt\x18\x9E\x01 \x01(\x0B2\$.pg_query.AlterTableSpaceOptionsStmtH\x00R\x1AAlterTableSpaceOptionsStmt\x12\\\x0A\x19alter_table_move_all_stmt\x18\x9F\x01 \x01(\x0B2\x1F.pg_query.AlterTableMoveAllStmtH\x00R\x15AlterTableMoveAllStmt\x12T\x0A\x15create_extension_stmt\x18\xA0\x01 \x01(\x0B2\x1D.pg_query.CreateExtensionStmtH\x00R\x13CreateExtensionStmt\x12Q\x0A\x14alter_extension_stmt\x18\xA1\x01 \x01(\x0B2\x1C.pg_query.AlterExtensionStmtH\x00R\x12AlterExtensionStmt\x12j\x0A\x1Dalter_extension_contents_stmt\x18\xA2\x01 \x01(\x0B2\$.pg_query.AlterExtensionContentsStmtH\x00R\x1AAlterExtensionContentsStmt\x12B\x0A\x0Fcreate_fdw_stmt\x18\xA3\x01 \x01(\x0B2\x17.pg_query.CreateFdwStmtH\x00R\x0DCreateFdwStmt\x12?\x0A\x0Ealter_fdw_stmt\x18\xA4\x01 \x01(\x0B2\x16.pg_query.AlterFdwStmtH\x00R\x0CAlterFdwStmt\x12a\x0A\x1Acreate_foreign_server_stmt\x18\xA5\x01 \x01(\x0B2!.pg_query.CreateForeignServerStmtH\x00R\x17CreateForeignServerStmt\x12^\x0A\x19alter_foreign_server_stmt\x18\xA6\x01 \x01(\x0B2 .pg_query.AlterForeignServerStmtH\x00R\x16AlterForeignServerStmt\x12^\x0A\x19create_foreign_table_stmt\x18\xA7\x01 \x01(\x0B2 .pg_query.CreateForeignTableStmtH\x00R\x16CreateForeignTableStmt\x12[\x0A\x18create_user_mapping_stmt\x18\xA8\x01 \x01(\x0B2\x1F.pg_query.CreateUserMappingStmtH\x00R\x15CreateUserMappingStmt\x12X\x0A\x17alter_user_mapping_stmt\x18\xA9\x01 \x01(\x0B2\x1E.pg_query.AlterUserMappingStmtH\x00R\x14AlterUserMappingStmt\x12U\x0A\x16drop_user_mapping_stmt\x18\xAA\x01 \x01(\x0B2\x1D.pg_query.DropUserMappingStmtH\x00R\x13DropUserMappingStmt\x12a\x0A\x1Aimport_foreign_schema_stmt\x18\xAB\x01 \x01(\x0B2!.pg_query.ImportForeignSchemaStmtH\x00R\x17ImportForeignSchemaStmt\x12K\x0A\x12create_policy_stmt\x18\xAC\x01 \x01(\x0B2\x1A.pg_query.CreatePolicyStmtH\x00R\x10CreatePolicyStmt\x12H\x0A\x11alter_policy_stmt\x18\xAD\x01 \x01(\x0B2\x19.pg_query.AlterPolicyStmtH\x00R\x0FAlterPolicyStmt\x12?\x0A\x0Ecreate_am_stmt\x18\xAE\x01 \x01(\x0B2\x16.pg_query.CreateAmStmtH\x00R\x0CCreateAmStmt\x12E\x0A\x10create_trig_stmt\x18\xAF\x01 \x01(\x0B2\x18.pg_query.CreateTrigStmtH\x00R\x0ECreateTrigStmt\x12U\x0A\x16create_event_trig_stmt\x18\xB0\x01 \x01(\x0B2\x1D.pg_query.CreateEventTrigStmtH\x00R\x13CreateEventTrigStmt\x12R\x0A\x15alter_event_trig_stmt\x18\xB1\x01 \x01(\x0B2\x1C.pg_query.AlterEventTrigStmtH\x00R\x12AlterEventTrigStmt\x12H\x0A\x11create_plang_stmt\x18\xB2\x01 \x01(\x0B2\x19.pg_query.CreatePLangStmtH\x00R\x0FCreatePLangStmt\x12E\x0A\x10create_role_stmt\x18\xB3\x01 \x01(\x0B2\x18.pg_query.CreateRoleStmtH\x00R\x0ECreateRoleStmt\x12B\x0A\x0Falter_role_stmt\x18\xB4\x01 \x01(\x0B2\x17.pg_query.AlterRoleStmtH\x00R\x0DAlterRoleStmt\x12L\x0A\x13alter_role_set_stmt\x18\xB5\x01 \x01(\x0B2\x1A.pg_query.AlterRoleSetStmtH\x00R\x10AlterRoleSetStmt\x12?\x0A\x0Edrop_role_stmt\x18\xB6\x01 \x01(\x0B2\x16.pg_query.DropRoleStmtH\x00R\x0CDropRoleStmt\x12B\x0A\x0Fcreate_seq_stmt\x18\xB7\x01 \x01(\x0B2\x17.pg_query.CreateSeqStmtH\x00R\x0DCreateSeqStmt\x12?\x0A\x0Ealter_seq_stmt\x18\xB8\x01 \x01(\x0B2\x16.pg_query.AlterSeqStmtH\x00R\x0CAlterSeqStmt\x128\x0A\x0Bdefine_stmt\x18\xB9\x01 \x01(\x0B2\x14.pg_query.DefineStmtH\x00R\x0ADefineStmt\x12K\x0A\x12create_domain_stmt\x18\xBA\x01 \x01(\x0B2\x1A.pg_query.CreateDomainStmtH\x00R\x10CreateDomainStmt\x12O\x0A\x14create_op_class_stmt\x18\xBB\x01 \x01(\x0B2\x1B.pg_query.CreateOpClassStmtH\x00R\x11CreateOpClassStmt\x12O\x0A\x14create_op_class_item\x18\xBC\x01 \x01(\x0B2\x1B.pg_query.CreateOpClassItemH\x00R\x11CreateOpClassItem\x12R\x0A\x15create_op_family_stmt\x18\xBD\x01 \x01(\x0B2\x1C.pg_query.CreateOpFamilyStmtH\x00R\x12CreateOpFamilyStmt\x12O\x0A\x14alter_op_family_stmt\x18\xBE\x01 \x01(\x0B2\x1B.pg_query.AlterOpFamilyStmtH\x00R\x11AlterOpFamilyStmt\x122\x0A\x09drop_stmt\x18\xBF\x01 \x01(\x0B2\x12.pg_query.DropStmtH\x00R\x08DropStmt\x12>\x0A\x0Dtruncate_stmt\x18\xC0\x01 \x01(\x0B2\x16.pg_query.TruncateStmtH\x00R\x0CTruncateStmt\x12;\x0A\x0Ccomment_stmt\x18\xC1\x01 \x01(\x0B2\x15.pg_query.CommentStmtH\x00R\x0BCommentStmt\x12?\x0A\x0Esec_label_stmt\x18\xC2\x01 \x01(\x0B2\x16.pg_query.SecLabelStmtH\x00R\x0CSecLabelStmt\x12N\x0A\x13declare_cursor_stmt\x18\xC3\x01 \x01(\x0B2\x1B.pg_query.DeclareCursorStmtH\x00R\x11DeclareCursorStmt\x12H\x0A\x11close_portal_stmt\x18\xC4\x01 \x01(\x0B2\x19.pg_query.ClosePortalStmtH\x00R\x0FClosePortalStmt\x125\x0A\x0Afetch_stmt\x18\xC5\x01 \x01(\x0B2\x13.pg_query.FetchStmtH\x00R\x09FetchStmt\x125\x0A\x0Aindex_stmt\x18\xC6\x01 \x01(\x0B2\x13.pg_query.IndexStmtH\x00R\x09IndexStmt\x12H\x0A\x11create_stats_stmt\x18\xC7\x01 \x01(\x0B2\x19.pg_query.CreateStatsStmtH\x00R\x0FCreateStatsStmt\x125\x0A\x0Astats_elem\x18\xC8\x01 \x01(\x0B2\x13.pg_query.StatsElemH\x00R\x09StatsElem\x12E\x0A\x10alter_stats_stmt\x18\xC9\x01 \x01(\x0B2\x18.pg_query.AlterStatsStmtH\x00R\x0EAlterStatsStmt\x12Q\x0A\x14create_function_stmt\x18\xCA\x01 \x01(\x0B2\x1C.pg_query.CreateFunctionStmtH\x00R\x12CreateFunctionStmt\x12M\x0A\x12function_parameter\x18\xCB\x01 \x01(\x0B2\x1B.pg_query.FunctionParameterH\x00R\x11FunctionParameter\x12N\x0A\x13alter_function_stmt\x18\xCC\x01 \x01(\x0B2\x1B.pg_query.AlterFunctionStmtH\x00R\x11AlterFunctionStmt\x12,\x0A\x07do_stmt\x18\xCD\x01 \x01(\x0B2\x10.pg_query.DoStmtH\x00R\x06DoStmt\x12H\x0A\x11inline_code_block\x18\xCE\x01 \x01(\x0B2\x19.pg_query.InlineCodeBlockH\x00R\x0FInlineCodeBlock\x122\x0A\x09call_stmt\x18\xCF\x01 \x01(\x0B2\x12.pg_query.CallStmtH\x00R\x08CallStmt\x12;\x0A\x0Ccall_context\x18\xD0\x01 \x01(\x0B2\x15.pg_query.CallContextH\x00R\x0BCallContext\x128\x0A\x0Brename_stmt\x18\xD1\x01 \x01(\x0B2\x14.pg_query.RenameStmtH\x00R\x0ARenameStmt\x12^\x0A\x19alter_object_depends_stmt\x18\xD2\x01 \x01(\x0B2 .pg_query.AlterObjectDependsStmtH\x00R\x16AlterObjectDependsStmt\x12[\x0A\x18alter_object_schema_stmt\x18\xD3\x01 \x01(\x0B2\x1F.pg_query.AlterObjectSchemaStmtH\x00R\x15AlterObjectSchemaStmt\x12E\x0A\x10alter_owner_stmt\x18\xD4\x01 \x01(\x0B2\x18.pg_query.AlterOwnerStmtH\x00R\x0EAlterOwnerStmt\x12N\x0A\x13alter_operator_stmt\x18\xD5\x01 \x01(\x0B2\x1B.pg_query.AlterOperatorStmtH\x00R\x11AlterOperatorStmt\x12B\x0A\x0Falter_type_stmt\x18\xD6\x01 \x01(\x0B2\x17.pg_query.AlterTypeStmtH\x00R\x0DAlterTypeStmt\x122\x0A\x09rule_stmt\x18\xD7\x01 \x01(\x0B2\x12.pg_query.RuleStmtH\x00R\x08RuleStmt\x128\x0A\x0Bnotify_stmt\x18\xD8\x01 \x01(\x0B2\x14.pg_query.NotifyStmtH\x00R\x0ANotifyStmt\x128\x0A\x0Blisten_stmt\x18\xD9\x01 \x01(\x0B2\x14.pg_query.ListenStmtH\x00R\x0AListenStmt\x12>\x0A\x0Dunlisten_stmt\x18\xDA\x01 \x01(\x0B2\x16.pg_query.UnlistenStmtH\x00R\x0CUnlistenStmt\x12G\x0A\x10transaction_stmt\x18\xDB\x01 \x01(\x0B2\x19.pg_query.TransactionStmtH\x00R\x0FTransactionStmt\x12N\x0A\x13composite_type_stmt\x18\xDC\x01 \x01(\x0B2\x1B.pg_query.CompositeTypeStmtH\x00R\x11CompositeTypeStmt\x12E\x0A\x10create_enum_stmt\x18\xDD\x01 \x01(\x0B2\x18.pg_query.CreateEnumStmtH\x00R\x0ECreateEnumStmt\x12H\x0A\x11create_range_stmt\x18\xDE\x01 \x01(\x0B2\x19.pg_query.CreateRangeStmtH\x00R\x0FCreateRangeStmt\x12B\x0A\x0Falter_enum_stmt\x18\xDF\x01 \x01(\x0B2\x17.pg_query.AlterEnumStmtH\x00R\x0DAlterEnumStmt\x122\x0A\x09view_stmt\x18\xE0\x01 \x01(\x0B2\x12.pg_query.ViewStmtH\x00R\x08ViewStmt\x122\x0A\x09load_stmt\x18\xE1\x01 \x01(\x0B2\x12.pg_query.LoadStmtH\x00R\x08LoadStmt\x12>\x0A\x0Dcreatedb_stmt\x18\xE2\x01 \x01(\x0B2\x16.pg_query.CreatedbStmtH\x00R\x0CCreatedbStmt\x12N\x0A\x13alter_database_stmt\x18\xE3\x01 \x01(\x0B2\x1B.pg_query.AlterDatabaseStmtH\x00R\x11AlterDatabaseStmt\x12q\x0A alter_database_refresh_coll_stmt\x18\xE4\x01 \x01(\x0B2&.pg_query.AlterDatabaseRefreshCollStmtH\x00R\x1CAlterDatabaseRefreshCollStmt\x12X\x0A\x17alter_database_set_stmt\x18\xE5\x01 \x01(\x0B2\x1E.pg_query.AlterDatabaseSetStmtH\x00R\x14AlterDatabaseSetStmt\x128\x0A\x0Bdropdb_stmt\x18\xE6\x01 \x01(\x0B2\x14.pg_query.DropdbStmtH\x00R\x0ADropdbStmt\x12H\x0A\x11alter_system_stmt\x18\xE7\x01 \x01(\x0B2\x19.pg_query.AlterSystemStmtH\x00R\x0FAlterSystemStmt\x12;\x0A\x0Ccluster_stmt\x18\xE8\x01 \x01(\x0B2\x15.pg_query.ClusterStmtH\x00R\x0BClusterStmt\x128\x0A\x0Bvacuum_stmt\x18\xE9\x01 \x01(\x0B2\x14.pg_query.VacuumStmtH\x00R\x0AVacuumStmt\x12D\x0A\x0Fvacuum_relation\x18\xEA\x01 \x01(\x0B2\x18.pg_query.VacuumRelationH\x00R\x0EVacuumRelation\x12;\x0A\x0Cexplain_stmt\x18\xEB\x01 \x01(\x0B2\x15.pg_query.ExplainStmtH\x00R\x0BExplainStmt\x12O\x0A\x14create_table_as_stmt\x18\xEC\x01 \x01(\x0B2\x1B.pg_query.CreateTableAsStmtH\x00R\x11CreateTableAsStmt\x12R\x0A\x15refresh_mat_view_stmt\x18\xED\x01 \x01(\x0B2\x1C.pg_query.RefreshMatViewStmtH\x00R\x12RefreshMatViewStmt\x12E\x0A\x10check_point_stmt\x18\xEE\x01 \x01(\x0B2\x18.pg_query.CheckPointStmtH\x00R\x0ECheckPointStmt\x12;\x0A\x0Cdiscard_stmt\x18\xEF\x01 \x01(\x0B2\x15.pg_query.DiscardStmtH\x00R\x0BDiscardStmt\x122\x0A\x09lock_stmt\x18\xF0\x01 \x01(\x0B2\x12.pg_query.LockStmtH\x00R\x08LockStmt\x12Q\x0A\x14constraints_set_stmt\x18\xF1\x01 \x01(\x0B2\x1C.pg_query.ConstraintsSetStmtH\x00R\x12ConstraintsSetStmt\x12;\x0A\x0Creindex_stmt\x18\xF2\x01 \x01(\x0B2\x15.pg_query.ReindexStmtH\x00R\x0BReindexStmt\x12W\x0A\x16create_conversion_stmt\x18\xF3\x01 \x01(\x0B2\x1E.pg_query.CreateConversionStmtH\x00R\x14CreateConversionStmt\x12E\x0A\x10create_cast_stmt\x18\xF4\x01 \x01(\x0B2\x18.pg_query.CreateCastStmtH\x00R\x0ECreateCastStmt\x12T\x0A\x15create_transform_stmt\x18\xF5\x01 \x01(\x0B2\x1D.pg_query.CreateTransformStmtH\x00R\x13CreateTransformStmt\x12;\x0A\x0Cprepare_stmt\x18\xF6\x01 \x01(\x0B2\x15.pg_query.PrepareStmtH\x00R\x0BPrepareStmt\x12;\x0A\x0Cexecute_stmt\x18\xF7\x01 \x01(\x0B2\x15.pg_query.ExecuteStmtH\x00R\x0BExecuteStmt\x12D\x0A\x0Fdeallocate_stmt\x18\xF8\x01 \x01(\x0B2\x18.pg_query.DeallocateStmtH\x00R\x0EDeallocateStmt\x12B\x0A\x0Fdrop_owned_stmt\x18\xF9\x01 \x01(\x0B2\x17.pg_query.DropOwnedStmtH\x00R\x0DDropOwnedStmt\x12N\x0A\x13reassign_owned_stmt\x18\xFA\x01 \x01(\x0B2\x1B.pg_query.ReassignOwnedStmtH\x00R\x11ReassignOwnedStmt\x12Z\x0A\x17alter_tsdictionary_stmt\x18\xFB\x01 \x01(\x0B2\x1F.pg_query.AlterTSDictionaryStmtH\x00R\x15AlterTSDictionaryStmt\x12c\x0A\x1Aalter_tsconfiguration_stmt\x18\xFC\x01 \x01(\x0B2\".pg_query.AlterTSConfigurationStmtH\x00R\x18AlterTSConfigurationStmt\x12J\x0A\x11publication_table\x18\xFD\x01 \x01(\x0B2\x1A.pg_query.PublicationTableH\x00R\x10PublicationTable\x12Q\x0A\x14publication_obj_spec\x18\xFE\x01 \x01(\x0B2\x1C.pg_query.PublicationObjSpecH\x00R\x12PublicationObjSpec\x12Z\x0A\x17create_publication_stmt\x18\xFF\x01 \x01(\x0B2\x1F.pg_query.CreatePublicationStmtH\x00R\x15CreatePublicationStmt\x12W\x0A\x16alter_publication_stmt\x18\x80\x02 \x01(\x0B2\x1E.pg_query.AlterPublicationStmtH\x00R\x14AlterPublicationStmt\x12]\x0A\x18create_subscription_stmt\x18\x81\x02 \x01(\x0B2 .pg_query.CreateSubscriptionStmtH\x00R\x16CreateSubscriptionStmt\x12Z\x0A\x17alter_subscription_stmt\x18\x82\x02 \x01(\x0B2\x1F.pg_query.AlterSubscriptionStmtH\x00R\x15AlterSubscriptionStmt\x12W\x0A\x16drop_subscription_stmt\x18\x83\x02 \x01(\x0B2\x1E.pg_query.DropSubscriptionStmtH\x00R\x14DropSubscriptionStmt\x12.\x0A\x07integer\x18\x84\x02 \x01(\x0B2\x11.pg_query.IntegerH\x00R\x07Integer\x12(\x0A\x05float\x18\x85\x02 \x01(\x0B2\x0F.pg_query.FloatH\x00R\x05Float\x12.\x0A\x07boolean\x18\x86\x02 \x01(\x0B2\x11.pg_query.BooleanH\x00R\x07Boolean\x12+\x0A\x06string\x18\x87\x02 \x01(\x0B2\x10.pg_query.StringH\x00R\x06String\x125\x0A\x0Abit_string\x18\x88\x02 \x01(\x0B2\x13.pg_query.BitStringH\x00R\x09BitString\x12%\x0A\x04list\x18\x89\x02 \x01(\x0B2\x0E.pg_query.ListH\x00R\x04List\x12/\x0A\x08int_list\x18\x8A\x02 \x01(\x0B2\x11.pg_query.IntListH\x00R\x07IntList\x12/\x0A\x08oid_list\x18\x8B\x02 \x01(\x0B2\x11.pg_query.OidListH\x00R\x07OidList\x12.\x0A\x07a_const\x18\x8C\x02 \x01(\x0B2\x11.pg_query.A_ConstH\x00R\x07A_ConstB\x06\x0A\x04node\"\x17\x0A\x07Integer\x12\x0C\x0A\x04ival\x18\x01 \x01(\x05\"\x15\x0A\x05Float\x12\x0C\x0A\x04fval\x18\x01 \x01(\x09\"\x1A\x0A\x07Boolean\x12\x0F\x0A\x07boolval\x18\x01 \x01(\x08\"\x16\x0A\x06String\x12\x0C\x0A\x04sval\x18\x01 \x01(\x09\"\x1A\x0A\x09BitString\x12\x0D\x0A\x05bsval\x18\x01 \x01(\x09\"%\x0A\x04List\x12\x1D\x0A\x05items\x18\x01 \x03(\x0B2\x0E.pg_query.Node\"(\x0A\x07OidList\x12\x1D\x0A\x05items\x18\x01 \x03(\x0B2\x0E.pg_query.Node\"(\x0A\x07IntList\x12\x1D\x0A\x05items\x18\x01 \x03(\x0B2\x0E.pg_query.Node\"\xE4\x01\x0A\x07A_Const\x12!\x0A\x04ival\x18\x01 \x01(\x0B2\x11.pg_query.IntegerH\x00\x12\x1F\x0A\x04fval\x18\x02 \x01(\x0B2\x0F.pg_query.FloatH\x00\x12\$\x0A\x07boolval\x18\x03 \x01(\x0B2\x11.pg_query.BooleanH\x00\x12 \x0A\x04sval\x18\x04 \x01(\x0B2\x10.pg_query.StringH\x00\x12\$\x0A\x05bsval\x18\x05 \x01(\x0B2\x13.pg_query.BitStringH\x00\x12\x0E\x0A\x06isnull\x18\x0A \x01(\x08\x12\x10\x0A\x08location\x18\x0B \x01(\x05B\x05\x0A\x03val\"Q\x0A\x05Alias\x12\x1C\x0A\x09aliasname\x18\x01 \x01(\x09R\x09aliasname\x12*\x0A\x08colnames\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x08colnames\"\xE3\x01\x0A\x08RangeVar\x12 \x0A\x0Bcatalogname\x18\x01 \x01(\x09R\x0Bcatalogname\x12\x1E\x0A\x0Aschemaname\x18\x02 \x01(\x09R\x0Aschemaname\x12\x18\x0A\x07relname\x18\x03 \x01(\x09R\x07relname\x12\x10\x0A\x03inh\x18\x04 \x01(\x08R\x03inh\x12&\x0A\x0Erelpersistence\x18\x05 \x01(\x09R\x0Erelpersistence\x12%\x0A\x05alias\x18\x06 \x01(\x0B2\x0F.pg_query.AliasR\x05alias\x12\x1A\x0A\x08location\x18\x07 \x01(\x05R\x08location\"\xF4\x05\x0A\x09TableFunc\x123\x0A\x08functype\x18\x01 \x01(\x0E2\x17.pg_query.TableFuncTypeR\x08functype\x12(\x0A\x07ns_uris\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x07ns_uris\x12*\x0A\x08ns_names\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x08ns_names\x12(\x0A\x07docexpr\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x07docexpr\x12(\x0A\x07rowexpr\x18\x05 \x01(\x0B2\x0E.pg_query.NodeR\x07rowexpr\x12*\x0A\x08colnames\x18\x06 \x03(\x0B2\x0E.pg_query.NodeR\x08colnames\x12*\x0A\x08coltypes\x18\x07 \x03(\x0B2\x0E.pg_query.NodeR\x08coltypes\x12.\x0A\x0Acoltypmods\x18\x08 \x03(\x0B2\x0E.pg_query.NodeR\x0Acoltypmods\x124\x0A\x0Dcolcollations\x18\x09 \x03(\x0B2\x0E.pg_query.NodeR\x0Dcolcollations\x12*\x0A\x08colexprs\x18\x0A \x03(\x0B2\x0E.pg_query.NodeR\x08colexprs\x120\x0A\x0Bcoldefexprs\x18\x0B \x03(\x0B2\x0E.pg_query.NodeR\x0Bcoldefexprs\x120\x0A\x0Bcolvalexprs\x18\x0C \x03(\x0B2\x0E.pg_query.NodeR\x0Bcolvalexprs\x128\x0A\x0Fpassingvalexprs\x18\x0D \x03(\x0B2\x0E.pg_query.NodeR\x0Fpassingvalexprs\x12\x1A\x0A\x08notnulls\x18\x0E \x03(\x04R\x08notnulls\x12\"\x0A\x04plan\x18\x0F \x01(\x0B2\x0E.pg_query.NodeR\x04plan\x12\$\x0A\x0Dordinalitycol\x18\x10 \x01(\x05R\x0Dordinalitycol\x12\x1A\x0A\x08location\x18\x11 \x01(\x05R\x08location\"\xDB\x02\x0A\x0AIntoClause\x12\$\x0A\x03rel\x18\x01 \x01(\x0B2\x12.pg_query.RangeVarR\x03rel\x12+\x0A\x09col_names\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x08colNames\x12#\x0A\x0Daccess_method\x18\x03 \x01(\x09R\x0CaccessMethod\x12(\x0A\x07options\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x07options\x125\x0A\x09on_commit\x18\x05 \x01(\x0E2\x18.pg_query.OnCommitActionR\x08onCommit\x12(\x0A\x10table_space_name\x18\x06 \x01(\x09R\x0EtableSpaceName\x12-\x0A\x0Aview_query\x18\x07 \x01(\x0B2\x0E.pg_query.NodeR\x09viewQuery\x12\x1B\x0A\x09skip_data\x18\x08 \x01(\x08R\x08skipData\"\x95\x02\x0A\x03Var\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\x14\x0A\x05varno\x18\x02 \x01(\x05R\x05varno\x12\x1A\x0A\x08varattno\x18\x03 \x01(\x05R\x08varattno\x12\x18\x0A\x07vartype\x18\x04 \x01(\x0DR\x07vartype\x12\x1C\x0A\x09vartypmod\x18\x05 \x01(\x05R\x09vartypmod\x12\x1C\x0A\x09varcollid\x18\x06 \x01(\x0DR\x09varcollid\x12&\x0A\x0Evarnullingrels\x18\x07 \x03(\x04R\x0Evarnullingrels\x12 \x0A\x0Bvarlevelsup\x18\x08 \x01(\x0DR\x0Bvarlevelsup\x12\x1A\x0A\x08location\x18\x09 \x01(\x05R\x08location\"\xF4\x01\x0A\x05Param\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x121\x0A\x09paramkind\x18\x02 \x01(\x0E2\x13.pg_query.ParamKindR\x09paramkind\x12\x18\x0A\x07paramid\x18\x03 \x01(\x05R\x07paramid\x12\x1C\x0A\x09paramtype\x18\x04 \x01(\x0DR\x09paramtype\x12 \x0A\x0Bparamtypmod\x18\x05 \x01(\x05R\x0Bparamtypmod\x12 \x0A\x0Bparamcollid\x18\x06 \x01(\x0DR\x0Bparamcollid\x12\x1A\x0A\x08location\x18\x07 \x01(\x05R\x08location\"\xB2\x05\x0A\x06Aggref\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\x1A\x0A\x08aggfnoid\x18\x02 \x01(\x0DR\x08aggfnoid\x12\x18\x0A\x07aggtype\x18\x03 \x01(\x0DR\x07aggtype\x12\x1C\x0A\x09aggcollid\x18\x04 \x01(\x0DR\x09aggcollid\x12 \x0A\x0Binputcollid\x18\x05 \x01(\x0DR\x0Binputcollid\x120\x0A\x0Baggargtypes\x18\x06 \x03(\x0B2\x0E.pg_query.NodeR\x0Baggargtypes\x124\x0A\x0Daggdirectargs\x18\x07 \x03(\x0B2\x0E.pg_query.NodeR\x0Daggdirectargs\x12\"\x0A\x04args\x18\x08 \x03(\x0B2\x0E.pg_query.NodeR\x04args\x12*\x0A\x08aggorder\x18\x09 \x03(\x0B2\x0E.pg_query.NodeR\x08aggorder\x120\x0A\x0Baggdistinct\x18\x0A \x03(\x0B2\x0E.pg_query.NodeR\x0Baggdistinct\x12,\x0A\x09aggfilter\x18\x0B \x01(\x0B2\x0E.pg_query.NodeR\x09aggfilter\x12\x18\x0A\x07aggstar\x18\x0C \x01(\x08R\x07aggstar\x12 \x0A\x0Baggvariadic\x18\x0D \x01(\x08R\x0Baggvariadic\x12\x18\x0A\x07aggkind\x18\x0E \x01(\x09R\x07aggkind\x12 \x0A\x0Bagglevelsup\x18\x0F \x01(\x0DR\x0Bagglevelsup\x12.\x0A\x08aggsplit\x18\x10 \x01(\x0E2\x12.pg_query.AggSplitR\x08aggsplit\x12\x14\x0A\x05aggno\x18\x11 \x01(\x05R\x05aggno\x12\x1E\x0A\x0Aaggtransno\x18\x12 \x01(\x05R\x0Aaggtransno\x12\x1A\x0A\x08location\x18\x13 \x01(\x05R\x08location\"\xB6\x01\x0A\x0CGroupingFunc\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\"\x0A\x04args\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x04args\x12\"\x0A\x04refs\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x04refs\x12 \x0A\x0Bagglevelsup\x18\x04 \x01(\x0DR\x0Bagglevelsup\x12\x1A\x0A\x08location\x18\x05 \x01(\x05R\x08location\"\x91\x03\x0A\x0AWindowFunc\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\x1A\x0A\x08winfnoid\x18\x02 \x01(\x0DR\x08winfnoid\x12\x18\x0A\x07wintype\x18\x03 \x01(\x0DR\x07wintype\x12\x1C\x0A\x09wincollid\x18\x04 \x01(\x0DR\x09wincollid\x12 \x0A\x0Binputcollid\x18\x05 \x01(\x0DR\x0Binputcollid\x12\"\x0A\x04args\x18\x06 \x03(\x0B2\x0E.pg_query.NodeR\x04args\x12,\x0A\x09aggfilter\x18\x07 \x01(\x0B2\x0E.pg_query.NodeR\x09aggfilter\x123\x0A\x0Drun_condition\x18\x08 \x03(\x0B2\x0E.pg_query.NodeR\x0CrunCondition\x12\x16\x0A\x06winref\x18\x09 \x01(\x0DR\x06winref\x12\x18\x0A\x07winstar\x18\x0A \x01(\x08R\x07winstar\x12\x16\x0A\x06winagg\x18\x0B \x01(\x08R\x06winagg\x12\x1A\x0A\x08location\x18\x0C \x01(\x05R\x08location\"\xB2\x01\x0A\x16WindowFuncRunCondition\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\x12\x0A\x04opno\x18\x02 \x01(\x0DR\x04opno\x12 \x0A\x0Binputcollid\x18\x03 \x01(\x0DR\x0Binputcollid\x12\x1E\x0A\x0Awfunc_left\x18\x04 \x01(\x08R\x0Awfunc_left\x12 \x0A\x03arg\x18\x05 \x01(\x0B2\x0E.pg_query.NodeR\x03arg\"\x88\x01\x0A\x10MergeSupportFunc\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\x18\x0A\x07msftype\x18\x02 \x01(\x0DR\x07msftype\x12\x1C\x0A\x09msfcollid\x18\x03 \x01(\x0DR\x09msfcollid\x12\x1A\x0A\x08location\x18\x04 \x01(\x05R\x08location\"\xAF\x03\x0A\x0FSubscriptingRef\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12*\x0A\x10refcontainertype\x18\x02 \x01(\x0DR\x10refcontainertype\x12 \x0A\x0Brefelemtype\x18\x03 \x01(\x0DR\x0Brefelemtype\x12\x1E\x0A\x0Arefrestype\x18\x04 \x01(\x0DR\x0Arefrestype\x12\x1C\x0A\x09reftypmod\x18\x05 \x01(\x05R\x09reftypmod\x12\x1C\x0A\x09refcollid\x18\x06 \x01(\x0DR\x09refcollid\x128\x0A\x0Frefupperindexpr\x18\x07 \x03(\x0B2\x0E.pg_query.NodeR\x0Frefupperindexpr\x128\x0A\x0Freflowerindexpr\x18\x08 \x03(\x0B2\x0E.pg_query.NodeR\x0Freflowerindexpr\x12(\x0A\x07refexpr\x18\x09 \x01(\x0B2\x0E.pg_query.NodeR\x07refexpr\x122\x0A\x0Crefassgnexpr\x18\x0A \x01(\x0B2\x0E.pg_query.NodeR\x0Crefassgnexpr\"\xEA\x02\x0A\x08FuncExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\x16\x0A\x06funcid\x18\x02 \x01(\x0DR\x06funcid\x12&\x0A\x0Efuncresulttype\x18\x03 \x01(\x0DR\x0Efuncresulttype\x12\x1E\x0A\x0Afuncretset\x18\x04 \x01(\x08R\x0Afuncretset\x12\"\x0A\x0Cfuncvariadic\x18\x05 \x01(\x08R\x0Cfuncvariadic\x126\x0A\x0Afuncformat\x18\x06 \x01(\x0E2\x16.pg_query.CoercionFormR\x0Afuncformat\x12\x1E\x0A\x0Afunccollid\x18\x07 \x01(\x0DR\x0Afunccollid\x12 \x0A\x0Binputcollid\x18\x08 \x01(\x0DR\x0Binputcollid\x12\"\x0A\x04args\x18\x09 \x03(\x0B2\x0E.pg_query.NodeR\x04args\x12\x1A\x0A\x08location\x18\x0A \x01(\x05R\x08location\"\xA0\x01\x0A\x0CNamedArgExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12 \x0A\x03arg\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x03arg\x12\x12\x0A\x04name\x18\x03 \x01(\x09R\x04name\x12\x1C\x0A\x09argnumber\x18\x04 \x01(\x05R\x09argnumber\x12\x1A\x0A\x08location\x18\x05 \x01(\x05R\x08location\"\xFC\x01\x0A\x06OpExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\x12\x0A\x04opno\x18\x02 \x01(\x0DR\x04opno\x12\"\x0A\x0Copresulttype\x18\x03 \x01(\x0DR\x0Copresulttype\x12\x1A\x0A\x08opretset\x18\x04 \x01(\x08R\x08opretset\x12\x1A\x0A\x08opcollid\x18\x05 \x01(\x0DR\x08opcollid\x12 \x0A\x0Binputcollid\x18\x06 \x01(\x0DR\x0Binputcollid\x12\"\x0A\x04args\x18\x07 \x03(\x0B2\x0E.pg_query.NodeR\x04args\x12\x1A\x0A\x08location\x18\x08 \x01(\x05R\x08location\"\x82\x02\x0A\x0CDistinctExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\x12\x0A\x04opno\x18\x02 \x01(\x0DR\x04opno\x12\"\x0A\x0Copresulttype\x18\x03 \x01(\x0DR\x0Copresulttype\x12\x1A\x0A\x08opretset\x18\x04 \x01(\x08R\x08opretset\x12\x1A\x0A\x08opcollid\x18\x05 \x01(\x0DR\x08opcollid\x12 \x0A\x0Binputcollid\x18\x06 \x01(\x0DR\x0Binputcollid\x12\"\x0A\x04args\x18\x07 \x03(\x0B2\x0E.pg_query.NodeR\x04args\x12\x1A\x0A\x08location\x18\x08 \x01(\x05R\x08location\"\x80\x02\x0A\x0ANullIfExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\x12\x0A\x04opno\x18\x02 \x01(\x0DR\x04opno\x12\"\x0A\x0Copresulttype\x18\x03 \x01(\x0DR\x0Copresulttype\x12\x1A\x0A\x08opretset\x18\x04 \x01(\x08R\x08opretset\x12\x1A\x0A\x08opcollid\x18\x05 \x01(\x0DR\x08opcollid\x12 \x0A\x0Binputcollid\x18\x06 \x01(\x0DR\x0Binputcollid\x12\"\x0A\x04args\x18\x07 \x03(\x0B2\x0E.pg_query.NodeR\x04args\x12\x1A\x0A\x08location\x18\x08 \x01(\x05R\x08location\"\xC2\x01\x0A\x11ScalarArrayOpExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\x12\x0A\x04opno\x18\x02 \x01(\x0DR\x04opno\x12\x15\x0A\x06use_or\x18\x03 \x01(\x08R\x05useOr\x12 \x0A\x0Binputcollid\x18\x04 \x01(\x0DR\x0Binputcollid\x12\"\x0A\x04args\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x04args\x12\x1A\x0A\x08location\x18\x06 \x01(\x05R\x08location\"\x9C\x01\x0A\x08BoolExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12.\x0A\x06boolop\x18\x02 \x01(\x0E2\x16.pg_query.BoolExprTypeR\x06boolop\x12\"\x0A\x04args\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x04args\x12\x1A\x0A\x08location\x18\x04 \x01(\x05R\x08location\"\xA9\x02\x0A\x07SubLink\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x129\x0A\x0Dsub_link_type\x18\x02 \x01(\x0E2\x15.pg_query.SubLinkTypeR\x0BsubLinkType\x12\x1E\x0A\x0Bsub_link_id\x18\x03 \x01(\x05R\x09subLinkId\x12*\x0A\x08testexpr\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x08testexpr\x12+\x0A\x09oper_name\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x08operName\x12,\x0A\x09subselect\x18\x06 \x01(\x0B2\x0E.pg_query.NodeR\x09subselect\x12\x1A\x0A\x08location\x18\x07 \x01(\x05R\x08location\"\xB5\x05\x0A\x07SubPlan\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x129\x0A\x0Dsub_link_type\x18\x02 \x01(\x0E2\x15.pg_query.SubLinkTypeR\x0BsubLinkType\x12*\x0A\x08testexpr\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x08testexpr\x12+\x0A\x09param_ids\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x08paramIds\x12\x18\x0A\x07plan_id\x18\x05 \x01(\x05R\x07plan_id\x12\x1C\x0A\x09plan_name\x18\x06 \x01(\x09R\x09plan_name\x12\$\x0A\x0Efirst_col_type\x18\x07 \x01(\x0DR\x0CfirstColType\x12(\x0A\x10first_col_typmod\x18\x08 \x01(\x05R\x0EfirstColTypmod\x12.\x0A\x13first_col_collation\x18\x09 \x01(\x0DR\x11firstColCollation\x12\$\x0A\x0Euse_hash_table\x18\x0A \x01(\x08R\x0CuseHashTable\x12(\x0A\x10unknown_eq_false\x18\x0B \x01(\x08R\x0EunknownEqFalse\x12\$\x0A\x0Dparallel_safe\x18\x0C \x01(\x08R\x0Dparallel_safe\x12+\x0A\x09set_param\x18\x0D \x03(\x0B2\x0E.pg_query.NodeR\x08setParam\x12+\x0A\x09par_param\x18\x0E \x03(\x0B2\x0E.pg_query.NodeR\x08parParam\x12\"\x0A\x04args\x18\x0F \x03(\x0B2\x0E.pg_query.NodeR\x04args\x12\"\x0A\x0Cstartup_cost\x18\x10 \x01(\x01R\x0Cstartup_cost\x12\$\x0A\x0Dper_call_cost\x18\x11 \x01(\x01R\x0Dper_call_cost\"b\x0A\x12AlternativeSubPlan\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12*\x0A\x08subplans\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x08subplans\"\xD5\x01\x0A\x0BFieldSelect\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12 \x0A\x03arg\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x03arg\x12\x1A\x0A\x08fieldnum\x18\x03 \x01(\x05R\x08fieldnum\x12\x1E\x0A\x0Aresulttype\x18\x04 \x01(\x0DR\x0Aresulttype\x12\"\x0A\x0Cresulttypmod\x18\x05 \x01(\x05R\x0Cresulttypmod\x12\"\x0A\x0Cresultcollid\x18\x06 \x01(\x0DR\x0Cresultcollid\"\xC8\x01\x0A\x0AFieldStore\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12 \x0A\x03arg\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x03arg\x12(\x0A\x07newvals\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x07newvals\x12,\x0A\x09fieldnums\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x09fieldnums\x12\x1E\x0A\x0Aresulttype\x18\x05 \x01(\x0DR\x0Aresulttype\"\x93\x02\x0A\x0BRelabelType\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12 \x0A\x03arg\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x03arg\x12\x1E\x0A\x0Aresulttype\x18\x03 \x01(\x0DR\x0Aresulttype\x12\"\x0A\x0Cresulttypmod\x18\x04 \x01(\x05R\x0Cresulttypmod\x12\"\x0A\x0Cresultcollid\x18\x05 \x01(\x0DR\x0Cresultcollid\x12<\x0A\x0Drelabelformat\x18\x06 \x01(\x0E2\x16.pg_query.CoercionFormR\x0Drelabelformat\x12\x1A\x0A\x08location\x18\x07 \x01(\x05R\x08location\"\xED\x01\x0A\x0BCoerceViaIO\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12 \x0A\x03arg\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x03arg\x12\x1E\x0A\x0Aresulttype\x18\x03 \x01(\x0DR\x0Aresulttype\x12\"\x0A\x0Cresultcollid\x18\x04 \x01(\x0DR\x0Cresultcollid\x12:\x0A\x0Ccoerceformat\x18\x05 \x01(\x0E2\x16.pg_query.CoercionFormR\x0Ccoerceformat\x12\x1A\x0A\x08location\x18\x06 \x01(\x05R\x08location\"\xC1\x02\x0A\x0FArrayCoerceExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12 \x0A\x03arg\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x03arg\x12*\x0A\x08elemexpr\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x08elemexpr\x12\x1E\x0A\x0Aresulttype\x18\x04 \x01(\x0DR\x0Aresulttype\x12\"\x0A\x0Cresulttypmod\x18\x05 \x01(\x05R\x0Cresulttypmod\x12\"\x0A\x0Cresultcollid\x18\x06 \x01(\x0DR\x0Cresultcollid\x12:\x0A\x0Ccoerceformat\x18\x07 \x01(\x0E2\x16.pg_query.CoercionFormR\x0Ccoerceformat\x12\x1A\x0A\x08location\x18\x08 \x01(\x05R\x08location\"\xD2\x01\x0A\x12ConvertRowtypeExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12 \x0A\x03arg\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x03arg\x12\x1E\x0A\x0Aresulttype\x18\x03 \x01(\x0DR\x0Aresulttype\x12<\x0A\x0Dconvertformat\x18\x04 \x01(\x0E2\x16.pg_query.CoercionFormR\x0Dconvertformat\x12\x1A\x0A\x08location\x18\x05 \x01(\x05R\x08location\"\x88\x01\x0A\x0BCollateExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12 \x0A\x03arg\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x03arg\x12\x19\x0A\x08coll_oid\x18\x03 \x01(\x0DR\x07collOid\x12\x1A\x0A\x08location\x18\x04 \x01(\x05R\x08location\"\xF8\x01\x0A\x08CaseExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\x1A\x0A\x08casetype\x18\x02 \x01(\x0DR\x08casetype\x12\x1E\x0A\x0Acasecollid\x18\x03 \x01(\x0DR\x0Acasecollid\x12 \x0A\x03arg\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x03arg\x12\"\x0A\x04args\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x04args\x12,\x0A\x09defresult\x18\x06 \x01(\x0B2\x0E.pg_query.NodeR\x09defresult\x12\x1A\x0A\x08location\x18\x07 \x01(\x05R\x08location\"\x94\x01\x0A\x08CaseWhen\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\"\x0A\x04expr\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x04expr\x12&\x0A\x06result\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x06result\x12\x1A\x0A\x08location\x18\x04 \x01(\x05R\x08location\"\x82\x01\x0A\x0CCaseTestExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\x17\x0A\x07type_id\x18\x02 \x01(\x0DR\x06typeId\x12\x19\x0A\x08type_mod\x18\x03 \x01(\x05R\x07typeMod\x12\x1C\x0A\x09collation\x18\x04 \x01(\x0DR\x09collation\"\x83\x02\x0A\x09ArrayExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\"\x0A\x0Carray_typeid\x18\x02 \x01(\x0DR\x0Carray_typeid\x12\"\x0A\x0Carray_collid\x18\x03 \x01(\x0DR\x0Carray_collid\x12&\x0A\x0Eelement_typeid\x18\x04 \x01(\x0DR\x0Eelement_typeid\x12*\x0A\x08elements\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x08elements\x12\x1C\x0A\x09multidims\x18\x06 \x01(\x08R\x09multidims\x12\x1A\x0A\x08location\x18\x07 \x01(\x05R\x08location\"\xEF\x01\x0A\x07RowExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\"\x0A\x04args\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x04args\x12\x1E\x0A\x0Arow_typeid\x18\x03 \x01(\x0DR\x0Arow_typeid\x126\x0A\x0Arow_format\x18\x04 \x01(\x0E2\x16.pg_query.CoercionFormR\x0Arow_format\x12*\x0A\x08colnames\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x08colnames\x12\x1A\x0A\x08location\x18\x06 \x01(\x05R\x08location\"\xBA\x02\x0A\x0ERowCompareExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x120\x0A\x06rctype\x18\x02 \x01(\x0E2\x18.pg_query.RowCompareTypeR\x06rctype\x12\$\x0A\x05opnos\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x05opnos\x12.\x0A\x0Aopfamilies\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x0Aopfamilies\x122\x0A\x0Cinputcollids\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x0Cinputcollids\x12\$\x0A\x05largs\x18\x06 \x03(\x0B2\x0E.pg_query.NodeR\x05largs\x12\$\x0A\x05rargs\x18\x07 \x03(\x0B2\x0E.pg_query.NodeR\x05rargs\"\xBC\x01\x0A\x0CCoalesceExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\"\x0A\x0Ccoalescetype\x18\x02 \x01(\x0DR\x0Ccoalescetype\x12&\x0A\x0Ecoalescecollid\x18\x03 \x01(\x0DR\x0Ecoalescecollid\x12\"\x0A\x04args\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x04args\x12\x1A\x0A\x08location\x18\x05 \x01(\x05R\x08location\"\xF8\x01\x0A\x0AMinMaxExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\x1E\x0A\x0Aminmaxtype\x18\x02 \x01(\x0DR\x0Aminmaxtype\x12\"\x0A\x0Cminmaxcollid\x18\x03 \x01(\x0DR\x0Cminmaxcollid\x12 \x0A\x0Binputcollid\x18\x04 \x01(\x0DR\x0Binputcollid\x12\"\x0A\x02op\x18\x05 \x01(\x0E2\x12.pg_query.MinMaxOpR\x02op\x12\"\x0A\x04args\x18\x06 \x03(\x0B2\x0E.pg_query.NodeR\x04args\x12\x1A\x0A\x08location\x18\x07 \x01(\x05R\x08location\"\xAA\x01\x0A\x10SQLValueFunction\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12,\x0A\x02op\x18\x02 \x01(\x0E2\x1C.pg_query.SQLValueFunctionOpR\x02op\x12\x12\x0A\x04type\x18\x03 \x01(\x0DR\x04type\x12\x16\x0A\x06typmod\x18\x04 \x01(\x05R\x06typmod\x12\x1A\x0A\x08location\x18\x05 \x01(\x05R\x08location\"\xFD\x02\x0A\x07XmlExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12#\x0A\x02op\x18\x02 \x01(\x0E2\x13.pg_query.XmlExprOpR\x02op\x12\x12\x0A\x04name\x18\x03 \x01(\x09R\x04name\x12.\x0A\x0Anamed_args\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x0Anamed_args\x12,\x0A\x09arg_names\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x09arg_names\x12\"\x0A\x04args\x18\x06 \x03(\x0B2\x0E.pg_query.NodeR\x04args\x125\x0A\x09xmloption\x18\x07 \x01(\x0E2\x17.pg_query.XmlOptionTypeR\x09xmloption\x12\x16\x0A\x06indent\x18\x08 \x01(\x08R\x06indent\x12\x12\x0A\x04type\x18\x09 \x01(\x0DR\x04type\x12\x16\x0A\x06typmod\x18\x0A \x01(\x05R\x06typmod\x12\x1A\x0A\x08location\x18\x0B \x01(\x05R\x08location\"\x98\x01\x0A\x0AJsonFormat\x12:\x0A\x0Bformat_type\x18\x01 \x01(\x0E2\x18.pg_query.JsonFormatTypeR\x0Bformat_type\x122\x0A\x08encoding\x18\x02 \x01(\x0E2\x16.pg_query.JsonEncodingR\x08encoding\x12\x1A\x0A\x08location\x18\x03 \x01(\x05R\x08location\"k\x0A\x0DJsonReturning\x12,\x0A\x06format\x18\x01 \x01(\x0B2\x14.pg_query.JsonFormatR\x06format\x12\x14\x0A\x05typid\x18\x02 \x01(\x0DR\x05typid\x12\x16\x0A\x06typmod\x18\x03 \x01(\x05R\x06typmod\"\xA1\x01\x0A\x0DJsonValueExpr\x12*\x0A\x08raw_expr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x08raw_expr\x126\x0A\x0Eformatted_expr\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x0Eformatted_expr\x12,\x0A\x06format\x18\x03 \x01(\x0B2\x14.pg_query.JsonFormatR\x06format\"\xF1\x02\x0A\x13JsonConstructorExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x121\x0A\x04type\x18\x02 \x01(\x0E2\x1D.pg_query.JsonConstructorTypeR\x04type\x12\"\x0A\x04args\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x04args\x12\"\x0A\x04func\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x04func\x12*\x0A\x08coercion\x18\x05 \x01(\x0B2\x0E.pg_query.NodeR\x08coercion\x125\x0A\x09returning\x18\x06 \x01(\x0B2\x17.pg_query.JsonReturningR\x09returning\x12&\x0A\x0Eabsent_on_null\x18\x07 \x01(\x08R\x0Eabsent_on_null\x12\x16\x0A\x06unique\x18\x08 \x01(\x08R\x06unique\x12\x1A\x0A\x08location\x18\x09 \x01(\x05R\x08location\"\xD8\x01\x0A\x0FJsonIsPredicate\x12\"\x0A\x04expr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x04expr\x12,\x0A\x06format\x18\x02 \x01(\x0B2\x14.pg_query.JsonFormatR\x06format\x125\x0A\x09item_type\x18\x03 \x01(\x0E2\x17.pg_query.JsonValueTypeR\x09item_type\x12 \x0A\x0Bunique_keys\x18\x04 \x01(\x08R\x0Bunique_keys\x12\x1A\x0A\x08location\x18\x05 \x01(\x05R\x08location\"\x98\x01\x0A\x0CJsonBehavior\x120\x0A\x05btype\x18\x01 \x01(\x0E2\x1A.pg_query.JsonBehaviorTypeR\x05btype\x12\"\x0A\x04expr\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x04expr\x12\x16\x0A\x06coerce\x18\x03 \x01(\x08R\x06coerce\x12\x1A\x0A\x08location\x18\x04 \x01(\x05R\x08location\"\xFA\x05\x0A\x08JsonExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\$\x0A\x02op\x18\x02 \x01(\x0E2\x14.pg_query.JsonExprOpR\x02op\x12 \x0A\x0Bcolumn_name\x18\x03 \x01(\x09R\x0Bcolumn_name\x126\x0A\x0Eformatted_expr\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x0Eformatted_expr\x12,\x0A\x06format\x18\x05 \x01(\x0B2\x14.pg_query.JsonFormatR\x06format\x12,\x0A\x09path_spec\x18\x06 \x01(\x0B2\x0E.pg_query.NodeR\x09path_spec\x125\x0A\x09returning\x18\x07 \x01(\x0B2\x17.pg_query.JsonReturningR\x09returning\x124\x0A\x0Dpassing_names\x18\x08 \x03(\x0B2\x0E.pg_query.NodeR\x0Dpassing_names\x126\x0A\x0Epassing_values\x18\x09 \x03(\x0B2\x0E.pg_query.NodeR\x0Epassing_values\x122\x0A\x08on_empty\x18\x0A \x01(\x0B2\x16.pg_query.JsonBehaviorR\x08on_empty\x122\x0A\x08on_error\x18\x0B \x01(\x0B2\x16.pg_query.JsonBehaviorR\x08on_error\x12(\x0A\x0Fuse_io_coercion\x18\x0C \x01(\x08R\x0Fuse_io_coercion\x12,\x0A\x11use_json_coercion\x18\x0D \x01(\x08R\x11use_json_coercion\x12/\x0A\x07wrapper\x18\x0E \x01(\x0E2\x15.pg_query.JsonWrapperR\x07wrapper\x12 \x0A\x0Bomit_quotes\x18\x0F \x01(\x08R\x0Bomit_quotes\x12\x1C\x0A\x09collation\x18\x10 \x01(\x0DR\x09collation\x12\x1A\x0A\x08location\x18\x11 \x01(\x05R\x08location\"#\x0A\x0DJsonTablePath\x12\x12\x0A\x04name\x18\x01 \x01(\x09R\x04name\"\xE2\x01\x0A\x11JsonTablePathScan\x12\"\x0A\x04plan\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x04plan\x12+\x0A\x04path\x18\x02 \x01(\x0B2\x17.pg_query.JsonTablePathR\x04path\x12\$\x0A\x0Eerror_on_error\x18\x03 \x01(\x08R\x0CerrorOnError\x12\$\x0A\x05child\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x05child\x12\x17\x0A\x07col_min\x18\x05 \x01(\x05R\x06colMin\x12\x17\x0A\x07col_max\x18\x06 \x01(\x05R\x06colMax\"\x86\x01\x0A\x14JsonTableSiblingJoin\x12\"\x0A\x04plan\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x04plan\x12\$\x0A\x05lplan\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x05lplan\x12\$\x0A\x05rplan\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x05rplan\"\xC2\x01\x0A\x08NullTest\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12 \x0A\x03arg\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x03arg\x12:\x0A\x0Cnulltesttype\x18\x03 \x01(\x0E2\x16.pg_query.NullTestTypeR\x0Cnulltesttype\x12\x1A\x0A\x08argisrow\x18\x04 \x01(\x08R\x08argisrow\x12\x1A\x0A\x08location\x18\x05 \x01(\x05R\x08location\"\xA9\x01\x0A\x0BBooleanTest\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12 \x0A\x03arg\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x03arg\x12:\x0A\x0Cbooltesttype\x18\x03 \x01(\x0E2\x16.pg_query.BoolTestTypeR\x0Cbooltesttype\x12\x1A\x0A\x08location\x18\x04 \x01(\x05R\x08location\"\xBC\x02\x0A\x0BMergeAction\x127\x0A\x0Amatch_kind\x18\x01 \x01(\x0E2\x18.pg_query.MergeMatchKindR\x09matchKind\x124\x0A\x0Ccommand_type\x18\x02 \x01(\x0E2\x11.pg_query.CmdTypeR\x0BcommandType\x124\x0A\x08override\x18\x03 \x01(\x0E2\x18.pg_query.OverridingKindR\x08override\x12\"\x0A\x04qual\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x04qual\x12/\x0A\x0Btarget_list\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x0AtargetList\x123\x0A\x0Dupdate_colnos\x18\x06 \x03(\x0B2\x0E.pg_query.NodeR\x0CupdateColnos\"\x98\x02\x0A\x0ECoerceToDomain\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12 \x0A\x03arg\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x03arg\x12\x1E\x0A\x0Aresulttype\x18\x03 \x01(\x0DR\x0Aresulttype\x12\"\x0A\x0Cresulttypmod\x18\x04 \x01(\x05R\x0Cresulttypmod\x12\"\x0A\x0Cresultcollid\x18\x05 \x01(\x0DR\x0Cresultcollid\x12>\x0A\x0Ecoercionformat\x18\x06 \x01(\x0E2\x16.pg_query.CoercionFormR\x0Ecoercionformat\x12\x1A\x0A\x08location\x18\x07 \x01(\x05R\x08location\"\xA5\x01\x0A\x13CoerceToDomainValue\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\x17\x0A\x07type_id\x18\x02 \x01(\x0DR\x06typeId\x12\x19\x0A\x08type_mod\x18\x03 \x01(\x05R\x07typeMod\x12\x1C\x0A\x09collation\x18\x04 \x01(\x0DR\x09collation\x12\x1A\x0A\x08location\x18\x05 \x01(\x05R\x08location\"\x9E\x01\x0A\x0CSetToDefault\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\x17\x0A\x07type_id\x18\x02 \x01(\x0DR\x06typeId\x12\x19\x0A\x08type_mod\x18\x03 \x01(\x05R\x07typeMod\x12\x1C\x0A\x09collation\x18\x04 \x01(\x0DR\x09collation\x12\x1A\x0A\x08location\x18\x05 \x01(\x05R\x08location\"\x8F\x01\x0A\x0DCurrentOfExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\x16\x0A\x06cvarno\x18\x02 \x01(\x0DR\x06cvarno\x12 \x0A\x0Bcursor_name\x18\x03 \x01(\x09R\x0Bcursor_name\x12\"\x0A\x0Ccursor_param\x18\x04 \x01(\x05R\x0Ccursor_param\"`\x0A\x0DNextValueExpr\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\x14\x0A\x05seqid\x18\x02 \x01(\x0DR\x05seqid\x12\x17\x0A\x07type_id\x18\x03 \x01(\x0DR\x06typeId\"\x9B\x01\x0A\x0DInferenceElem\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\"\x0A\x04expr\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x04expr\x12 \x0A\x0Binfercollid\x18\x03 \x01(\x0DR\x0Binfercollid\x12\"\x0A\x0Cinferopclass\x18\x04 \x01(\x0DR\x0Cinferopclass\"\x87\x02\x0A\x0BTargetEntry\x12 \x0A\x03xpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03xpr\x12\"\x0A\x04expr\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x04expr\x12\x14\x0A\x05resno\x18\x03 \x01(\x05R\x05resno\x12\x18\x0A\x07resname\x18\x04 \x01(\x09R\x07resname\x12(\x0A\x0Fressortgroupref\x18\x05 \x01(\x0DR\x0Fressortgroupref\x12\x1E\x0A\x0Aresorigtbl\x18\x06 \x01(\x0DR\x0Aresorigtbl\x12\x1E\x0A\x0Aresorigcol\x18\x07 \x01(\x05R\x0Aresorigcol\x12\x18\x0A\x07resjunk\x18\x08 \x01(\x08R\x07resjunk\"'\x0A\x0BRangeTblRef\x12\x18\x0A\x07rtindex\x18\x01 \x01(\x05R\x07rtindex\"\xF8\x02\x0A\x08JoinExpr\x12.\x0A\x08jointype\x18\x01 \x01(\x0E2\x12.pg_query.JoinTypeR\x08jointype\x12\x1D\x0A\x0Ais_natural\x18\x02 \x01(\x08R\x09isNatural\x12\"\x0A\x04larg\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x04larg\x12\"\x0A\x04rarg\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x04rarg\x121\x0A\x0Cusing_clause\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x0BusingClause\x12;\x0A\x10join_using_alias\x18\x06 \x01(\x0B2\x0F.pg_query.AliasR\x10join_using_alias\x12\$\x0A\x05quals\x18\x07 \x01(\x0B2\x0E.pg_query.NodeR\x05quals\x12%\x0A\x05alias\x18\x08 \x01(\x0B2\x0F.pg_query.AliasR\x05alias\x12\x18\x0A\x07rtindex\x18\x09 \x01(\x05R\x07rtindex\"\\\x0A\x08FromExpr\x12*\x0A\x08fromlist\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x08fromlist\x12\$\x0A\x05quals\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x05quals\"\x9E\x03\x0A\x0EOnConflictExpr\x122\x0A\x06action\x18\x01 \x01(\x0E2\x1A.pg_query.OnConflictActionR\x06action\x123\x0A\x0Darbiter_elems\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x0CarbiterElems\x123\x0A\x0Darbiter_where\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x0CarbiterWhere\x12\x1E\x0A\x0Aconstraint\x18\x04 \x01(\x0DR\x0Aconstraint\x126\x0A\x0Fon_conflict_set\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x0DonConflictSet\x12:\x0A\x11on_conflict_where\x18\x06 \x01(\x0B2\x0E.pg_query.NodeR\x0FonConflictWhere\x12\$\x0A\x0Eexcl_rel_index\x18\x07 \x01(\x05R\x0CexclRelIndex\x124\x0A\x0Eexcl_rel_tlist\x18\x08 \x03(\x0B2\x0E.pg_query.NodeR\x0CexclRelTlist\"\xC6\x0F\x0A\x05Query\x124\x0A\x0Ccommand_type\x18\x01 \x01(\x0E2\x11.pg_query.CmdTypeR\x0BcommandType\x128\x0A\x0Cquery_source\x18\x02 \x01(\x0E2\x15.pg_query.QuerySourceR\x0BquerySource\x12\x1E\x0A\x0Bcan_set_tag\x18\x03 \x01(\x08R\x09canSetTag\x121\x0A\x0Cutility_stmt\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x0ButilityStmt\x12'\x0A\x0Fresult_relation\x18\x05 \x01(\x05R\x0EresultRelation\x12\x19\x0A\x08has_aggs\x18\x06 \x01(\x08R\x07hasAggs\x12(\x0A\x10has_window_funcs\x18\x07 \x01(\x08R\x0EhasWindowFuncs\x12&\x0A\x0Fhas_target_srfs\x18\x08 \x01(\x08R\x0DhasTargetSRFs\x12\"\x0A\x0Dhas_sub_links\x18\x09 \x01(\x08R\x0BhasSubLinks\x12&\x0A\x0Fhas_distinct_on\x18\x0A \x01(\x08R\x0DhasDistinctOn\x12#\x0A\x0Dhas_recursive\x18\x0B \x01(\x08R\x0ChasRecursive\x12*\x0A\x11has_modifying_cte\x18\x0C \x01(\x08R\x0FhasModifyingCTE\x12\$\x0A\x0Ehas_for_update\x18\x0D \x01(\x08R\x0ChasForUpdate\x12(\x0A\x10has_row_security\x18\x0E \x01(\x08R\x0EhasRowSecurity\x12\x1B\x0A\x09is_return\x18\x0F \x01(\x08R\x08isReturn\x12)\x0A\x08cte_list\x18\x10 \x03(\x0B2\x0E.pg_query.NodeR\x07cteList\x12&\x0A\x06rtable\x18\x11 \x03(\x0B2\x0E.pg_query.NodeR\x06rtable\x122\x0A\x0Crteperminfos\x18\x12 \x03(\x0B2\x0E.pg_query.NodeR\x0Crteperminfos\x12.\x0A\x08jointree\x18\x13 \x01(\x0B2\x12.pg_query.FromExprR\x08jointree\x12:\x0A\x11merge_action_list\x18\x14 \x03(\x0B2\x0E.pg_query.NodeR\x0FmergeActionList\x122\x0A\x15merge_target_relation\x18\x15 \x01(\x05R\x13mergeTargetRelation\x12@\x0A\x14merge_join_condition\x18\x16 \x01(\x0B2\x0E.pg_query.NodeR\x12mergeJoinCondition\x12/\x0A\x0Btarget_list\x18\x17 \x03(\x0B2\x0E.pg_query.NodeR\x0AtargetList\x124\x0A\x08override\x18\x18 \x01(\x0E2\x18.pg_query.OverridingKindR\x08override\x129\x0A\x0Bon_conflict\x18\x19 \x01(\x0B2\x18.pg_query.OnConflictExprR\x0AonConflict\x125\x0A\x0Ereturning_list\x18\x1A \x03(\x0B2\x0E.pg_query.NodeR\x0DreturningList\x121\x0A\x0Cgroup_clause\x18\x1B \x03(\x0B2\x0E.pg_query.NodeR\x0BgroupClause\x12%\x0A\x0Egroup_distinct\x18\x1C \x01(\x08R\x0DgroupDistinct\x123\x0A\x0Dgrouping_sets\x18\x1D \x03(\x0B2\x0E.pg_query.NodeR\x0CgroupingSets\x12/\x0A\x0Bhaving_qual\x18\x1E \x01(\x0B2\x0E.pg_query.NodeR\x0AhavingQual\x123\x0A\x0Dwindow_clause\x18\x1F \x03(\x0B2\x0E.pg_query.NodeR\x0CwindowClause\x127\x0A\x0Fdistinct_clause\x18 \x03(\x0B2\x0E.pg_query.NodeR\x0EdistinctClause\x12/\x0A\x0Bsort_clause\x18! \x03(\x0B2\x0E.pg_query.NodeR\x0AsortClause\x121\x0A\x0Climit_offset\x18\" \x01(\x0B2\x0E.pg_query.NodeR\x0BlimitOffset\x12/\x0A\x0Blimit_count\x18# \x01(\x0B2\x0E.pg_query.NodeR\x0AlimitCount\x128\x0A\x0Climit_option\x18\$ \x01(\x0E2\x15.pg_query.LimitOptionR\x0BlimitOption\x12+\x0A\x09row_marks\x18% \x03(\x0B2\x0E.pg_query.NodeR\x08rowMarks\x125\x0A\x0Eset_operations\x18& \x01(\x0B2\x0E.pg_query.NodeR\x0DsetOperations\x127\x0A\x0Fconstraint_deps\x18' \x03(\x0B2\x0E.pg_query.NodeR\x0EconstraintDeps\x12<\x0A\x12with_check_options\x18( \x03(\x0B2\x0E.pg_query.NodeR\x10withCheckOptions\x12\$\x0A\x0Dstmt_location\x18) \x01(\x05R\x0Dstmt_location\x12\x1A\x0A\x08stmt_len\x18* \x01(\x05R\x08stmt_len\"\x90\x02\x0A\x08TypeName\x12\$\x0A\x05names\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x05names\x12\x19\x0A\x08type_oid\x18\x02 \x01(\x0DR\x07typeOid\x12\x14\x0A\x05setof\x18\x03 \x01(\x08R\x05setof\x12\x1A\x0A\x08pct_type\x18\x04 \x01(\x08R\x08pct_type\x12(\x0A\x07typmods\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x07typmods\x12\x18\x0A\x07typemod\x18\x06 \x01(\x05R\x07typemod\x121\x0A\x0Carray_bounds\x18\x07 \x03(\x0B2\x0E.pg_query.NodeR\x0BarrayBounds\x12\x1A\x0A\x08location\x18\x08 \x01(\x05R\x08location\"O\x0A\x09ColumnRef\x12&\x0A\x06fields\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x06fields\x12\x1A\x0A\x08location\x18\x02 \x01(\x05R\x08location\">\x0A\x08ParamRef\x12\x16\x0A\x06number\x18\x01 \x01(\x05R\x06number\x12\x1A\x0A\x08location\x18\x02 \x01(\x05R\x08location\"\xBF\x01\x0A\x06A_Expr\x12)\x0A\x04kind\x18\x01 \x01(\x0E2\x15.pg_query.A_Expr_KindR\x04kind\x12\"\x0A\x04name\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x04name\x12\$\x0A\x05lexpr\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x05lexpr\x12\$\x0A\x05rexpr\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x05rexpr\x12\x1A\x0A\x08location\x18\x05 \x01(\x05R\x08location\"y\x0A\x08TypeCast\x12 \x0A\x03arg\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03arg\x12/\x0A\x09type_name\x18\x02 \x01(\x0B2\x12.pg_query.TypeNameR\x08typeName\x12\x1A\x0A\x08location\x18\x03 \x01(\x05R\x08location\"y\x0A\x0DCollateClause\x12 \x0A\x03arg\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03arg\x12*\x0A\x08collname\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x08collname\x12\x1A\x0A\x08location\x18\x03 \x01(\x05R\x08location\"v\x0A\x08RoleSpec\x122\x0A\x08roletype\x18\x01 \x01(\x0E2\x16.pg_query.RoleSpecTypeR\x08roletype\x12\x1A\x0A\x08rolename\x18\x02 \x01(\x09R\x08rolename\x12\x1A\x0A\x08location\x18\x03 \x01(\x05R\x08location\"\xC7\x03\x0A\x08FuncCall\x12*\x0A\x08funcname\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x08funcname\x12\"\x0A\x04args\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x04args\x12,\x0A\x09agg_order\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x09agg_order\x12.\x0A\x0Aagg_filter\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x0Aagg_filter\x12'\x0A\x04over\x18\x05 \x01(\x0B2\x13.pg_query.WindowDefR\x04over\x12*\x0A\x10agg_within_group\x18\x06 \x01(\x08R\x10agg_within_group\x12\x1A\x0A\x08agg_star\x18\x07 \x01(\x08R\x08agg_star\x12\"\x0A\x0Cagg_distinct\x18\x08 \x01(\x08R\x0Cagg_distinct\x12\$\x0A\x0Dfunc_variadic\x18\x09 \x01(\x08R\x0Dfunc_variadic\x126\x0A\x0Afuncformat\x18\x0A \x01(\x0E2\x16.pg_query.CoercionFormR\x0Afuncformat\x12\x1A\x0A\x08location\x18\x0B \x01(\x05R\x08location\"\x08\x0A\x06A_Star\"o\x0A\x09A_Indices\x12\x1A\x0A\x08is_slice\x18\x01 \x01(\x08R\x08is_slice\x12\"\x0A\x04lidx\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x04lidx\x12\"\x0A\x04uidx\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x04uidx\"c\x0A\x0DA_Indirection\x12 \x0A\x03arg\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03arg\x120\x0A\x0Bindirection\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x0Bindirection\"U\x0A\x0BA_ArrayExpr\x12*\x0A\x08elements\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x08elements\x12\x1A\x0A\x08location\x18\x02 \x01(\x05R\x08location\"\x8F\x01\x0A\x09ResTarget\x12\x12\x0A\x04name\x18\x01 \x01(\x09R\x04name\x120\x0A\x0Bindirection\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x0Bindirection\x12 \x0A\x03val\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x03val\x12\x1A\x0A\x08location\x18\x04 \x01(\x05R\x08location\"j\x0A\x0EMultiAssignRef\x12&\x0A\x06source\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x06source\x12\x14\x0A\x05colno\x18\x02 \x01(\x05R\x05colno\x12\x1A\x0A\x08ncolumns\x18\x03 \x01(\x05R\x08ncolumns\"\xDF\x01\x0A\x06SortBy\x12\"\x0A\x04node\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x04node\x123\x0A\x0Asortby_dir\x18\x02 \x01(\x0E2\x13.pg_query.SortByDirR\x0Asortby_dir\x129\x0A\x0Csortby_nulls\x18\x03 \x01(\x0E2\x15.pg_query.SortByNullsR\x0Csortby_nulls\x12%\x0A\x06use_op\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x05useOp\x12\x1A\x0A\x08location\x18\x05 \x01(\x05R\x08location\"\xCA\x02\x0A\x09WindowDef\x12\x12\x0A\x04name\x18\x01 \x01(\x09R\x04name\x12\x18\x0A\x07refname\x18\x02 \x01(\x09R\x07refname\x129\x0A\x10partition_clause\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x0FpartitionClause\x121\x0A\x0Corder_clause\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x0BorderClause\x12#\x0A\x0Dframe_options\x18\x05 \x01(\x05R\x0CframeOptions\x121\x0A\x0Cstart_offset\x18\x06 \x01(\x0B2\x0E.pg_query.NodeR\x0BstartOffset\x12-\x0A\x0Aend_offset\x18\x07 \x01(\x0B2\x0E.pg_query.NodeR\x09endOffset\x12\x1A\x0A\x08location\x18\x08 \x01(\x05R\x08location\"}\x0A\x0ERangeSubselect\x12\x18\x0A\x07lateral\x18\x01 \x01(\x08R\x07lateral\x12*\x0A\x08subquery\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x08subquery\x12%\x0A\x05alias\x18\x03 \x01(\x0B2\x0F.pg_query.AliasR\x05alias\"\xF0\x01\x0A\x0DRangeFunction\x12\x18\x0A\x07lateral\x18\x01 \x01(\x08R\x07lateral\x12\x1E\x0A\x0Aordinality\x18\x02 \x01(\x08R\x0Aordinality\x12 \x0A\x0Bis_rowsfrom\x18\x03 \x01(\x08R\x0Bis_rowsfrom\x12,\x0A\x09functions\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x09functions\x12%\x0A\x05alias\x18\x05 \x01(\x0B2\x0F.pg_query.AliasR\x05alias\x12.\x0A\x0Acoldeflist\x18\x06 \x03(\x0B2\x0E.pg_query.NodeR\x0Acoldeflist\"\x9B\x02\x0A\x0ERangeTableFunc\x12\x18\x0A\x07lateral\x18\x01 \x01(\x08R\x07lateral\x12(\x0A\x07docexpr\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x07docexpr\x12(\x0A\x07rowexpr\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x07rowexpr\x12.\x0A\x0Anamespaces\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x0Anamespaces\x12(\x0A\x07columns\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x07columns\x12%\x0A\x05alias\x18\x06 \x01(\x0B2\x0F.pg_query.AliasR\x05alias\x12\x1A\x0A\x08location\x18\x07 \x01(\x05R\x08location\"\x9E\x02\x0A\x11RangeTableFuncCol\x12\x18\x0A\x07colname\x18\x01 \x01(\x09R\x07colname\x12/\x0A\x09type_name\x18\x02 \x01(\x0B2\x12.pg_query.TypeNameR\x08typeName\x12&\x0A\x0Efor_ordinality\x18\x03 \x01(\x08R\x0Efor_ordinality\x12 \x0A\x0Bis_not_null\x18\x04 \x01(\x08R\x0Bis_not_null\x12(\x0A\x07colexpr\x18\x05 \x01(\x0B2\x0E.pg_query.NodeR\x07colexpr\x12.\x0A\x0Acoldefexpr\x18\x06 \x01(\x0B2\x0E.pg_query.NodeR\x0Acoldefexpr\x12\x1A\x0A\x08location\x18\x07 \x01(\x05R\x08location\"\xD6\x01\x0A\x10RangeTableSample\x12*\x0A\x08relation\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x08relation\x12&\x0A\x06method\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x06method\x12\"\x0A\x04args\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x04args\x12.\x0A\x0Arepeatable\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x0Arepeatable\x12\x1A\x0A\x08location\x18\x05 \x01(\x05R\x08location\"\xEC\x05\x0A\x09ColumnDef\x12\x18\x0A\x07colname\x18\x01 \x01(\x09R\x07colname\x12/\x0A\x09type_name\x18\x02 \x01(\x0B2\x12.pg_query.TypeNameR\x08typeName\x12 \x0A\x0Bcompression\x18\x03 \x01(\x09R\x0Bcompression\x12\x1A\x0A\x08inhcount\x18\x04 \x01(\x05R\x08inhcount\x12\x1A\x0A\x08is_local\x18\x05 \x01(\x08R\x08is_local\x12 \x0A\x0Bis_not_null\x18\x06 \x01(\x08R\x0Bis_not_null\x12\"\x0A\x0Cis_from_type\x18\x07 \x01(\x08R\x0Cis_from_type\x12\x18\x0A\x07storage\x18\x08 \x01(\x09R\x07storage\x12\"\x0A\x0Cstorage_name\x18\x09 \x01(\x09R\x0Cstorage_name\x120\x0A\x0Braw_default\x18\x0A \x01(\x0B2\x0E.pg_query.NodeR\x0Braw_default\x126\x0A\x0Ecooked_default\x18\x0B \x01(\x0B2\x0E.pg_query.NodeR\x0Ecooked_default\x12\x1A\x0A\x08identity\x18\x0C \x01(\x09R\x08identity\x12?\x0A\x11identity_sequence\x18\x0D \x01(\x0B2\x12.pg_query.RangeVarR\x10identitySequence\x12\x1C\x0A\x09generated\x18\x0E \x01(\x09R\x09generated\x128\x0A\x0Bcoll_clause\x18\x0F \x01(\x0B2\x17.pg_query.CollateClauseR\x0AcollClause\x12\x19\x0A\x08coll_oid\x18\x10 \x01(\x0DR\x07collOid\x120\x0A\x0Bconstraints\x18\x11 \x03(\x0B2\x0E.pg_query.NodeR\x0Bconstraints\x12.\x0A\x0Afdwoptions\x18\x12 \x03(\x0B2\x0E.pg_query.NodeR\x0Afdwoptions\x12\x1A\x0A\x08location\x18\x13 \x01(\x05R\x08location\"~\x0A\x0FTableLikeClause\x12.\x0A\x08relation\x18\x01 \x01(\x0B2\x12.pg_query.RangeVarR\x08relation\x12\x18\x0A\x07options\x18\x02 \x01(\x0DR\x07options\x12!\x0A\x0Crelation_oid\x18\x03 \x01(\x0DR\x0BrelationOid\"\xE1\x02\x0A\x09IndexElem\x12\x12\x0A\x04name\x18\x01 \x01(\x09R\x04name\x12\"\x0A\x04expr\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x04expr\x12\"\x0A\x0Cindexcolname\x18\x03 \x01(\x09R\x0Cindexcolname\x12,\x0A\x09collation\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x09collation\x12(\x0A\x07opclass\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x07opclass\x120\x0A\x0Bopclassopts\x18\x06 \x03(\x0B2\x0E.pg_query.NodeR\x0Bopclassopts\x12/\x0A\x08ordering\x18\x07 \x01(\x0E2\x13.pg_query.SortByDirR\x08ordering\x12=\x0A\x0Enulls_ordering\x18\x08 \x01(\x0E2\x15.pg_query.SortByNullsR\x0Enulls_ordering\"\xBC\x01\x0A\x07DefElem\x12\"\x0A\x0Cdefnamespace\x18\x01 \x01(\x09R\x0Cdefnamespace\x12\x18\x0A\x07defname\x18\x02 \x01(\x09R\x07defname\x12 \x0A\x03arg\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x03arg\x125\x0A\x09defaction\x18\x04 \x01(\x0E2\x17.pg_query.DefElemActionR\x09defaction\x12\x1A\x0A\x08location\x18\x05 \x01(\x05R\x08location\"\xB5\x01\x0A\x0DLockingClause\x12/\x0A\x0Blocked_rels\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x0AlockedRels\x128\x0A\x08strength\x18\x02 \x01(\x0E2\x1C.pg_query.LockClauseStrengthR\x08strength\x129\x0A\x0Bwait_policy\x18\x03 \x01(\x0E2\x18.pg_query.LockWaitPolicyR\x0AwaitPolicy\"\xCE\x01\x0A\x0CXmlSerialize\x125\x0A\x09xmloption\x18\x01 \x01(\x0E2\x17.pg_query.XmlOptionTypeR\x09xmloption\x12\"\x0A\x04expr\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x04expr\x12/\x0A\x09type_name\x18\x03 \x01(\x0B2\x12.pg_query.TypeNameR\x08typeName\x12\x16\x0A\x06indent\x18\x04 \x01(\x08R\x06indent\x12\x1A\x0A\x08location\x18\x05 \x01(\x05R\x08location\"\xBB\x01\x0A\x0DPartitionElem\x12\x12\x0A\x04name\x18\x01 \x01(\x09R\x04name\x12\"\x0A\x04expr\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x04expr\x12,\x0A\x09collation\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x09collation\x12(\x0A\x07opclass\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x07opclass\x12\x1A\x0A\x08location\x18\x05 \x01(\x05R\x08location\"\x95\x01\x0A\x0DPartitionSpec\x127\x0A\x08strategy\x18\x01 \x01(\x0E2\x1B.pg_query.PartitionStrategyR\x08strategy\x12/\x0A\x0Bpart_params\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x0ApartParams\x12\x1A\x0A\x08location\x18\x03 \x01(\x05R\x08location\"\xB8\x02\x0A\x12PartitionBoundSpec\x12\x1A\x0A\x08strategy\x18\x01 \x01(\x09R\x08strategy\x12\x1E\x0A\x0Ais_default\x18\x02 \x01(\x08R\x0Ais_default\x12\x18\x0A\x07modulus\x18\x03 \x01(\x05R\x07modulus\x12\x1C\x0A\x09remainder\x18\x04 \x01(\x05R\x09remainder\x12.\x0A\x0Alistdatums\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x0Alistdatums\x120\x0A\x0Blowerdatums\x18\x06 \x03(\x0B2\x0E.pg_query.NodeR\x0Blowerdatums\x120\x0A\x0Bupperdatums\x18\x07 \x03(\x0B2\x0E.pg_query.NodeR\x0Bupperdatums\x12\x1A\x0A\x08location\x18\x08 \x01(\x05R\x08location\"\x8E\x01\x0A\x13PartitionRangeDatum\x125\x0A\x04kind\x18\x01 \x01(\x0E2!.pg_query.PartitionRangeDatumKindR\x04kind\x12\$\x0A\x05value\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x05value\x12\x1A\x0A\x08location\x18\x03 \x01(\x05R\x08location\"\x15\x0A\x13SinglePartitionSpec\"\x8A\x01\x0A\x0CPartitionCmd\x12&\x0A\x04name\x18\x01 \x01(\x0B2\x12.pg_query.RangeVarR\x04name\x122\x0A\x05bound\x18\x02 \x01(\x0B2\x1C.pg_query.PartitionBoundSpecR\x05bound\x12\x1E\x0A\x0Aconcurrent\x18\x03 \x01(\x08R\x0Aconcurrent\"\xB9\x0A\x0A\x0DRangeTblEntry\x12%\x0A\x05alias\x18\x01 \x01(\x0B2\x0F.pg_query.AliasR\x05alias\x12#\x0A\x04eref\x18\x02 \x01(\x0B2\x0F.pg_query.AliasR\x04eref\x12+\x0A\x07rtekind\x18\x03 \x01(\x0E2\x11.pg_query.RTEKindR\x07rtekind\x12\x14\x0A\x05relid\x18\x04 \x01(\x0DR\x05relid\x12\x10\x0A\x03inh\x18\x05 \x01(\x08R\x03inh\x12\x18\x0A\x07relkind\x18\x06 \x01(\x09R\x07relkind\x12 \x0A\x0Brellockmode\x18\x07 \x01(\x05R\x0Brellockmode\x12\$\x0A\x0Dperminfoindex\x18\x08 \x01(\x0DR\x0Dperminfoindex\x12=\x0A\x0Btablesample\x18\x09 \x01(\x0B2\x1B.pg_query.TableSampleClauseR\x0Btablesample\x12+\x0A\x08subquery\x18\x0A \x01(\x0B2\x0F.pg_query.QueryR\x08subquery\x12*\x0A\x10security_barrier\x18\x0B \x01(\x08R\x10security_barrier\x12.\x0A\x08jointype\x18\x0C \x01(\x0E2\x12.pg_query.JoinTypeR\x08jointype\x12&\x0A\x0Ejoinmergedcols\x18\x0D \x01(\x05R\x0Ejoinmergedcols\x124\x0A\x0Djoinaliasvars\x18\x0E \x03(\x0B2\x0E.pg_query.NodeR\x0Djoinaliasvars\x122\x0A\x0Cjoinleftcols\x18\x0F \x03(\x0B2\x0E.pg_query.NodeR\x0Cjoinleftcols\x124\x0A\x0Djoinrightcols\x18\x10 \x03(\x0B2\x0E.pg_query.NodeR\x0Djoinrightcols\x12;\x0A\x10join_using_alias\x18\x11 \x01(\x0B2\x0F.pg_query.AliasR\x10join_using_alias\x12,\x0A\x09functions\x18\x12 \x03(\x0B2\x0E.pg_query.NodeR\x09functions\x12&\x0A\x0Efuncordinality\x18\x13 \x01(\x08R\x0Efuncordinality\x121\x0A\x09tablefunc\x18\x14 \x01(\x0B2\x13.pg_query.TableFuncR\x09tablefunc\x122\x0A\x0Cvalues_lists\x18\x15 \x03(\x0B2\x0E.pg_query.NodeR\x0Cvalues_lists\x12\x18\x0A\x07ctename\x18\x16 \x01(\x09R\x07ctename\x12 \x0A\x0Bctelevelsup\x18\x17 \x01(\x0DR\x0Bctelevelsup\x12&\x0A\x0Eself_reference\x18\x18 \x01(\x08R\x0Eself_reference\x12*\x0A\x08coltypes\x18\x19 \x03(\x0B2\x0E.pg_query.NodeR\x08coltypes\x12.\x0A\x0Acoltypmods\x18\x1A \x03(\x0B2\x0E.pg_query.NodeR\x0Acoltypmods\x124\x0A\x0Dcolcollations\x18\x1B \x03(\x0B2\x0E.pg_query.NodeR\x0Dcolcollations\x12\x18\x0A\x07enrname\x18\x1C \x01(\x09R\x07enrname\x12\x1C\x0A\x09enrtuples\x18\x1D \x01(\x01R\x09enrtuples\x12\x18\x0A\x07lateral\x18\x1E \x01(\x08R\x07lateral\x12\x1C\x0A\x0Ain_from_cl\x18\x1F \x01(\x08R\x08inFromCl\x125\x0A\x0Esecurity_quals\x18 \x03(\x0B2\x0E.pg_query.NodeR\x0DsecurityQuals\"\xF3\x01\x0A\x11RTEPermissionInfo\x12\x14\x0A\x05relid\x18\x01 \x01(\x0DR\x05relid\x12\x10\x0A\x03inh\x18\x02 \x01(\x08R\x03inh\x12%\x0A\x0Erequired_perms\x18\x03 \x01(\x04R\x0DrequiredPerms\x12\"\x0A\x0Dcheck_as_user\x18\x04 \x01(\x0DR\x0BcheckAsUser\x12#\x0A\x0Dselected_cols\x18\x05 \x03(\x04R\x0CselectedCols\x12#\x0A\x0Dinserted_cols\x18\x06 \x03(\x04R\x0CinsertedCols\x12!\x0A\x0Cupdated_cols\x18\x07 \x03(\x04R\x0BupdatedCols\"\xE0\x02\x0A\x10RangeTblFunction\x12*\x0A\x08funcexpr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x08funcexpr\x12\"\x0A\x0Cfunccolcount\x18\x02 \x01(\x05R\x0Cfunccolcount\x122\x0A\x0Cfunccolnames\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x0Cfunccolnames\x122\x0A\x0Cfunccoltypes\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x0Cfunccoltypes\x126\x0A\x0Efunccoltypmods\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x0Efunccoltypmods\x12<\x0A\x11funccolcollations\x18\x06 \x03(\x0B2\x0E.pg_query.NodeR\x11funccolcollations\x12\x1E\x0A\x0Afuncparams\x18\x07 \x03(\x04R\x0Afuncparams\"\x87\x01\x0A\x11TableSampleClause\x12\x1E\x0A\x0Atsmhandler\x18\x01 \x01(\x0DR\x0Atsmhandler\x12\"\x0A\x04args\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x04args\x12.\x0A\x0Arepeatable\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x0Arepeatable\"\xAC\x01\x0A\x0FWithCheckOption\x12%\x0A\x04kind\x18\x01 \x01(\x0E2\x11.pg_query.WCOKindR\x04kind\x12\x18\x0A\x07relname\x18\x02 \x01(\x09R\x07relname\x12\x18\x0A\x07polname\x18\x03 \x01(\x09R\x07polname\x12\"\x0A\x04qual\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x04qual\x12\x1A\x0A\x08cascaded\x18\x05 \x01(\x08R\x08cascaded\"\xA8\x01\x0A\x0FSortGroupClause\x12+\x0A\x12tle_sort_group_ref\x18\x01 \x01(\x0DR\x0FtleSortGroupRef\x12\x12\x0A\x04eqop\x18\x02 \x01(\x0DR\x04eqop\x12\x16\x0A\x06sortop\x18\x03 \x01(\x0DR\x06sortop\x12 \x0A\x0Bnulls_first\x18\x04 \x01(\x08R\x0Bnulls_first\x12\x1A\x0A\x08hashable\x18\x05 \x01(\x08R\x08hashable\"\x82\x01\x0A\x0BGroupingSet\x12-\x0A\x04kind\x18\x01 \x01(\x0E2\x19.pg_query.GroupingSetKindR\x04kind\x12(\x0A\x07content\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x07content\x12\x1A\x0A\x08location\x18\x03 \x01(\x05R\x08location\"\xBD\x04\x0A\x0CWindowClause\x12\x12\x0A\x04name\x18\x01 \x01(\x09R\x04name\x12\x18\x0A\x07refname\x18\x02 \x01(\x09R\x07refname\x129\x0A\x10partition_clause\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x0FpartitionClause\x121\x0A\x0Corder_clause\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x0BorderClause\x12#\x0A\x0Dframe_options\x18\x05 \x01(\x05R\x0CframeOptions\x121\x0A\x0Cstart_offset\x18\x06 \x01(\x0B2\x0E.pg_query.NodeR\x0BstartOffset\x12-\x0A\x0Aend_offset\x18\x07 \x01(\x0B2\x0E.pg_query.NodeR\x09endOffset\x12-\x0A\x13start_in_range_func\x18\x08 \x01(\x0DR\x10startInRangeFunc\x12)\x0A\x11end_in_range_func\x18\x09 \x01(\x0DR\x0EendInRangeFunc\x12\"\x0A\x0Din_range_coll\x18\x0A \x01(\x0DR\x0BinRangeColl\x12 \x0A\x0Cin_range_asc\x18\x0B \x01(\x08R\x0AinRangeAsc\x12/\x0A\x14in_range_nulls_first\x18\x0C \x01(\x08R\x11inRangeNullsFirst\x12\x16\x0A\x06winref\x18\x0D \x01(\x0DR\x06winref\x12!\x0A\x0Ccopied_order\x18\x0E \x01(\x08R\x0BcopiedOrder\"\xB7\x01\x0A\x0DRowMarkClause\x12\x10\x0A\x03rti\x18\x01 \x01(\x0DR\x03rti\x128\x0A\x08strength\x18\x02 \x01(\x0E2\x1C.pg_query.LockClauseStrengthR\x08strength\x129\x0A\x0Bwait_policy\x18\x03 \x01(\x0E2\x18.pg_query.LockWaitPolicyR\x0AwaitPolicy\x12\x1F\x0A\x0Bpushed_down\x18\x04 \x01(\x08R\x0ApushedDown\"j\x0A\x0AWithClause\x12\"\x0A\x04ctes\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x04ctes\x12\x1C\x0A\x09recursive\x18\x02 \x01(\x08R\x09recursive\x12\x1A\x0A\x08location\x18\x03 \x01(\x05R\x08location\"\xA7\x01\x0A\x0BInferClause\x12/\x0A\x0Bindex_elems\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x0AindexElems\x121\x0A\x0Cwhere_clause\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x0BwhereClause\x12\x18\x0A\x07conname\x18\x03 \x01(\x09R\x07conname\x12\x1A\x0A\x08location\x18\x04 \x01(\x05R\x08location\"\xF3\x01\x0A\x10OnConflictClause\x122\x0A\x06action\x18\x01 \x01(\x0E2\x1A.pg_query.OnConflictActionR\x06action\x12+\x0A\x05infer\x18\x02 \x01(\x0B2\x15.pg_query.InferClauseR\x05infer\x12/\x0A\x0Btarget_list\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x0AtargetList\x121\x0A\x0Cwhere_clause\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x0BwhereClause\x12\x1A\x0A\x08location\x18\x05 \x01(\x05R\x08location\"\xC9\x01\x0A\x0FCTESearchClause\x128\x0A\x0Fsearch_col_list\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x0Fsearch_col_list\x122\x0A\x14search_breadth_first\x18\x02 \x01(\x08R\x14search_breadth_first\x12,\x0A\x11search_seq_column\x18\x03 \x01(\x09R\x11search_seq_column\x12\x1A\x0A\x08location\x18\x04 \x01(\x05R\x08location\"\xF2\x03\x0A\x0ECTECycleClause\x126\x0A\x0Ecycle_col_list\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x0Ecycle_col_list\x12,\x0A\x11cycle_mark_column\x18\x02 \x01(\x09R\x11cycle_mark_column\x12:\x0A\x10cycle_mark_value\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x10cycle_mark_value\x12>\x0A\x12cycle_mark_default\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x12cycle_mark_default\x12,\x0A\x11cycle_path_column\x18\x05 \x01(\x09R\x11cycle_path_column\x12\x1A\x0A\x08location\x18\x06 \x01(\x05R\x08location\x12(\x0A\x0Fcycle_mark_type\x18\x07 \x01(\x0DR\x0Fcycle_mark_type\x12,\x0A\x11cycle_mark_typmod\x18\x08 \x01(\x05R\x11cycle_mark_typmod\x122\x0A\x14cycle_mark_collation\x18\x09 \x01(\x0DR\x14cycle_mark_collation\x12(\x0A\x0Fcycle_mark_neop\x18\x0A \x01(\x0DR\x0Fcycle_mark_neop\"\x88\x05\x0A\x0FCommonTableExpr\x12\x18\x0A\x07ctename\x18\x01 \x01(\x09R\x07ctename\x124\x0A\x0Daliascolnames\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x0Daliascolnames\x12B\x0A\x0Fctematerialized\x18\x03 \x01(\x0E2\x18.pg_query.CTEMaterializeR\x0Fctematerialized\x12*\x0A\x08ctequery\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x08ctequery\x12?\x0A\x0Dsearch_clause\x18\x05 \x01(\x0B2\x19.pg_query.CTESearchClauseR\x0Dsearch_clause\x12<\x0A\x0Ccycle_clause\x18\x06 \x01(\x0B2\x18.pg_query.CTECycleClauseR\x0Ccycle_clause\x12\x1A\x0A\x08location\x18\x07 \x01(\x05R\x08location\x12\"\x0A\x0Ccterecursive\x18\x08 \x01(\x08R\x0Ccterecursive\x12 \x0A\x0Bcterefcount\x18\x09 \x01(\x05R\x0Bcterefcount\x120\x0A\x0Bctecolnames\x18\x0A \x03(\x0B2\x0E.pg_query.NodeR\x0Bctecolnames\x120\x0A\x0Bctecoltypes\x18\x0B \x03(\x0B2\x0E.pg_query.NodeR\x0Bctecoltypes\x124\x0A\x0Dctecoltypmods\x18\x0C \x03(\x0B2\x0E.pg_query.NodeR\x0Dctecoltypmods\x12:\x0A\x10ctecolcollations\x18\x0D \x03(\x0B2\x0E.pg_query.NodeR\x10ctecolcollations\"\xBD\x02\x0A\x0FMergeWhenClause\x127\x0A\x0Amatch_kind\x18\x01 \x01(\x0E2\x18.pg_query.MergeMatchKindR\x09matchKind\x124\x0A\x0Ccommand_type\x18\x02 \x01(\x0E2\x11.pg_query.CmdTypeR\x0BcommandType\x124\x0A\x08override\x18\x03 \x01(\x0E2\x18.pg_query.OverridingKindR\x08override\x12,\x0A\x09condition\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x09condition\x12/\x0A\x0Btarget_list\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x0AtargetList\x12&\x0A\x06values\x18\x06 \x03(\x0B2\x0E.pg_query.NodeR\x06values\"Y\x0A\x11TriggerTransition\x12\x12\x0A\x04name\x18\x01 \x01(\x09R\x04name\x12\x15\x0A\x06is_new\x18\x02 \x01(\x08R\x05isNew\x12\x19\x0A\x08is_table\x18\x03 \x01(\x08R\x07isTable\"t\x0A\x0AJsonOutput\x12/\x0A\x09type_name\x18\x01 \x01(\x0B2\x12.pg_query.TypeNameR\x08typeName\x125\x0A\x09returning\x18\x02 \x01(\x0B2\x17.pg_query.JsonReturningR\x09returning\"M\x0A\x0CJsonArgument\x12)\x0A\x03val\x18\x01 \x01(\x0B2\x17.pg_query.JsonValueExprR\x03val\x12\x12\x0A\x04name\x18\x02 \x01(\x09R\x04name\"\xFA\x03\x0A\x0CJsonFuncExpr\x12\$\x0A\x02op\x18\x01 \x01(\x0E2\x14.pg_query.JsonExprOpR\x02op\x12 \x0A\x0Bcolumn_name\x18\x02 \x01(\x09R\x0Bcolumn_name\x12;\x0A\x0Ccontext_item\x18\x03 \x01(\x0B2\x17.pg_query.JsonValueExprR\x0Ccontext_item\x12*\x0A\x08pathspec\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x08pathspec\x12(\x0A\x07passing\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x07passing\x12,\x0A\x06output\x18\x06 \x01(\x0B2\x14.pg_query.JsonOutputR\x06output\x122\x0A\x08on_empty\x18\x07 \x01(\x0B2\x16.pg_query.JsonBehaviorR\x08on_empty\x122\x0A\x08on_error\x18\x08 \x01(\x0B2\x16.pg_query.JsonBehaviorR\x08on_error\x12/\x0A\x07wrapper\x18\x09 \x01(\x0E2\x15.pg_query.JsonWrapperR\x07wrapper\x12,\x0A\x06quotes\x18\x0A \x01(\x0E2\x14.pg_query.JsonQuotesR\x06quotes\x12\x1A\x0A\x08location\x18\x0B \x01(\x05R\x08location\"\x91\x01\x0A\x11JsonTablePathSpec\x12&\x0A\x06string\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x06string\x12\x12\x0A\x04name\x18\x02 \x01(\x09R\x04name\x12\$\x0A\x0Dname_location\x18\x03 \x01(\x05R\x0Dname_location\x12\x1A\x0A\x08location\x18\x04 \x01(\x05R\x08location\"\xE6\x02\x0A\x09JsonTable\x12;\x0A\x0Ccontext_item\x18\x01 \x01(\x0B2\x17.pg_query.JsonValueExprR\x0Ccontext_item\x127\x0A\x08pathspec\x18\x02 \x01(\x0B2\x1B.pg_query.JsonTablePathSpecR\x08pathspec\x12(\x0A\x07passing\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x07passing\x12(\x0A\x07columns\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x07columns\x122\x0A\x08on_error\x18\x05 \x01(\x0B2\x16.pg_query.JsonBehaviorR\x08on_error\x12%\x0A\x05alias\x18\x06 \x01(\x0B2\x0F.pg_query.AliasR\x05alias\x12\x18\x0A\x07lateral\x18\x07 \x01(\x08R\x07lateral\x12\x1A\x0A\x08location\x18\x08 \x01(\x05R\x08location\"\x83\x04\x0A\x0FJsonTableColumn\x127\x0A\x07coltype\x18\x01 \x01(\x0E2\x1D.pg_query.JsonTableColumnTypeR\x07coltype\x12\x12\x0A\x04name\x18\x02 \x01(\x09R\x04name\x12/\x0A\x09type_name\x18\x03 \x01(\x0B2\x12.pg_query.TypeNameR\x08typeName\x127\x0A\x08pathspec\x18\x04 \x01(\x0B2\x1B.pg_query.JsonTablePathSpecR\x08pathspec\x12,\x0A\x06format\x18\x05 \x01(\x0B2\x14.pg_query.JsonFormatR\x06format\x12/\x0A\x07wrapper\x18\x06 \x01(\x0E2\x15.pg_query.JsonWrapperR\x07wrapper\x12,\x0A\x06quotes\x18\x07 \x01(\x0E2\x14.pg_query.JsonQuotesR\x06quotes\x12(\x0A\x07columns\x18\x08 \x03(\x0B2\x0E.pg_query.NodeR\x07columns\x122\x0A\x08on_empty\x18\x09 \x01(\x0B2\x16.pg_query.JsonBehaviorR\x08on_empty\x122\x0A\x08on_error\x18\x0A \x01(\x0B2\x16.pg_query.JsonBehaviorR\x08on_error\x12\x1A\x0A\x08location\x18\x0B \x01(\x05R\x08location\"_\x0A\x0CJsonKeyValue\x12 \x0A\x03key\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x03key\x12-\x0A\x05value\x18\x02 \x01(\x0B2\x17.pg_query.JsonValueExprR\x05value\"\xA8\x01\x0A\x0DJsonParseExpr\x12+\x0A\x04expr\x18\x01 \x01(\x0B2\x17.pg_query.JsonValueExprR\x04expr\x12,\x0A\x06output\x18\x02 \x01(\x0B2\x14.pg_query.JsonOutputR\x06output\x12 \x0A\x0Bunique_keys\x18\x03 \x01(\x08R\x0Bunique_keys\x12\x1A\x0A\x08location\x18\x04 \x01(\x05R\x08location\"~\x0A\x0EJsonScalarExpr\x12\"\x0A\x04expr\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x04expr\x12,\x0A\x06output\x18\x02 \x01(\x0B2\x14.pg_query.JsonOutputR\x06output\x12\x1A\x0A\x08location\x18\x03 \x01(\x05R\x08location\"\x8A\x01\x0A\x11JsonSerializeExpr\x12+\x0A\x04expr\x18\x01 \x01(\x0B2\x17.pg_query.JsonValueExprR\x04expr\x12,\x0A\x06output\x18\x02 \x01(\x0B2\x14.pg_query.JsonOutputR\x06output\x12\x1A\x0A\x08location\x18\x03 \x01(\x05R\x08location\"\xC7\x01\x0A\x15JsonObjectConstructor\x12\$\x0A\x05exprs\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x05exprs\x12,\x0A\x06output\x18\x02 \x01(\x0B2\x14.pg_query.JsonOutputR\x06output\x12&\x0A\x0Eabsent_on_null\x18\x03 \x01(\x08R\x0Eabsent_on_null\x12\x16\x0A\x06unique\x18\x04 \x01(\x08R\x06unique\x12\x1A\x0A\x08location\x18\x05 \x01(\x05R\x08location\"\xAE\x01\x0A\x14JsonArrayConstructor\x12\$\x0A\x05exprs\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x05exprs\x12,\x0A\x06output\x18\x02 \x01(\x0B2\x14.pg_query.JsonOutputR\x06output\x12&\x0A\x0Eabsent_on_null\x18\x03 \x01(\x08R\x0Eabsent_on_null\x12\x1A\x0A\x08location\x18\x04 \x01(\x05R\x08location\"\xE1\x01\x0A\x19JsonArrayQueryConstructor\x12\$\x0A\x05query\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x05query\x12,\x0A\x06output\x18\x02 \x01(\x0B2\x14.pg_query.JsonOutputR\x06output\x12,\x0A\x06format\x18\x03 \x01(\x0B2\x14.pg_query.JsonFormatR\x06format\x12&\x0A\x0Eabsent_on_null\x18\x04 \x01(\x08R\x0Eabsent_on_null\x12\x1A\x0A\x08location\x18\x05 \x01(\x05R\x08location\"\xE5\x01\x0A\x12JsonAggConstructor\x12,\x0A\x06output\x18\x01 \x01(\x0B2\x14.pg_query.JsonOutputR\x06output\x12.\x0A\x0Aagg_filter\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x0Aagg_filter\x12,\x0A\x09agg_order\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x09agg_order\x12'\x0A\x04over\x18\x04 \x01(\x0B2\x13.pg_query.WindowDefR\x04over\x12\x1A\x0A\x08location\x18\x05 \x01(\x05R\x08location\"\xB9\x01\x0A\x0DJsonObjectAgg\x12>\x0A\x0Bconstructor\x18\x01 \x01(\x0B2\x1C.pg_query.JsonAggConstructorR\x0Bconstructor\x12(\x0A\x03arg\x18\x02 \x01(\x0B2\x16.pg_query.JsonKeyValueR\x03arg\x12&\x0A\x0Eabsent_on_null\x18\x03 \x01(\x08R\x0Eabsent_on_null\x12\x16\x0A\x06unique\x18\x04 \x01(\x08R\x06unique\"\xA1\x01\x0A\x0CJsonArrayAgg\x12>\x0A\x0Bconstructor\x18\x01 \x01(\x0B2\x1C.pg_query.JsonAggConstructorR\x0Bconstructor\x12)\x0A\x03arg\x18\x02 \x01(\x0B2\x17.pg_query.JsonValueExprR\x03arg\x12&\x0A\x0Eabsent_on_null\x18\x03 \x01(\x08R\x0Eabsent_on_null\"o\x0A\x07RawStmt\x12\"\x0A\x04stmt\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x04stmt\x12\$\x0A\x0Dstmt_location\x18\x02 \x01(\x05R\x0Dstmt_location\x12\x1A\x0A\x08stmt_len\x18\x03 \x01(\x05R\x08stmt_len\"\xFF\x02\x0A\x0AInsertStmt\x12.\x0A\x08relation\x18\x01 \x01(\x0B2\x12.pg_query.RangeVarR\x08relation\x12\"\x0A\x04cols\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x04cols\x12/\x0A\x0Bselect_stmt\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x0AselectStmt\x12H\x0A\x12on_conflict_clause\x18\x04 \x01(\x0B2\x1A.pg_query.OnConflictClauseR\x10onConflictClause\x125\x0A\x0Ereturning_list\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x0DreturningList\x125\x0A\x0Bwith_clause\x18\x06 \x01(\x0B2\x14.pg_query.WithClauseR\x0AwithClause\x124\x0A\x08override\x18\x07 \x01(\x0E2\x18.pg_query.OverridingKindR\x08override\"\x90\x02\x0A\x0ADeleteStmt\x12.\x0A\x08relation\x18\x01 \x01(\x0B2\x12.pg_query.RangeVarR\x08relation\x121\x0A\x0Cusing_clause\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x0BusingClause\x121\x0A\x0Cwhere_clause\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x0BwhereClause\x125\x0A\x0Ereturning_list\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x0DreturningList\x125\x0A\x0Bwith_clause\x18\x05 \x01(\x0B2\x14.pg_query.WithClauseR\x0AwithClause\"\xBF\x02\x0A\x0AUpdateStmt\x12.\x0A\x08relation\x18\x01 \x01(\x0B2\x12.pg_query.RangeVarR\x08relation\x12/\x0A\x0Btarget_list\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x0AtargetList\x121\x0A\x0Cwhere_clause\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x0BwhereClause\x12/\x0A\x0Bfrom_clause\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x0AfromClause\x125\x0A\x0Ereturning_list\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x0DreturningList\x125\x0A\x0Bwith_clause\x18\x06 \x01(\x0B2\x14.pg_query.WithClauseR\x0AwithClause\"\xD7\x02\x0A\x09MergeStmt\x12.\x0A\x08relation\x18\x01 \x01(\x0B2\x12.pg_query.RangeVarR\x08relation\x127\x0A\x0Fsource_relation\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x0EsourceRelation\x125\x0A\x0Ejoin_condition\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x0DjoinCondition\x12<\x0A\x12merge_when_clauses\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x10mergeWhenClauses\x125\x0A\x0Ereturning_list\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x0DreturningList\x125\x0A\x0Bwith_clause\x18\x06 \x01(\x0B2\x14.pg_query.WithClauseR\x0AwithClause\"\xD3\x07\x0A\x0ASelectStmt\x127\x0A\x0Fdistinct_clause\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x0EdistinctClause\x125\x0A\x0Binto_clause\x18\x02 \x01(\x0B2\x14.pg_query.IntoClauseR\x0AintoClause\x12/\x0A\x0Btarget_list\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x0AtargetList\x12/\x0A\x0Bfrom_clause\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x0AfromClause\x121\x0A\x0Cwhere_clause\x18\x05 \x01(\x0B2\x0E.pg_query.NodeR\x0BwhereClause\x121\x0A\x0Cgroup_clause\x18\x06 \x03(\x0B2\x0E.pg_query.NodeR\x0BgroupClause\x12%\x0A\x0Egroup_distinct\x18\x07 \x01(\x08R\x0DgroupDistinct\x123\x0A\x0Dhaving_clause\x18\x08 \x01(\x0B2\x0E.pg_query.NodeR\x0ChavingClause\x123\x0A\x0Dwindow_clause\x18\x09 \x03(\x0B2\x0E.pg_query.NodeR\x0CwindowClause\x121\x0A\x0Cvalues_lists\x18\x0A \x03(\x0B2\x0E.pg_query.NodeR\x0BvaluesLists\x12/\x0A\x0Bsort_clause\x18\x0B \x03(\x0B2\x0E.pg_query.NodeR\x0AsortClause\x121\x0A\x0Climit_offset\x18\x0C \x01(\x0B2\x0E.pg_query.NodeR\x0BlimitOffset\x12/\x0A\x0Blimit_count\x18\x0D \x01(\x0B2\x0E.pg_query.NodeR\x0AlimitCount\x128\x0A\x0Climit_option\x18\x0E \x01(\x0E2\x15.pg_query.LimitOptionR\x0BlimitOption\x125\x0A\x0Elocking_clause\x18\x0F \x03(\x0B2\x0E.pg_query.NodeR\x0DlockingClause\x125\x0A\x0Bwith_clause\x18\x10 \x01(\x0B2\x14.pg_query.WithClauseR\x0AwithClause\x12&\x0A\x02op\x18\x11 \x01(\x0E2\x16.pg_query.SetOperationR\x02op\x12\x10\x0A\x03all\x18\x12 \x01(\x08R\x03all\x12(\x0A\x04larg\x18\x13 \x01(\x0B2\x14.pg_query.SelectStmtR\x04larg\x12(\x0A\x04rarg\x18\x14 \x01(\x0B2\x14.pg_query.SelectStmtR\x04rarg\"\xDE\x02\x0A\x10SetOperationStmt\x12&\x0A\x02op\x18\x01 \x01(\x0E2\x16.pg_query.SetOperationR\x02op\x12\x10\x0A\x03all\x18\x02 \x01(\x08R\x03all\x12\"\x0A\x04larg\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x04larg\x12\"\x0A\x04rarg\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x04rarg\x12+\x0A\x09col_types\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x08colTypes\x12/\x0A\x0Bcol_typmods\x18\x06 \x03(\x0B2\x0E.pg_query.NodeR\x0AcolTypmods\x125\x0A\x0Ecol_collations\x18\x07 \x03(\x0B2\x0E.pg_query.NodeR\x0DcolCollations\x123\x0A\x0Dgroup_clauses\x18\x08 \x03(\x0B2\x0E.pg_query.NodeR\x0CgroupClauses\":\x0A\x0AReturnStmt\x12,\x0A\x09returnval\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x09returnval\"\xB0\x01\x0A\x0CPLAssignStmt\x12\x12\x0A\x04name\x18\x01 \x01(\x09R\x04name\x120\x0A\x0Bindirection\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x0Bindirection\x12\x16\x0A\x06nnames\x18\x03 \x01(\x05R\x06nnames\x12&\x0A\x03val\x18\x04 \x01(\x0B2\x14.pg_query.SelectStmtR\x03val\x12\x1A\x0A\x08location\x18\x05 \x01(\x05R\x08location\"\xB9\x01\x0A\x10CreateSchemaStmt\x12\x1E\x0A\x0Aschemaname\x18\x01 \x01(\x09R\x0Aschemaname\x12.\x0A\x08authrole\x18\x02 \x01(\x0B2\x12.pg_query.RoleSpecR\x08authrole\x12/\x0A\x0Bschema_elts\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x0AschemaElts\x12\$\x0A\x0Dif_not_exists\x18\x04 \x01(\x08R\x0Dif_not_exists\"\xB4\x01\x0A\x0EAlterTableStmt\x12.\x0A\x08relation\x18\x01 \x01(\x0B2\x12.pg_query.RangeVarR\x08relation\x12\"\x0A\x04cmds\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x04cmds\x12.\x0A\x07objtype\x18\x03 \x01(\x0E2\x14.pg_query.ObjectTypeR\x07objtype\x12\x1E\x0A\x0Amissing_ok\x18\x04 \x01(\x08R\x0Amissing_ok\"O\x0A\x13ReplicaIdentityStmt\x12\$\x0A\x0Didentity_type\x18\x01 \x01(\x09R\x0Didentity_type\x12\x12\x0A\x04name\x18\x02 \x01(\x09R\x04name\"\xA9\x02\x0A\x0DAlterTableCmd\x122\x0A\x07subtype\x18\x01 \x01(\x0E2\x18.pg_query.AlterTableTypeR\x07subtype\x12\x12\x0A\x04name\x18\x02 \x01(\x09R\x04name\x12\x10\x0A\x03num\x18\x03 \x01(\x05R\x03num\x12.\x0A\x08newowner\x18\x04 \x01(\x0B2\x12.pg_query.RoleSpecR\x08newowner\x12 \x0A\x03def\x18\x05 \x01(\x0B2\x0E.pg_query.NodeR\x03def\x122\x0A\x08behavior\x18\x06 \x01(\x0E2\x16.pg_query.DropBehaviorR\x08behavior\x12\x1E\x0A\x0Amissing_ok\x18\x07 \x01(\x08R\x0Amissing_ok\x12\x18\x0A\x07recurse\x18\x08 \x01(\x08R\x07recurse\"@\x0A\x12AlterCollationStmt\x12*\x0A\x08collname\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x08collname\"\xE2\x01\x0A\x0FAlterDomainStmt\x12\x18\x0A\x07subtype\x18\x01 \x01(\x09R\x07subtype\x12+\x0A\x09type_name\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x08typeName\x12\x12\x0A\x04name\x18\x03 \x01(\x09R\x04name\x12 \x0A\x03def\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x03def\x122\x0A\x08behavior\x18\x05 \x01(\x0E2\x16.pg_query.DropBehaviorR\x08behavior\x12\x1E\x0A\x0Amissing_ok\x18\x06 \x01(\x08R\x0Amissing_ok\"\x9A\x03\x0A\x09GrantStmt\x12\x1A\x0A\x08is_grant\x18\x01 \x01(\x08R\x08is_grant\x125\x0A\x08targtype\x18\x02 \x01(\x0E2\x19.pg_query.GrantTargetTypeR\x08targtype\x12.\x0A\x07objtype\x18\x03 \x01(\x0E2\x14.pg_query.ObjectTypeR\x07objtype\x12(\x0A\x07objects\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x07objects\x12.\x0A\x0Aprivileges\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x0Aprivileges\x12*\x0A\x08grantees\x18\x06 \x03(\x0B2\x0E.pg_query.NodeR\x08grantees\x12\"\x0A\x0Cgrant_option\x18\x07 \x01(\x08R\x0Cgrant_option\x12,\x0A\x07grantor\x18\x08 \x01(\x0B2\x12.pg_query.RoleSpecR\x07grantor\x122\x0A\x08behavior\x18\x09 \x01(\x0E2\x16.pg_query.DropBehaviorR\x08behavior\"\xC2\x01\x0A\x0EObjectWithArgs\x12(\x0A\x07objname\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x07objname\x12(\x0A\x07objargs\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x07objargs\x120\x0A\x0Bobjfuncargs\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x0Bobjfuncargs\x12*\x0A\x10args_unspecified\x18\x04 \x01(\x08R\x10args_unspecified\"N\x0A\x0AAccessPriv\x12\x1C\x0A\x09priv_name\x18\x01 \x01(\x09R\x09priv_name\x12\"\x0A\x04cols\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x04cols\"\x9B\x02\x0A\x0DGrantRoleStmt\x124\x0A\x0Dgranted_roles\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x0Dgranted_roles\x124\x0A\x0Dgrantee_roles\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x0Dgrantee_roles\x12\x1A\x0A\x08is_grant\x18\x03 \x01(\x08R\x08is_grant\x12 \x0A\x03opt\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x03opt\x12,\x0A\x07grantor\x18\x05 \x01(\x0B2\x12.pg_query.RoleSpecR\x07grantor\x122\x0A\x08behavior\x18\x06 \x01(\x0E2\x16.pg_query.DropBehaviorR\x08behavior\"s\x0A\x1AAlterDefaultPrivilegesStmt\x12(\x0A\x07options\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x07options\x12+\x0A\x06action\x18\x02 \x01(\x0B2\x13.pg_query.GrantStmtR\x06action\"\xBD\x02\x0A\x08CopyStmt\x12.\x0A\x08relation\x18\x01 \x01(\x0B2\x12.pg_query.RangeVarR\x08relation\x12\$\x0A\x05query\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x05query\x12(\x0A\x07attlist\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x07attlist\x12\x18\x0A\x07is_from\x18\x04 \x01(\x08R\x07is_from\x12\x1E\x0A\x0Ais_program\x18\x05 \x01(\x08R\x0Ais_program\x12\x1A\x0A\x08filename\x18\x06 \x01(\x09R\x08filename\x12(\x0A\x07options\x18\x07 \x03(\x0B2\x0E.pg_query.NodeR\x07options\x121\x0A\x0Cwhere_clause\x18\x08 \x01(\x0B2\x0E.pg_query.NodeR\x0BwhereClause\"\x94\x01\x0A\x0FVariableSetStmt\x12-\x0A\x04kind\x18\x01 \x01(\x0E2\x19.pg_query.VariableSetKindR\x04kind\x12\x12\x0A\x04name\x18\x02 \x01(\x09R\x04name\x12\"\x0A\x04args\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x04args\x12\x1A\x0A\x08is_local\x18\x04 \x01(\x08R\x08is_local\"&\x0A\x10VariableShowStmt\x12\x12\x0A\x04name\x18\x01 \x01(\x09R\x04name\"\xCB\x04\x0A\x0ACreateStmt\x12.\x0A\x08relation\x18\x01 \x01(\x0B2\x12.pg_query.RangeVarR\x08relation\x12-\x0A\x0Atable_elts\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x09tableElts\x123\x0A\x0Dinh_relations\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x0CinhRelations\x12:\x0A\x09partbound\x18\x04 \x01(\x0B2\x1C.pg_query.PartitionBoundSpecR\x09partbound\x123\x0A\x08partspec\x18\x05 \x01(\x0B2\x17.pg_query.PartitionSpecR\x08partspec\x123\x0A\x0Bof_typename\x18\x06 \x01(\x0B2\x12.pg_query.TypeNameR\x0AofTypename\x120\x0A\x0Bconstraints\x18\x07 \x03(\x0B2\x0E.pg_query.NodeR\x0Bconstraints\x12(\x0A\x07options\x18\x08 \x03(\x0B2\x0E.pg_query.NodeR\x07options\x124\x0A\x08oncommit\x18\x09 \x01(\x0E2\x18.pg_query.OnCommitActionR\x08oncommit\x12&\x0A\x0Etablespacename\x18\x0A \x01(\x09R\x0Etablespacename\x12#\x0A\x0Daccess_method\x18\x0B \x01(\x09R\x0CaccessMethod\x12\$\x0A\x0Dif_not_exists\x18\x0C \x01(\x08R\x0Dif_not_exists\"\xFA\x09\x0A\x0AConstraint\x12.\x0A\x07contype\x18\x01 \x01(\x0E2\x14.pg_query.ConstrTypeR\x07contype\x12\x18\x0A\x07conname\x18\x02 \x01(\x09R\x07conname\x12\x1E\x0A\x0Adeferrable\x18\x03 \x01(\x08R\x0Adeferrable\x12\"\x0A\x0Cinitdeferred\x18\x04 \x01(\x08R\x0Cinitdeferred\x12(\x0A\x0Fskip_validation\x18\x05 \x01(\x08R\x0Fskip_validation\x12(\x0A\x0Finitially_valid\x18\x06 \x01(\x08R\x0Finitially_valid\x12\$\x0A\x0Dis_no_inherit\x18\x07 \x01(\x08R\x0Dis_no_inherit\x12*\x0A\x08raw_expr\x18\x08 \x01(\x0B2\x0E.pg_query.NodeR\x08raw_expr\x12 \x0A\x0Bcooked_expr\x18\x09 \x01(\x09R\x0Bcooked_expr\x12&\x0A\x0Egenerated_when\x18\x0A \x01(\x09R\x0Egenerated_when\x12\x1A\x0A\x08inhcount\x18\x0B \x01(\x05R\x08inhcount\x12.\x0A\x12nulls_not_distinct\x18\x0C \x01(\x08R\x12nulls_not_distinct\x12\"\x0A\x04keys\x18\x0D \x03(\x0B2\x0E.pg_query.NodeR\x04keys\x12,\x0A\x09including\x18\x0E \x03(\x0B2\x0E.pg_query.NodeR\x09including\x12.\x0A\x0Aexclusions\x18\x0F \x03(\x0B2\x0E.pg_query.NodeR\x0Aexclusions\x12(\x0A\x07options\x18\x10 \x03(\x0B2\x0E.pg_query.NodeR\x07options\x12\x1C\x0A\x09indexname\x18\x11 \x01(\x09R\x09indexname\x12\x1E\x0A\x0Aindexspace\x18\x12 \x01(\x09R\x0Aindexspace\x122\x0A\x14reset_default_tblspc\x18\x13 \x01(\x08R\x14reset_default_tblspc\x12\$\x0A\x0Daccess_method\x18\x14 \x01(\x09R\x0Daccess_method\x122\x0A\x0Cwhere_clause\x18\x15 \x01(\x0B2\x0E.pg_query.NodeR\x0Cwhere_clause\x12,\x0A\x07pktable\x18\x16 \x01(\x0B2\x12.pg_query.RangeVarR\x07pktable\x12*\x0A\x08fk_attrs\x18\x17 \x03(\x0B2\x0E.pg_query.NodeR\x08fk_attrs\x12*\x0A\x08pk_attrs\x18\x18 \x03(\x0B2\x0E.pg_query.NodeR\x08pk_attrs\x12\"\x0A\x0Cfk_matchtype\x18\x19 \x01(\x09R\x0Cfk_matchtype\x12\$\x0A\x0Dfk_upd_action\x18\x1A \x01(\x09R\x0Dfk_upd_action\x12\$\x0A\x0Dfk_del_action\x18\x1B \x01(\x09R\x0Dfk_del_action\x128\x0A\x0Ffk_del_set_cols\x18\x1C \x03(\x0B2\x0E.pg_query.NodeR\x0Ffk_del_set_cols\x124\x0A\x0Dold_conpfeqop\x18\x1D \x03(\x0B2\x0E.pg_query.NodeR\x0Dold_conpfeqop\x12(\x0A\x0Fold_pktable_oid\x18\x1E \x01(\x0DR\x0Fold_pktable_oid\x12\x1A\x0A\x08location\x18\x1F \x01(\x05R\x08location\"\xAE\x01\x0A\x14CreateTableSpaceStmt\x12&\x0A\x0Etablespacename\x18\x01 \x01(\x09R\x0Etablespacename\x12(\x0A\x05owner\x18\x02 \x01(\x0B2\x12.pg_query.RoleSpecR\x05owner\x12\x1A\x0A\x08location\x18\x03 \x01(\x09R\x08location\x12(\x0A\x07options\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x07options\"\\\x0A\x12DropTableSpaceStmt\x12&\x0A\x0Etablespacename\x18\x01 \x01(\x09R\x0Etablespacename\x12\x1E\x0A\x0Amissing_ok\x18\x02 \x01(\x08R\x0Amissing_ok\"\x89\x01\x0A\x1AAlterTableSpaceOptionsStmt\x12&\x0A\x0Etablespacename\x18\x01 \x01(\x09R\x0Etablespacename\x12(\x0A\x07options\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x07options\x12\x19\x0A\x08is_reset\x18\x03 \x01(\x08R\x07isReset\"\xE7\x01\x0A\x15AlterTableMoveAllStmt\x120\x0A\x13orig_tablespacename\x18\x01 \x01(\x09R\x13orig_tablespacename\x12.\x0A\x07objtype\x18\x02 \x01(\x0E2\x14.pg_query.ObjectTypeR\x07objtype\x12\$\x0A\x05roles\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x05roles\x12.\x0A\x12new_tablespacename\x18\x04 \x01(\x09R\x12new_tablespacename\x12\x16\x0A\x06nowait\x18\x05 \x01(\x08R\x06nowait\"\x7F\x0A\x13CreateExtensionStmt\x12\x18\x0A\x07extname\x18\x01 \x01(\x09R\x07extname\x12\$\x0A\x0Dif_not_exists\x18\x02 \x01(\x08R\x0Dif_not_exists\x12(\x0A\x07options\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x07options\"X\x0A\x12AlterExtensionStmt\x12\x18\x0A\x07extname\x18\x01 \x01(\x09R\x07extname\x12(\x0A\x07options\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x07options\"\xA6\x01\x0A\x1AAlterExtensionContentsStmt\x12\x18\x0A\x07extname\x18\x01 \x01(\x09R\x07extname\x12\x16\x0A\x06action\x18\x02 \x01(\x05R\x06action\x12.\x0A\x07objtype\x18\x03 \x01(\x0E2\x14.pg_query.ObjectTypeR\x07objtype\x12&\x0A\x06object\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x06object\"\x87\x01\x0A\x0DCreateFdwStmt\x12\x18\x0A\x07fdwname\x18\x01 \x01(\x09R\x07fdwname\x122\x0A\x0Cfunc_options\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x0Cfunc_options\x12(\x0A\x07options\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x07options\"\x86\x01\x0A\x0CAlterFdwStmt\x12\x18\x0A\x07fdwname\x18\x01 \x01(\x09R\x07fdwname\x122\x0A\x0Cfunc_options\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x0Cfunc_options\x12(\x0A\x07options\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x07options\"\xDD\x01\x0A\x17CreateForeignServerStmt\x12\x1E\x0A\x0Aservername\x18\x01 \x01(\x09R\x0Aservername\x12\x1E\x0A\x0Aservertype\x18\x02 \x01(\x09R\x0Aservertype\x12\x18\x0A\x07version\x18\x03 \x01(\x09R\x07version\x12\x18\x0A\x07fdwname\x18\x04 \x01(\x09R\x07fdwname\x12\$\x0A\x0Dif_not_exists\x18\x05 \x01(\x08R\x0Dif_not_exists\x12(\x0A\x07options\x18\x06 \x03(\x0B2\x0E.pg_query.NodeR\x07options\"\x9E\x01\x0A\x16AlterForeignServerStmt\x12\x1E\x0A\x0Aservername\x18\x01 \x01(\x09R\x0Aservername\x12\x18\x0A\x07version\x18\x02 \x01(\x09R\x07version\x12(\x0A\x07options\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x07options\x12 \x0A\x0Bhas_version\x18\x04 \x01(\x08R\x0Bhas_version\"\x91\x01\x0A\x16CreateForeignTableStmt\x12-\x0A\x09base_stmt\x18\x01 \x01(\x0B2\x14.pg_query.CreateStmtR\x04base\x12\x1E\x0A\x0Aservername\x18\x02 \x01(\x09R\x0Aservername\x12(\x0A\x07options\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x07options\"\xAF\x01\x0A\x15CreateUserMappingStmt\x12&\x0A\x04user\x18\x01 \x01(\x0B2\x12.pg_query.RoleSpecR\x04user\x12\x1E\x0A\x0Aservername\x18\x02 \x01(\x09R\x0Aservername\x12\$\x0A\x0Dif_not_exists\x18\x03 \x01(\x08R\x0Dif_not_exists\x12(\x0A\x07options\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x07options\"\x88\x01\x0A\x14AlterUserMappingStmt\x12&\x0A\x04user\x18\x01 \x01(\x0B2\x12.pg_query.RoleSpecR\x04user\x12\x1E\x0A\x0Aservername\x18\x02 \x01(\x09R\x0Aservername\x12(\x0A\x07options\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x07options\"}\x0A\x13DropUserMappingStmt\x12&\x0A\x04user\x18\x01 \x01(\x0B2\x12.pg_query.RoleSpecR\x04user\x12\x1E\x0A\x0Aservername\x18\x02 \x01(\x09R\x0Aservername\x12\x1E\x0A\x0Amissing_ok\x18\x03 \x01(\x08R\x0Amissing_ok\"\xA0\x02\x0A\x17ImportForeignSchemaStmt\x12 \x0A\x0Bserver_name\x18\x01 \x01(\x09R\x0Bserver_name\x12\$\x0A\x0Dremote_schema\x18\x02 \x01(\x09R\x0Dremote_schema\x12\"\x0A\x0Clocal_schema\x18\x03 \x01(\x09R\x0Clocal_schema\x12?\x0A\x09list_type\x18\x04 \x01(\x0E2!.pg_query.ImportForeignSchemaTypeR\x09list_type\x12.\x0A\x0Atable_list\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x0Atable_list\x12(\x0A\x07options\x18\x06 \x03(\x0B2\x0E.pg_query.NodeR\x07options\"\x94\x02\x0A\x10CreatePolicyStmt\x12 \x0A\x0Bpolicy_name\x18\x01 \x01(\x09R\x0Bpolicy_name\x12(\x0A\x05table\x18\x02 \x01(\x0B2\x12.pg_query.RangeVarR\x05table\x12\x1A\x0A\x08cmd_name\x18\x03 \x01(\x09R\x08cmd_name\x12\x1E\x0A\x0Apermissive\x18\x04 \x01(\x08R\x0Apermissive\x12\$\x0A\x05roles\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x05roles\x12\"\x0A\x04qual\x18\x06 \x01(\x0B2\x0E.pg_query.NodeR\x04qual\x12.\x0A\x0Awith_check\x18\x07 \x01(\x0B2\x0E.pg_query.NodeR\x0Awith_check\"\xD7\x01\x0A\x0FAlterPolicyStmt\x12 \x0A\x0Bpolicy_name\x18\x01 \x01(\x09R\x0Bpolicy_name\x12(\x0A\x05table\x18\x02 \x01(\x0B2\x12.pg_query.RangeVarR\x05table\x12\$\x0A\x05roles\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x05roles\x12\"\x0A\x04qual\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x04qual\x12.\x0A\x0Awith_check\x18\x05 \x01(\x0B2\x0E.pg_query.NodeR\x0Awith_check\"r\x0A\x0CCreateAmStmt\x12\x16\x0A\x06amname\x18\x01 \x01(\x09R\x06amname\x122\x0A\x0Chandler_name\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x0Chandler_name\x12\x16\x0A\x06amtype\x18\x03 \x01(\x09R\x06amtype\"\xB6\x04\x0A\x0ECreateTrigStmt\x12\x18\x0A\x07replace\x18\x01 \x01(\x08R\x07replace\x12\"\x0A\x0Cisconstraint\x18\x02 \x01(\x08R\x0Cisconstraint\x12\x1A\x0A\x08trigname\x18\x03 \x01(\x09R\x08trigname\x12.\x0A\x08relation\x18\x04 \x01(\x0B2\x12.pg_query.RangeVarR\x08relation\x12*\x0A\x08funcname\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x08funcname\x12\"\x0A\x04args\x18\x06 \x03(\x0B2\x0E.pg_query.NodeR\x04args\x12\x10\x0A\x03row\x18\x07 \x01(\x08R\x03row\x12\x16\x0A\x06timing\x18\x08 \x01(\x05R\x06timing\x12\x16\x0A\x06events\x18\x09 \x01(\x05R\x06events\x12(\x0A\x07columns\x18\x0A \x03(\x0B2\x0E.pg_query.NodeR\x07columns\x12/\x0A\x0Bwhen_clause\x18\x0B \x01(\x0B2\x0E.pg_query.NodeR\x0AwhenClause\x127\x0A\x0Ftransition_rels\x18\x0C \x03(\x0B2\x0E.pg_query.NodeR\x0EtransitionRels\x12\x1E\x0A\x0Adeferrable\x18\x0D \x01(\x08R\x0Adeferrable\x12\"\x0A\x0Cinitdeferred\x18\x0E \x01(\x08R\x0Cinitdeferred\x120\x0A\x09constrrel\x18\x0F \x01(\x0B2\x12.pg_query.RangeVarR\x09constrrel\"\xAB\x01\x0A\x13CreateEventTrigStmt\x12\x1A\x0A\x08trigname\x18\x01 \x01(\x09R\x08trigname\x12\x1C\x0A\x09eventname\x18\x02 \x01(\x09R\x09eventname\x12.\x0A\x0Awhenclause\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x0Awhenclause\x12*\x0A\x08funcname\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x08funcname\"N\x0A\x12AlterEventTrigStmt\x12\x1A\x0A\x08trigname\x18\x01 \x01(\x09R\x08trigname\x12\x1C\x0A\x09tgenabled\x18\x02 \x01(\x09R\x09tgenabled\"\xED\x01\x0A\x0FCreatePLangStmt\x12\x18\x0A\x07replace\x18\x01 \x01(\x08R\x07replace\x12\x16\x0A\x06plname\x18\x02 \x01(\x09R\x06plname\x12,\x0A\x09plhandler\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x09plhandler\x12*\x0A\x08plinline\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x08plinline\x120\x0A\x0Bplvalidator\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x0Bplvalidator\x12\x1C\x0A\x09pltrusted\x18\x06 \x01(\x08R\x09pltrusted\"\x84\x01\x0A\x0ECreateRoleStmt\x124\x0A\x09stmt_type\x18\x01 \x01(\x0E2\x16.pg_query.RoleStmtTypeR\x09stmt_type\x12\x12\x0A\x04role\x18\x02 \x01(\x09R\x04role\x12(\x0A\x07options\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x07options\"y\x0A\x0DAlterRoleStmt\x12&\x0A\x04role\x18\x01 \x01(\x0B2\x12.pg_query.RoleSpecR\x04role\x12(\x0A\x07options\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x07options\x12\x16\x0A\x06action\x18\x03 \x01(\x05R\x06action\"\x8B\x01\x0A\x10AlterRoleSetStmt\x12&\x0A\x04role\x18\x01 \x01(\x0B2\x12.pg_query.RoleSpecR\x04role\x12\x1A\x0A\x08database\x18\x02 \x01(\x09R\x08database\x123\x0A\x07setstmt\x18\x03 \x01(\x0B2\x19.pg_query.VariableSetStmtR\x07setstmt\"T\x0A\x0CDropRoleStmt\x12\$\x0A\x05roles\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x05roles\x12\x1E\x0A\x0Amissing_ok\x18\x02 \x01(\x08R\x0Amissing_ok\"\xCE\x01\x0A\x0DCreateSeqStmt\x12.\x0A\x08sequence\x18\x01 \x01(\x0B2\x12.pg_query.RangeVarR\x08sequence\x12(\x0A\x07options\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x07options\x12\x19\x0A\x08owner_id\x18\x03 \x01(\x0DR\x07ownerId\x12\"\x0A\x0Cfor_identity\x18\x04 \x01(\x08R\x0Cfor_identity\x12\$\x0A\x0Dif_not_exists\x18\x05 \x01(\x08R\x0Dif_not_exists\"\xAC\x01\x0A\x0CAlterSeqStmt\x12.\x0A\x08sequence\x18\x01 \x01(\x0B2\x12.pg_query.RangeVarR\x08sequence\x12(\x0A\x07options\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x07options\x12\"\x0A\x0Cfor_identity\x18\x03 \x01(\x08R\x0Cfor_identity\x12\x1E\x0A\x0Amissing_ok\x18\x04 \x01(\x08R\x0Amissing_ok\"\x92\x02\x0A\x0ADefineStmt\x12(\x0A\x04kind\x18\x01 \x01(\x0E2\x14.pg_query.ObjectTypeR\x04kind\x12\x1A\x0A\x08oldstyle\x18\x02 \x01(\x08R\x08oldstyle\x12*\x0A\x08defnames\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x08defnames\x12\"\x0A\x04args\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x04args\x12.\x0A\x0Adefinition\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x0Adefinition\x12\$\x0A\x0Dif_not_exists\x18\x06 \x01(\x08R\x0Dif_not_exists\x12\x18\x0A\x07replace\x18\x07 \x01(\x08R\x07replace\"\xDF\x01\x0A\x10CreateDomainStmt\x12.\x0A\x0Adomainname\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x0Adomainname\x12/\x0A\x09type_name\x18\x02 \x01(\x0B2\x12.pg_query.TypeNameR\x08typeName\x128\x0A\x0Bcoll_clause\x18\x03 \x01(\x0B2\x17.pg_query.CollateClauseR\x0AcollClause\x120\x0A\x0Bconstraints\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x0Bconstraints\"\x86\x02\x0A\x11CreateOpClassStmt\x120\x0A\x0Bopclassname\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x0Bopclassname\x122\x0A\x0Copfamilyname\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x0Copfamilyname\x12\x16\x0A\x06amname\x18\x03 \x01(\x09R\x06amname\x12.\x0A\x08datatype\x18\x04 \x01(\x0B2\x12.pg_query.TypeNameR\x08datatype\x12\$\x0A\x05items\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x05items\x12\x1D\x0A\x0Ais_default\x18\x06 \x01(\x08R\x09isDefault\"\x8D\x02\x0A\x11CreateOpClassItem\x12\x1A\x0A\x08itemtype\x18\x01 \x01(\x05R\x08itemtype\x12,\x0A\x04name\x18\x02 \x01(\x0B2\x18.pg_query.ObjectWithArgsR\x04name\x12\x16\x0A\x06number\x18\x03 \x01(\x05R\x06number\x122\x0A\x0Corder_family\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x0Corder_family\x12.\x0A\x0Aclass_args\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x0Aclass_args\x122\x0A\x0Astoredtype\x18\x06 \x01(\x0B2\x12.pg_query.TypeNameR\x0Astoredtype\"`\x0A\x12CreateOpFamilyStmt\x122\x0A\x0Copfamilyname\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x0Copfamilyname\x12\x16\x0A\x06amname\x18\x02 \x01(\x09R\x06amname\"\x9E\x01\x0A\x11AlterOpFamilyStmt\x122\x0A\x0Copfamilyname\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x0Copfamilyname\x12\x16\x0A\x06amname\x18\x02 \x01(\x09R\x06amname\x12\x17\x0A\x07is_drop\x18\x03 \x01(\x08R\x06isDrop\x12\$\x0A\x05items\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x05items\"\xDF\x01\x0A\x08DropStmt\x12(\x0A\x07objects\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x07objects\x125\x0A\x0Bremove_type\x18\x02 \x01(\x0E2\x14.pg_query.ObjectTypeR\x0AremoveType\x122\x0A\x08behavior\x18\x03 \x01(\x0E2\x16.pg_query.DropBehaviorR\x08behavior\x12\x1E\x0A\x0Amissing_ok\x18\x04 \x01(\x08R\x0Amissing_ok\x12\x1E\x0A\x0Aconcurrent\x18\x05 \x01(\x08R\x0Aconcurrent\"\x94\x01\x0A\x0CTruncateStmt\x12,\x0A\x09relations\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x09relations\x12\"\x0A\x0Crestart_seqs\x18\x02 \x01(\x08R\x0Crestart_seqs\x122\x0A\x08behavior\x18\x03 \x01(\x0E2\x16.pg_query.DropBehaviorR\x08behavior\"\x7F\x0A\x0BCommentStmt\x12.\x0A\x07objtype\x18\x01 \x01(\x0E2\x14.pg_query.ObjectTypeR\x07objtype\x12&\x0A\x06object\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x06object\x12\x18\x0A\x07comment\x18\x03 \x01(\x09R\x07comment\"\x98\x01\x0A\x0CSecLabelStmt\x12.\x0A\x07objtype\x18\x01 \x01(\x0E2\x14.pg_query.ObjectTypeR\x07objtype\x12&\x0A\x06object\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x06object\x12\x1A\x0A\x08provider\x18\x03 \x01(\x09R\x08provider\x12\x14\x0A\x05label\x18\x04 \x01(\x09R\x05label\"s\x0A\x11DeclareCursorStmt\x12\x1E\x0A\x0Aportalname\x18\x01 \x01(\x09R\x0Aportalname\x12\x18\x0A\x07options\x18\x02 \x01(\x05R\x07options\x12\$\x0A\x05query\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x05query\"1\x0A\x0FClosePortalStmt\x12\x1E\x0A\x0Aportalname\x18\x01 \x01(\x09R\x0Aportalname\"\x96\x01\x0A\x09FetchStmt\x126\x0A\x09direction\x18\x01 \x01(\x0E2\x18.pg_query.FetchDirectionR\x09direction\x12\x19\x0A\x08how_many\x18\x02 \x01(\x03R\x07howMany\x12\x1E\x0A\x0Aportalname\x18\x03 \x01(\x09R\x0Aportalname\x12\x16\x0A\x06ismove\x18\x04 \x01(\x08R\x06ismove\"\xDC\x07\x0A\x09IndexStmt\x12\x18\x0A\x07idxname\x18\x01 \x01(\x09R\x07idxname\x12.\x0A\x08relation\x18\x02 \x01(\x0B2\x12.pg_query.RangeVarR\x08relation\x12#\x0A\x0Daccess_method\x18\x03 \x01(\x09R\x0CaccessMethod\x12\x1F\x0A\x0Btable_space\x18\x04 \x01(\x09R\x0AtableSpace\x121\x0A\x0Cindex_params\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x0BindexParams\x12D\x0A\x16index_including_params\x18\x06 \x03(\x0B2\x0E.pg_query.NodeR\x14indexIncludingParams\x12(\x0A\x07options\x18\x07 \x03(\x0B2\x0E.pg_query.NodeR\x07options\x121\x0A\x0Cwhere_clause\x18\x08 \x01(\x0B2\x0E.pg_query.NodeR\x0BwhereClause\x128\x0A\x10exclude_op_names\x18\x09 \x03(\x0B2\x0E.pg_query.NodeR\x0EexcludeOpNames\x12\x1E\x0A\x0Aidxcomment\x18\x0A \x01(\x09R\x0Aidxcomment\x12\x1B\x0A\x09index_oid\x18\x0B \x01(\x0DR\x08indexOid\x12\x1D\x0A\x0Aold_number\x18\x0C \x01(\x0DR\x09oldNumber\x12(\x0A\x10old_create_subid\x18\x0D \x01(\x0DR\x0EoldCreateSubid\x12C\x0A\x1Eold_first_relfilelocator_subid\x18\x0E \x01(\x0DR\x1BoldFirstRelfilelocatorSubid\x12\x16\x0A\x06unique\x18\x0F \x01(\x08R\x06unique\x12.\x0A\x12nulls_not_distinct\x18\x10 \x01(\x08R\x12nulls_not_distinct\x12\x18\x0A\x07primary\x18\x11 \x01(\x08R\x07primary\x12\"\x0A\x0Cisconstraint\x18\x12 \x01(\x08R\x0Cisconstraint\x12\x1E\x0A\x0Adeferrable\x18\x13 \x01(\x08R\x0Adeferrable\x12\"\x0A\x0Cinitdeferred\x18\x14 \x01(\x08R\x0Cinitdeferred\x12 \x0A\x0Btransformed\x18\x15 \x01(\x08R\x0Btransformed\x12\x1E\x0A\x0Aconcurrent\x18\x16 \x01(\x08R\x0Aconcurrent\x12\$\x0A\x0Dif_not_exists\x18\x17 \x01(\x08R\x0Dif_not_exists\x122\x0A\x14reset_default_tblspc\x18\x18 \x01(\x08R\x14reset_default_tblspc\"\xA9\x02\x0A\x0FCreateStatsStmt\x12*\x0A\x08defnames\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x08defnames\x12.\x0A\x0Astat_types\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x0Astat_types\x12\$\x0A\x05exprs\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x05exprs\x12,\x0A\x09relations\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x09relations\x12\x1E\x0A\x0Astxcomment\x18\x05 \x01(\x09R\x0Astxcomment\x12 \x0A\x0Btransformed\x18\x06 \x01(\x08R\x0Btransformed\x12\$\x0A\x0Dif_not_exists\x18\x07 \x01(\x08R\x0Dif_not_exists\"C\x0A\x09StatsElem\x12\x12\x0A\x04name\x18\x01 \x01(\x09R\x04name\x12\"\x0A\x04expr\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x04expr\"\x92\x01\x0A\x0EAlterStatsStmt\x12*\x0A\x08defnames\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x08defnames\x124\x0A\x0Dstxstattarget\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x0Dstxstattarget\x12\x1E\x0A\x0Amissing_ok\x18\x03 \x01(\x08R\x0Amissing_ok\"\xB9\x02\x0A\x12CreateFunctionStmt\x12\"\x0A\x0Cis_procedure\x18\x01 \x01(\x08R\x0Cis_procedure\x12\x18\x0A\x07replace\x18\x02 \x01(\x08R\x07replace\x12*\x0A\x08funcname\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x08funcname\x12.\x0A\x0Aparameters\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x0Aparameters\x123\x0A\x0Breturn_type\x18\x05 \x01(\x0B2\x12.pg_query.TypeNameR\x0AreturnType\x12(\x0A\x07options\x18\x06 \x03(\x0B2\x0E.pg_query.NodeR\x07options\x12*\x0A\x08sql_body\x18\x07 \x01(\x0B2\x0E.pg_query.NodeR\x08sql_body\"\xB5\x01\x0A\x11FunctionParameter\x12\x12\x0A\x04name\x18\x01 \x01(\x09R\x04name\x12-\x0A\x08arg_type\x18\x02 \x01(\x0B2\x12.pg_query.TypeNameR\x07argType\x123\x0A\x04mode\x18\x03 \x01(\x0E2\x1F.pg_query.FunctionParameterModeR\x04mode\x12(\x0A\x07defexpr\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x07defexpr\"\x9B\x01\x0A\x11AlterFunctionStmt\x12.\x0A\x07objtype\x18\x01 \x01(\x0E2\x14.pg_query.ObjectTypeR\x07objtype\x12,\x0A\x04func\x18\x02 \x01(\x0B2\x18.pg_query.ObjectWithArgsR\x04func\x12(\x0A\x07actions\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x07actions\",\x0A\x06DoStmt\x12\"\x0A\x04args\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x04args\"\x8E\x01\x0A\x0FInlineCodeBlock\x12 \x0A\x0Bsource_text\x18\x01 \x01(\x09R\x0Bsource_text\x12\x19\x0A\x08lang_oid\x18\x02 \x01(\x0DR\x07langOid\x12&\x0A\x0Flang_is_trusted\x18\x03 \x01(\x08R\x0DlangIsTrusted\x12\x16\x0A\x06atomic\x18\x04 \x01(\x08R\x06atomic\"\x94\x01\x0A\x08CallStmt\x12.\x0A\x08funccall\x18\x01 \x01(\x0B2\x12.pg_query.FuncCallR\x08funccall\x12.\x0A\x08funcexpr\x18\x02 \x01(\x0B2\x12.pg_query.FuncExprR\x08funcexpr\x12(\x0A\x07outargs\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x07outargs\"%\x0A\x0BCallContext\x12\x16\x0A\x06atomic\x18\x01 \x01(\x08R\x06atomic\"\xDE\x02\x0A\x0ARenameStmt\x125\x0A\x0Brename_type\x18\x01 \x01(\x0E2\x14.pg_query.ObjectTypeR\x0ArenameType\x129\x0A\x0Drelation_type\x18\x02 \x01(\x0E2\x14.pg_query.ObjectTypeR\x0CrelationType\x12.\x0A\x08relation\x18\x03 \x01(\x0B2\x12.pg_query.RangeVarR\x08relation\x12&\x0A\x06object\x18\x04 \x01(\x0B2\x0E.pg_query.NodeR\x06object\x12\x18\x0A\x07subname\x18\x05 \x01(\x09R\x07subname\x12\x18\x0A\x07newname\x18\x06 \x01(\x09R\x07newname\x122\x0A\x08behavior\x18\x07 \x01(\x0E2\x16.pg_query.DropBehaviorR\x08behavior\x12\x1E\x0A\x0Amissing_ok\x18\x08 \x01(\x08R\x0Amissing_ok\"\xEB\x01\x0A\x16AlterObjectDependsStmt\x125\x0A\x0Bobject_type\x18\x01 \x01(\x0E2\x14.pg_query.ObjectTypeR\x0AobjectType\x12.\x0A\x08relation\x18\x02 \x01(\x0B2\x12.pg_query.RangeVarR\x08relation\x12&\x0A\x06object\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x06object\x12*\x0A\x07extname\x18\x04 \x01(\x0B2\x10.pg_query.StringR\x07extname\x12\x16\x0A\x06remove\x18\x05 \x01(\x08R\x06remove\"\xE4\x01\x0A\x15AlterObjectSchemaStmt\x125\x0A\x0Bobject_type\x18\x01 \x01(\x0E2\x14.pg_query.ObjectTypeR\x0AobjectType\x12.\x0A\x08relation\x18\x02 \x01(\x0B2\x12.pg_query.RangeVarR\x08relation\x12&\x0A\x06object\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x06object\x12\x1C\x0A\x09newschema\x18\x04 \x01(\x09R\x09newschema\x12\x1E\x0A\x0Amissing_ok\x18\x05 \x01(\x08R\x0Amissing_ok\"\xCF\x01\x0A\x0EAlterOwnerStmt\x125\x0A\x0Bobject_type\x18\x01 \x01(\x0E2\x14.pg_query.ObjectTypeR\x0AobjectType\x12.\x0A\x08relation\x18\x02 \x01(\x0B2\x12.pg_query.RangeVarR\x08relation\x12&\x0A\x06object\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x06object\x12.\x0A\x08newowner\x18\x04 \x01(\x0B2\x12.pg_query.RoleSpecR\x08newowner\"s\x0A\x11AlterOperatorStmt\x124\x0A\x08opername\x18\x01 \x01(\x0B2\x18.pg_query.ObjectWithArgsR\x08opername\x12(\x0A\x07options\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x07options\"f\x0A\x0DAlterTypeStmt\x12+\x0A\x09type_name\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x08typeName\x12(\x0A\x07options\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x07options\"\x90\x02\x0A\x08RuleStmt\x12.\x0A\x08relation\x18\x01 \x01(\x0B2\x12.pg_query.RangeVarR\x08relation\x12\x1A\x0A\x08rulename\x18\x02 \x01(\x09R\x08rulename\x121\x0A\x0Cwhere_clause\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x0BwhereClause\x12'\x0A\x05event\x18\x04 \x01(\x0E2\x11.pg_query.CmdTypeR\x05event\x12\x18\x0A\x07instead\x18\x05 \x01(\x08R\x07instead\x12(\x0A\x07actions\x18\x06 \x03(\x0B2\x0E.pg_query.NodeR\x07actions\x12\x18\x0A\x07replace\x18\x07 \x01(\x08R\x07replace\"L\x0A\x0ANotifyStmt\x12\$\x0A\x0Dconditionname\x18\x01 \x01(\x09R\x0Dconditionname\x12\x18\x0A\x07payload\x18\x02 \x01(\x09R\x07payload\"2\x0A\x0AListenStmt\x12\$\x0A\x0Dconditionname\x18\x01 \x01(\x09R\x0Dconditionname\"4\x0A\x0CUnlistenStmt\x12\$\x0A\x0Dconditionname\x18\x01 \x01(\x09R\x0Dconditionname\"\xDA\x01\x0A\x0FTransactionStmt\x121\x0A\x04kind\x18\x01 \x01(\x0E2\x1D.pg_query.TransactionStmtKindR\x04kind\x12(\x0A\x07options\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x07options\x12&\x0A\x0Esavepoint_name\x18\x03 \x01(\x09R\x0Esavepoint_name\x12\x10\x0A\x03gid\x18\x04 \x01(\x09R\x03gid\x12\x14\x0A\x05chain\x18\x05 \x01(\x08R\x05chain\x12\x1A\x0A\x08location\x18\x06 \x01(\x05R\x08location\"q\x0A\x11CompositeTypeStmt\x12,\x0A\x07typevar\x18\x01 \x01(\x0B2\x12.pg_query.RangeVarR\x07typevar\x12.\x0A\x0Acoldeflist\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x0Acoldeflist\"a\x0A\x0ECreateEnumStmt\x12+\x0A\x09type_name\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x08typeName\x12\"\x0A\x04vals\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x04vals\"f\x0A\x0FCreateRangeStmt\x12+\x0A\x09type_name\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x08typeName\x12&\x0A\x06params\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x06params\"\xF5\x01\x0A\x0DAlterEnumStmt\x12+\x0A\x09type_name\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x08typeName\x12\x17\x0A\x07old_val\x18\x02 \x01(\x09R\x06oldVal\x12\x17\x0A\x07new_val\x18\x03 \x01(\x09R\x06newVal\x12(\x0A\x10new_val_neighbor\x18\x04 \x01(\x09R\x0EnewValNeighbor\x12'\x0A\x10new_val_is_after\x18\x05 \x01(\x08R\x0DnewValIsAfter\x122\x0A\x16skip_if_new_val_exists\x18\x06 \x01(\x08R\x12skipIfNewValExists\"\x8D\x02\x0A\x08ViewStmt\x12&\x0A\x04view\x18\x01 \x01(\x0B2\x12.pg_query.RangeVarR\x04view\x12(\x0A\x07aliases\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x07aliases\x12\$\x0A\x05query\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x05query\x12\x18\x0A\x07replace\x18\x04 \x01(\x08R\x07replace\x12(\x0A\x07options\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x07options\x12E\x0A\x11with_check_option\x18\x06 \x01(\x0E2\x19.pg_query.ViewCheckOptionR\x0FwithCheckOption\"&\x0A\x08LoadStmt\x12\x1A\x0A\x08filename\x18\x01 \x01(\x09R\x08filename\"P\x0A\x0CCreatedbStmt\x12\x16\x0A\x06dbname\x18\x01 \x01(\x09R\x06dbname\x12(\x0A\x07options\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x07options\"U\x0A\x11AlterDatabaseStmt\x12\x16\x0A\x06dbname\x18\x01 \x01(\x09R\x06dbname\x12(\x0A\x07options\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x07options\"6\x0A\x1CAlterDatabaseRefreshCollStmt\x12\x16\x0A\x06dbname\x18\x01 \x01(\x09R\x06dbname\"c\x0A\x14AlterDatabaseSetStmt\x12\x16\x0A\x06dbname\x18\x01 \x01(\x09R\x06dbname\x123\x0A\x07setstmt\x18\x02 \x01(\x0B2\x19.pg_query.VariableSetStmtR\x07setstmt\"n\x0A\x0ADropdbStmt\x12\x16\x0A\x06dbname\x18\x01 \x01(\x09R\x06dbname\x12\x1E\x0A\x0Amissing_ok\x18\x02 \x01(\x08R\x0Amissing_ok\x12(\x0A\x07options\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x07options\"F\x0A\x0FAlterSystemStmt\x123\x0A\x07setstmt\x18\x01 \x01(\x0B2\x19.pg_query.VariableSetStmtR\x07setstmt\"\x83\x01\x0A\x0BClusterStmt\x12.\x0A\x08relation\x18\x01 \x01(\x0B2\x12.pg_query.RangeVarR\x08relation\x12\x1C\x0A\x09indexname\x18\x02 \x01(\x09R\x09indexname\x12&\x0A\x06params\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x06params\"~\x0A\x0AVacuumStmt\x12(\x0A\x07options\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x07options\x12\"\x0A\x04rels\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x04rels\x12\"\x0A\x0Cis_vacuumcmd\x18\x03 \x01(\x08R\x0Cis_vacuumcmd\"|\x0A\x0EVacuumRelation\x12.\x0A\x08relation\x18\x01 \x01(\x0B2\x12.pg_query.RangeVarR\x08relation\x12\x10\x0A\x03oid\x18\x02 \x01(\x0DR\x03oid\x12(\x0A\x07va_cols\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x07va_cols\"]\x0A\x0BExplainStmt\x12\$\x0A\x05query\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x05query\x12(\x0A\x07options\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x07options\"\xE1\x01\x0A\x11CreateTableAsStmt\x12\$\x0A\x05query\x18\x01 \x01(\x0B2\x0E.pg_query.NodeR\x05query\x12(\x0A\x04into\x18\x02 \x01(\x0B2\x14.pg_query.IntoClauseR\x04into\x12.\x0A\x07objtype\x18\x03 \x01(\x0E2\x14.pg_query.ObjectTypeR\x07objtype\x12&\x0A\x0Eis_select_into\x18\x04 \x01(\x08R\x0Eis_select_into\x12\$\x0A\x0Dif_not_exists\x18\x05 \x01(\x08R\x0Dif_not_exists\"\x81\x01\x0A\x12RefreshMatViewStmt\x12\x1E\x0A\x0Aconcurrent\x18\x01 \x01(\x08R\x0Aconcurrent\x12\x1B\x0A\x09skip_data\x18\x02 \x01(\x08R\x08skipData\x12.\x0A\x08relation\x18\x03 \x01(\x0B2\x12.pg_query.RangeVarR\x08relation\"\x10\x0A\x0ECheckPointStmt\"<\x0A\x0BDiscardStmt\x12-\x0A\x06target\x18\x01 \x01(\x0E2\x15.pg_query.DiscardModeR\x06target\"d\x0A\x08LockStmt\x12,\x0A\x09relations\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x09relations\x12\x12\x0A\x04mode\x18\x02 \x01(\x05R\x04mode\x12\x16\x0A\x06nowait\x18\x03 \x01(\x08R\x06nowait\"b\x0A\x12ConstraintsSetStmt\x120\x0A\x0Bconstraints\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x0Bconstraints\x12\x1A\x0A\x08deferred\x18\x02 \x01(\x08R\x08deferred\"\xAA\x01\x0A\x0BReindexStmt\x12/\x0A\x04kind\x18\x01 \x01(\x0E2\x1B.pg_query.ReindexObjectTypeR\x04kind\x12.\x0A\x08relation\x18\x02 \x01(\x0B2\x12.pg_query.RangeVarR\x08relation\x12\x12\x0A\x04name\x18\x03 \x01(\x09R\x04name\x12&\x0A\x06params\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x06params\"\xEA\x01\x0A\x14CreateConversionStmt\x128\x0A\x0Fconversion_name\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x0Fconversion_name\x12,\x0A\x11for_encoding_name\x18\x02 \x01(\x09R\x11for_encoding_name\x12*\x0A\x10to_encoding_name\x18\x03 \x01(\x09R\x10to_encoding_name\x12,\x0A\x09func_name\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x09func_name\x12\x10\x0A\x03def\x18\x05 \x01(\x08R\x03def\"\xF1\x01\x0A\x0ECreateCastStmt\x122\x0A\x0Asourcetype\x18\x01 \x01(\x0B2\x12.pg_query.TypeNameR\x0Asourcetype\x122\x0A\x0Atargettype\x18\x02 \x01(\x0B2\x12.pg_query.TypeNameR\x0Atargettype\x12,\x0A\x04func\x18\x03 \x01(\x0B2\x18.pg_query.ObjectWithArgsR\x04func\x123\x0A\x07context\x18\x04 \x01(\x0E2\x19.pg_query.CoercionContextR\x07context\x12\x14\x0A\x05inout\x18\x05 \x01(\x08R\x05inout\"\xD9\x01\x0A\x13CreateTransformStmt\x12\x18\x0A\x07replace\x18\x01 \x01(\x08R\x07replace\x120\x0A\x09type_name\x18\x02 \x01(\x0B2\x12.pg_query.TypeNameR\x09type_name\x12\x12\x0A\x04lang\x18\x03 \x01(\x09R\x04lang\x122\x0A\x07fromsql\x18\x04 \x01(\x0B2\x18.pg_query.ObjectWithArgsR\x07fromsql\x12.\x0A\x05tosql\x18\x05 \x01(\x0B2\x18.pg_query.ObjectWithArgsR\x05tosql\"s\x0A\x0BPrepareStmt\x12\x12\x0A\x04name\x18\x01 \x01(\x09R\x04name\x12*\x0A\x08argtypes\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x08argtypes\x12\$\x0A\x05query\x18\x03 \x01(\x0B2\x0E.pg_query.NodeR\x05query\"I\x0A\x0BExecuteStmt\x12\x12\x0A\x04name\x18\x01 \x01(\x09R\x04name\x12&\x0A\x06params\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x06params\"V\x0A\x0EDeallocateStmt\x12\x12\x0A\x04name\x18\x01 \x01(\x09R\x04name\x12\x14\x0A\x05isall\x18\x02 \x01(\x08R\x05isall\x12\x1A\x0A\x08location\x18\x03 \x01(\x05R\x08location\"i\x0A\x0DDropOwnedStmt\x12\$\x0A\x05roles\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x05roles\x122\x0A\x08behavior\x18\x02 \x01(\x0E2\x16.pg_query.DropBehaviorR\x08behavior\"g\x0A\x11ReassignOwnedStmt\x12\$\x0A\x05roles\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x05roles\x12,\x0A\x07newrole\x18\x02 \x01(\x0B2\x12.pg_query.RoleSpecR\x07newrole\"m\x0A\x15AlterTSDictionaryStmt\x12*\x0A\x08dictname\x18\x01 \x03(\x0B2\x0E.pg_query.NodeR\x08dictname\x12(\x0A\x07options\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x07options\"\x9F\x02\x0A\x18AlterTSConfigurationStmt\x12/\x0A\x04kind\x18\x01 \x01(\x0E2\x1B.pg_query.AlterTSConfigTypeR\x04kind\x12(\x0A\x07cfgname\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x07cfgname\x12,\x0A\x09tokentype\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x09tokentype\x12\$\x0A\x05dicts\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x05dicts\x12\x1A\x0A\x08override\x18\x05 \x01(\x08R\x08override\x12\x18\x0A\x07replace\x18\x06 \x01(\x08R\x07replace\x12\x1E\x0A\x0Amissing_ok\x18\x07 \x01(\x08R\x0Amissing_ok\"\x9F\x01\x0A\x10PublicationTable\x12.\x0A\x08relation\x18\x01 \x01(\x0B2\x12.pg_query.RangeVarR\x08relation\x121\x0A\x0Cwhere_clause\x18\x02 \x01(\x0B2\x0E.pg_query.NodeR\x0BwhereClause\x12(\x0A\x07columns\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x07columns\"\xBE\x01\x0A\x12PublicationObjSpec\x12@\x0A\x0Apubobjtype\x18\x01 \x01(\x0E2 .pg_query.PublicationObjSpecTypeR\x0Apubobjtype\x12\x12\x0A\x04name\x18\x02 \x01(\x09R\x04name\x126\x0A\x08pubtable\x18\x03 \x01(\x0B2\x1A.pg_query.PublicationTableR\x08pubtable\x12\x1A\x0A\x08location\x18\x04 \x01(\x05R\x08location\"\xB3\x01\x0A\x15CreatePublicationStmt\x12\x18\x0A\x07pubname\x18\x01 \x01(\x09R\x07pubname\x12(\x0A\x07options\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x07options\x12.\x0A\x0Apubobjects\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x0Apubobjects\x12&\x0A\x0Efor_all_tables\x18\x04 \x01(\x08R\x0Efor_all_tables\"\xEC\x01\x0A\x14AlterPublicationStmt\x12\x18\x0A\x07pubname\x18\x01 \x01(\x09R\x07pubname\x12(\x0A\x07options\x18\x02 \x03(\x0B2\x0E.pg_query.NodeR\x07options\x12.\x0A\x0Apubobjects\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x0Apubobjects\x12&\x0A\x0Efor_all_tables\x18\x04 \x01(\x08R\x0Efor_all_tables\x128\x0A\x06action\x18\x05 \x01(\x0E2 .pg_query.AlterPublicationActionR\x06action\"\xAA\x01\x0A\x16CreateSubscriptionStmt\x12\x18\x0A\x07subname\x18\x01 \x01(\x09R\x07subname\x12\x1A\x0A\x08conninfo\x18\x02 \x01(\x09R\x08conninfo\x120\x0A\x0Bpublication\x18\x03 \x03(\x0B2\x0E.pg_query.NodeR\x0Bpublication\x12(\x0A\x07options\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x07options\"\xDE\x01\x0A\x15AlterSubscriptionStmt\x123\x0A\x04kind\x18\x01 \x01(\x0E2\x1F.pg_query.AlterSubscriptionTypeR\x04kind\x12\x18\x0A\x07subname\x18\x02 \x01(\x09R\x07subname\x12\x1A\x0A\x08conninfo\x18\x03 \x01(\x09R\x08conninfo\x120\x0A\x0Bpublication\x18\x04 \x03(\x0B2\x0E.pg_query.NodeR\x0Bpublication\x12(\x0A\x07options\x18\x05 \x03(\x0B2\x0E.pg_query.NodeR\x07options\"\x84\x01\x0A\x14DropSubscriptionStmt\x12\x18\x0A\x07subname\x18\x01 \x01(\x09R\x07subname\x12\x1E\x0A\x0Amissing_ok\x18\x02 \x01(\x08R\x0Amissing_ok\x122\x0A\x08behavior\x18\x03 \x01(\x0E2\x16.pg_query.DropBehaviorR\x08behavior\"t\x0A\x09ScanToken\x12\x0D\x0A\x05start\x18\x01 \x01(\x05\x12\x0B\x0A\x03end\x18\x02 \x01(\x05\x12\x1E\x0A\x05token\x18\x04 \x01(\x0E2\x0F.pg_query.Token\x12+\x0A\x0Ckeyword_kind\x18\x05 \x01(\x0E2\x15.pg_query.KeywordKind*\x9B\x01\x0A\x0BQuerySource\x12\x1A\x0A\x16QUERY_SOURCE_UNDEFINED\x10\x00\x12\x11\x0A\x0DQSRC_ORIGINAL\x10\x01\x12\x0F\x0A\x0BQSRC_PARSER\x10\x02\x12\x15\x0A\x11QSRC_INSTEAD_RULE\x10\x03\x12\x1A\x0A\x16QSRC_QUAL_INSTEAD_RULE\x10\x04\x12\x19\x0A\x15QSRC_NON_INSTEAD_RULE\x10\x05*m\x0A\x09SortByDir\x12\x19\x0A\x15SORT_BY_DIR_UNDEFINED\x10\x00\x12\x12\x0A\x0ESORTBY_DEFAULT\x10\x01\x12\x0E\x0A\x0ASORTBY_ASC\x10\x02\x12\x0F\x0A\x0BSORTBY_DESC\x10\x03\x12\x10\x0A\x0CSORTBY_USING\x10\x04*s\x0A\x0BSortByNulls\x12\x1B\x0A\x17SORT_BY_NULLS_UNDEFINED\x10\x00\x12\x18\x0A\x14SORTBY_NULLS_DEFAULT\x10\x01\x12\x16\x0A\x12SORTBY_NULLS_FIRST\x10\x02\x12\x15\x0A\x11SORTBY_NULLS_LAST\x10\x03*~\x0A\x0DSetQuantifier\x12\x1C\x0A\x18SET_QUANTIFIER_UNDEFINED\x10\x00\x12\x1A\x0A\x16SET_QUANTIFIER_DEFAULT\x10\x01\x12\x16\x0A\x12SET_QUANTIFIER_ALL\x10\x02\x12\x1B\x0A\x17SET_QUANTIFIER_DISTINCT\x10\x03*\xB6\x02\x0A\x0BA_Expr_Kind\x12\x19\x0A\x15A_EXPR_KIND_UNDEFINED\x10\x00\x12\x0C\x0A\x08AEXPR_OP\x10\x01\x12\x10\x0A\x0CAEXPR_OP_ANY\x10\x02\x12\x10\x0A\x0CAEXPR_OP_ALL\x10\x03\x12\x12\x0A\x0EAEXPR_DISTINCT\x10\x04\x12\x16\x0A\x12AEXPR_NOT_DISTINCT\x10\x05\x12\x10\x0A\x0CAEXPR_NULLIF\x10\x06\x12\x0C\x0A\x08AEXPR_IN\x10\x07\x12\x0E\x0A\x0AAEXPR_LIKE\x10\x08\x12\x0F\x0A\x0BAEXPR_ILIKE\x10\x09\x12\x11\x0A\x0DAEXPR_SIMILAR\x10\x0A\x12\x11\x0A\x0DAEXPR_BETWEEN\x10\x0B\x12\x15\x0A\x11AEXPR_NOT_BETWEEN\x10\x0C\x12\x15\x0A\x11AEXPR_BETWEEN_SYM\x10\x0D\x12\x19\x0A\x15AEXPR_NOT_BETWEEN_SYM\x10\x0E*\xA8\x01\x0A\x0CRoleSpecType\x12\x1C\x0A\x18ROLE_SPEC_TYPE_UNDEFINED\x10\x00\x12\x14\x0A\x10ROLESPEC_CSTRING\x10\x01\x12\x19\x0A\x15ROLESPEC_CURRENT_ROLE\x10\x02\x12\x19\x0A\x15ROLESPEC_CURRENT_USER\x10\x03\x12\x19\x0A\x15ROLESPEC_SESSION_USER\x10\x04\x12\x13\x0A\x0FROLESPEC_PUBLIC\x10\x05*\xF4\x02\x0A\x0FTableLikeOption\x12\x1F\x0A\x1BTABLE_LIKE_OPTION_UNDEFINED\x10\x00\x12\x1E\x0A\x1ACREATE_TABLE_LIKE_COMMENTS\x10\x01\x12!\x0A\x1DCREATE_TABLE_LIKE_COMPRESSION\x10\x02\x12!\x0A\x1DCREATE_TABLE_LIKE_CONSTRAINTS\x10\x03\x12\x1E\x0A\x1ACREATE_TABLE_LIKE_DEFAULTS\x10\x04\x12\x1F\x0A\x1BCREATE_TABLE_LIKE_GENERATED\x10\x05\x12\x1E\x0A\x1ACREATE_TABLE_LIKE_IDENTITY\x10\x06\x12\x1D\x0A\x19CREATE_TABLE_LIKE_INDEXES\x10\x07\x12 \x0A\x1CCREATE_TABLE_LIKE_STATISTICS\x10\x08\x12\x1D\x0A\x19CREATE_TABLE_LIKE_STORAGE\x10\x09\x12\x19\x0A\x15CREATE_TABLE_LIKE_ALL\x10\x0A*v\x0A\x0DDefElemAction\x12\x1D\x0A\x19DEF_ELEM_ACTION_UNDEFINED\x10\x00\x12\x12\x0A\x0EDEFELEM_UNSPEC\x10\x01\x12\x0F\x0A\x0BDEFELEM_SET\x10\x02\x12\x0F\x0A\x0BDEFELEM_ADD\x10\x03\x12\x10\x0A\x0CDEFELEM_DROP\x10\x04*\x8D\x01\x0A\x11PartitionStrategy\x12 \x0A\x1CPARTITION_STRATEGY_UNDEFINED\x10\x00\x12\x1B\x0A\x17PARTITION_STRATEGY_LIST\x10\x01\x12\x1C\x0A\x18PARTITION_STRATEGY_RANGE\x10\x02\x12\x1B\x0A\x17PARTITION_STRATEGY_HASH\x10\x03*\xAC\x01\x0A\x17PartitionRangeDatumKind\x12(\x0A\$PARTITION_RANGE_DATUM_KIND_UNDEFINED\x10\x00\x12\"\x0A\x1EPARTITION_RANGE_DATUM_MINVALUE\x10\x01\x12\x1F\x0A\x1BPARTITION_RANGE_DATUM_VALUE\x10\x02\x12\"\x0A\x1EPARTITION_RANGE_DATUM_MAXVALUE\x10\x03*\xBD\x01\x0A\x07RTEKind\x12\x15\x0A\x11RTEKIND_UNDEFINED\x10\x00\x12\x10\x0A\x0CRTE_RELATION\x10\x01\x12\x10\x0A\x0CRTE_SUBQUERY\x10\x02\x12\x0C\x0A\x08RTE_JOIN\x10\x03\x12\x10\x0A\x0CRTE_FUNCTION\x10\x04\x12\x11\x0A\x0DRTE_TABLEFUNC\x10\x05\x12\x0E\x0A\x0ARTE_VALUES\x10\x06\x12\x0B\x0A\x07RTE_CTE\x10\x07\x12\x17\x0A\x13RTE_NAMEDTUPLESTORE\x10\x08\x12\x0E\x0A\x0ARTE_RESULT\x10\x09*\xC4\x01\x0A\x07WCOKind\x12\x15\x0A\x11WCOKIND_UNDEFINED\x10\x00\x12\x12\x0A\x0EWCO_VIEW_CHECK\x10\x01\x12\x18\x0A\x14WCO_RLS_INSERT_CHECK\x10\x02\x12\x18\x0A\x14WCO_RLS_UPDATE_CHECK\x10\x03\x12\x1A\x0A\x16WCO_RLS_CONFLICT_CHECK\x10\x04\x12\x1E\x0A\x1AWCO_RLS_MERGE_UPDATE_CHECK\x10\x05\x12\x1E\x0A\x1AWCO_RLS_MERGE_DELETE_CHECK\x10\x06*\xAA\x01\x0A\x0FGroupingSetKind\x12\x1F\x0A\x1BGROUPING_SET_KIND_UNDEFINED\x10\x00\x12\x16\x0A\x12GROUPING_SET_EMPTY\x10\x01\x12\x17\x0A\x13GROUPING_SET_SIMPLE\x10\x02\x12\x17\x0A\x13GROUPING_SET_ROLLUP\x10\x03\x12\x15\x0A\x11GROUPING_SET_CUBE\x10\x04\x12\x15\x0A\x11GROUPING_SET_SETS\x10\x05*|\x0A\x0ECTEMaterialize\x12\x1C\x0A\x18CTEMATERIALIZE_UNDEFINED\x10\x00\x12\x19\x0A\x15CTEMaterializeDefault\x10\x01\x12\x18\x0A\x14CTEMaterializeAlways\x10\x02\x12\x17\x0A\x13CTEMaterializeNever\x10\x03*e\x0A\x0AJsonQuotes\x12\x19\x0A\x15JSON_QUOTES_UNDEFINED\x10\x00\x12\x14\x0A\x10JS_QUOTES_UNSPEC\x10\x01\x12\x12\x0A\x0EJS_QUOTES_KEEP\x10\x02\x12\x12\x0A\x0EJS_QUOTES_OMIT\x10\x03*\x97\x01\x0A\x13JsonTableColumnType\x12\$\x0A JSON_TABLE_COLUMN_TYPE_UNDEFINED\x10\x00\x12\x16\x0A\x12JTC_FOR_ORDINALITY\x10\x01\x12\x0F\x0A\x0BJTC_REGULAR\x10\x02\x12\x0E\x0A\x0AJTC_EXISTS\x10\x03\x12\x11\x0A\x0DJTC_FORMATTED\x10\x04\x12\x0E\x0A\x0AJTC_NESTED\x10\x05*s\x0A\x0CSetOperation\x12\x1B\x0A\x17SET_OPERATION_UNDEFINED\x10\x00\x12\x0E\x0A\x0ASETOP_NONE\x10\x01\x12\x0F\x0A\x0BSETOP_UNION\x10\x02\x12\x13\x0A\x0FSETOP_INTERSECT\x10\x03\x12\x10\x0A\x0CSETOP_EXCEPT\x10\x04*\x99\x09\x0A\x0AObjectType\x12\x19\x0A\x15OBJECT_TYPE_UNDEFINED\x10\x00\x12\x18\x0A\x14OBJECT_ACCESS_METHOD\x10\x01\x12\x14\x0A\x10OBJECT_AGGREGATE\x10\x02\x12\x0F\x0A\x0BOBJECT_AMOP\x10\x03\x12\x11\x0A\x0DOBJECT_AMPROC\x10\x04\x12\x14\x0A\x10OBJECT_ATTRIBUTE\x10\x05\x12\x0F\x0A\x0BOBJECT_CAST\x10\x06\x12\x11\x0A\x0DOBJECT_COLUMN\x10\x07\x12\x14\x0A\x10OBJECT_COLLATION\x10\x08\x12\x15\x0A\x11OBJECT_CONVERSION\x10\x09\x12\x13\x0A\x0FOBJECT_DATABASE\x10\x0A\x12\x12\x0A\x0EOBJECT_DEFAULT\x10\x0B\x12\x11\x0A\x0DOBJECT_DEFACL\x10\x0C\x12\x11\x0A\x0DOBJECT_DOMAIN\x10\x0D\x12\x18\x0A\x14OBJECT_DOMCONSTRAINT\x10\x0E\x12\x18\x0A\x14OBJECT_EVENT_TRIGGER\x10\x0F\x12\x14\x0A\x10OBJECT_EXTENSION\x10\x10\x12\x0E\x0A\x0AOBJECT_FDW\x10\x11\x12\x19\x0A\x15OBJECT_FOREIGN_SERVER\x10\x12\x12\x18\x0A\x14OBJECT_FOREIGN_TABLE\x10\x13\x12\x13\x0A\x0FOBJECT_FUNCTION\x10\x14\x12\x10\x0A\x0COBJECT_INDEX\x10\x15\x12\x13\x0A\x0FOBJECT_LANGUAGE\x10\x16\x12\x16\x0A\x12OBJECT_LARGEOBJECT\x10\x17\x12\x12\x0A\x0EOBJECT_MATVIEW\x10\x18\x12\x12\x0A\x0EOBJECT_OPCLASS\x10\x19\x12\x13\x0A\x0FOBJECT_OPERATOR\x10\x1A\x12\x13\x0A\x0FOBJECT_OPFAMILY\x10\x1B\x12\x18\x0A\x14OBJECT_PARAMETER_ACL\x10\x1C\x12\x11\x0A\x0DOBJECT_POLICY\x10\x1D\x12\x14\x0A\x10OBJECT_PROCEDURE\x10\x1E\x12\x16\x0A\x12OBJECT_PUBLICATION\x10\x1F\x12 \x0A\x1COBJECT_PUBLICATION_NAMESPACE\x10 \x12\x1A\x0A\x16OBJECT_PUBLICATION_REL\x10!\x12\x0F\x0A\x0BOBJECT_ROLE\x10\"\x12\x12\x0A\x0EOBJECT_ROUTINE\x10#\x12\x0F\x0A\x0BOBJECT_RULE\x10\$\x12\x11\x0A\x0DOBJECT_SCHEMA\x10%\x12\x13\x0A\x0FOBJECT_SEQUENCE\x10&\x12\x17\x0A\x13OBJECT_SUBSCRIPTION\x10'\x12\x18\x0A\x14OBJECT_STATISTIC_EXT\x10(\x12\x18\x0A\x14OBJECT_TABCONSTRAINT\x10)\x12\x10\x0A\x0COBJECT_TABLE\x10*\x12\x15\x0A\x11OBJECT_TABLESPACE\x10+\x12\x14\x0A\x10OBJECT_TRANSFORM\x10,\x12\x12\x0A\x0EOBJECT_TRIGGER\x10-\x12\x1A\x0A\x16OBJECT_TSCONFIGURATION\x10.\x12\x17\x0A\x13OBJECT_TSDICTIONARY\x10/\x12\x13\x0A\x0FOBJECT_TSPARSER\x100\x12\x15\x0A\x11OBJECT_TSTEMPLATE\x101\x12\x0F\x0A\x0BOBJECT_TYPE\x102\x12\x17\x0A\x13OBJECT_USER_MAPPING\x103\x12\x0F\x0A\x0BOBJECT_VIEW\x104*P\x0A\x0CDropBehavior\x12\x1B\x0A\x17DROP_BEHAVIOR_UNDEFINED\x10\x00\x12\x11\x0A\x0DDROP_RESTRICT\x10\x01\x12\x10\x0A\x0CDROP_CASCADE\x10\x02*\x8C\x0C\x0A\x0EAlterTableType\x12\x1E\x0A\x1AALTER_TABLE_TYPE_UNDEFINED\x10\x00\x12\x10\x0A\x0CAT_AddColumn\x10\x01\x12\x16\x0A\x12AT_AddColumnToView\x10\x02\x12\x14\x0A\x10AT_ColumnDefault\x10\x03\x12\x1A\x0A\x16AT_CookedColumnDefault\x10\x04\x12\x12\x0A\x0EAT_DropNotNull\x10\x05\x12\x11\x0A\x0DAT_SetNotNull\x10\x06\x12\x14\x0A\x10AT_SetExpression\x10\x07\x12\x15\x0A\x11AT_DropExpression\x10\x08\x12\x13\x0A\x0FAT_CheckNotNull\x10\x09\x12\x14\x0A\x10AT_SetStatistics\x10\x0A\x12\x11\x0A\x0DAT_SetOptions\x10\x0B\x12\x13\x0A\x0FAT_ResetOptions\x10\x0C\x12\x11\x0A\x0DAT_SetStorage\x10\x0D\x12\x15\x0A\x11AT_SetCompression\x10\x0E\x12\x11\x0A\x0DAT_DropColumn\x10\x0F\x12\x0F\x0A\x0BAT_AddIndex\x10\x10\x12\x11\x0A\x0DAT_ReAddIndex\x10\x11\x12\x14\x0A\x10AT_AddConstraint\x10\x12\x12\x16\x0A\x12AT_ReAddConstraint\x10\x13\x12\x1C\x0A\x18AT_ReAddDomainConstraint\x10\x14\x12\x16\x0A\x12AT_AlterConstraint\x10\x15\x12\x19\x0A\x15AT_ValidateConstraint\x10\x16\x12\x19\x0A\x15AT_AddIndexConstraint\x10\x17\x12\x15\x0A\x11AT_DropConstraint\x10\x18\x12\x13\x0A\x0FAT_ReAddComment\x10\x19\x12\x16\x0A\x12AT_AlterColumnType\x10\x1A\x12 \x0A\x1CAT_AlterColumnGenericOptions\x10\x1B\x12\x12\x0A\x0EAT_ChangeOwner\x10\x1C\x12\x10\x0A\x0CAT_ClusterOn\x10\x1D\x12\x12\x0A\x0EAT_DropCluster\x10\x1E\x12\x10\x0A\x0CAT_SetLogged\x10\x1F\x12\x12\x0A\x0EAT_SetUnLogged\x10 \x12\x0F\x0A\x0BAT_DropOids\x10!\x12\x16\x0A\x12AT_SetAccessMethod\x10\"\x12\x14\x0A\x10AT_SetTableSpace\x10#\x12\x14\x0A\x10AT_SetRelOptions\x10\$\x12\x16\x0A\x12AT_ResetRelOptions\x10%\x12\x18\x0A\x14AT_ReplaceRelOptions\x10&\x12\x11\x0A\x0DAT_EnableTrig\x10'\x12\x17\x0A\x13AT_EnableAlwaysTrig\x10(\x12\x18\x0A\x14AT_EnableReplicaTrig\x10)\x12\x12\x0A\x0EAT_DisableTrig\x10*\x12\x14\x0A\x10AT_EnableTrigAll\x10+\x12\x15\x0A\x11AT_DisableTrigAll\x10,\x12\x15\x0A\x11AT_EnableTrigUser\x10-\x12\x16\x0A\x12AT_DisableTrigUser\x10.\x12\x11\x0A\x0DAT_EnableRule\x10/\x12\x17\x0A\x13AT_EnableAlwaysRule\x100\x12\x18\x0A\x14AT_EnableReplicaRule\x101\x12\x12\x0A\x0EAT_DisableRule\x102\x12\x11\x0A\x0DAT_AddInherit\x103\x12\x12\x0A\x0EAT_DropInherit\x104\x12\x0C\x0A\x08AT_AddOf\x105\x12\x0D\x0A\x09AT_DropOf\x106\x12\x16\x0A\x12AT_ReplicaIdentity\x107\x12\x18\x0A\x14AT_EnableRowSecurity\x108\x12\x19\x0A\x15AT_DisableRowSecurity\x109\x12\x17\x0A\x13AT_ForceRowSecurity\x10:\x12\x19\x0A\x15AT_NoForceRowSecurity\x10;\x12\x15\x0A\x11AT_GenericOptions\x10<\x12\x16\x0A\x12AT_AttachPartition\x10=\x12\x16\x0A\x12AT_DetachPartition\x10>\x12\x1E\x0A\x1AAT_DetachPartitionFinalize\x10?\x12\x12\x0A\x0EAT_AddIdentity\x10@\x12\x12\x0A\x0EAT_SetIdentity\x10A\x12\x13\x0A\x0FAT_DropIdentity\x10B\x12\x16\x0A\x12AT_ReAddStatistics\x10C*\x80\x01\x0A\x0FGrantTargetType\x12\x1F\x0A\x1BGRANT_TARGET_TYPE_UNDEFINED\x10\x00\x12\x15\x0A\x11ACL_TARGET_OBJECT\x10\x01\x12\x1C\x0A\x18ACL_TARGET_ALL_IN_SCHEMA\x10\x02\x12\x17\x0A\x13ACL_TARGET_DEFAULTS\x10\x03*\xA4\x01\x0A\x0FVariableSetKind\x12\x1F\x0A\x1BVARIABLE_SET_KIND_UNDEFINED\x10\x00\x12\x11\x0A\x0DVAR_SET_VALUE\x10\x01\x12\x13\x0A\x0FVAR_SET_DEFAULT\x10\x02\x12\x13\x0A\x0FVAR_SET_CURRENT\x10\x03\x12\x11\x0A\x0DVAR_SET_MULTI\x10\x04\x12\x0D\x0A\x09VAR_RESET\x10\x05\x12\x11\x0A\x0DVAR_RESET_ALL\x10\x06*\xDF\x02\x0A\x0AConstrType\x12\x19\x0A\x15CONSTR_TYPE_UNDEFINED\x10\x00\x12\x0F\x0A\x0BCONSTR_NULL\x10\x01\x12\x12\x0A\x0ECONSTR_NOTNULL\x10\x02\x12\x12\x0A\x0ECONSTR_DEFAULT\x10\x03\x12\x13\x0A\x0FCONSTR_IDENTITY\x10\x04\x12\x14\x0A\x10CONSTR_GENERATED\x10\x05\x12\x10\x0A\x0CCONSTR_CHECK\x10\x06\x12\x12\x0A\x0ECONSTR_PRIMARY\x10\x07\x12\x11\x0A\x0DCONSTR_UNIQUE\x10\x08\x12\x14\x0A\x10CONSTR_EXCLUSION\x10\x09\x12\x12\x0A\x0ECONSTR_FOREIGN\x10\x0A\x12\x1A\x0A\x16CONSTR_ATTR_DEFERRABLE\x10\x0B\x12\x1E\x0A\x1ACONSTR_ATTR_NOT_DEFERRABLE\x10\x0C\x12\x18\x0A\x14CONSTR_ATTR_DEFERRED\x10\x0D\x12\x19\x0A\x15CONSTR_ATTR_IMMEDIATE\x10\x0E*\x9C\x01\x0A\x17ImportForeignSchemaType\x12(\x0A\$IMPORT_FOREIGN_SCHEMA_TYPE_UNDEFINED\x10\x00\x12\x19\x0A\x15FDW_IMPORT_SCHEMA_ALL\x10\x01\x12\x1E\x0A\x1AFDW_IMPORT_SCHEMA_LIMIT_TO\x10\x02\x12\x1C\x0A\x18FDW_IMPORT_SCHEMA_EXCEPT\x10\x03*f\x0A\x0CRoleStmtType\x12\x1C\x0A\x18ROLE_STMT_TYPE_UNDEFINED\x10\x00\x12\x11\x0A\x0DROLESTMT_ROLE\x10\x01\x12\x11\x0A\x0DROLESTMT_USER\x10\x02\x12\x12\x0A\x0EROLESTMT_GROUP\x10\x03*~\x0A\x0EFetchDirection\x12\x1D\x0A\x19FETCH_DIRECTION_UNDEFINED\x10\x00\x12\x11\x0A\x0DFETCH_FORWARD\x10\x01\x12\x12\x0A\x0EFETCH_BACKWARD\x10\x02\x12\x12\x0A\x0EFETCH_ABSOLUTE\x10\x03\x12\x12\x0A\x0EFETCH_RELATIVE\x10\x04*\xC2\x01\x0A\x15FunctionParameterMode\x12%\x0A!FUNCTION_PARAMETER_MODE_UNDEFINED\x10\x00\x12\x11\x0A\x0DFUNC_PARAM_IN\x10\x01\x12\x12\x0A\x0EFUNC_PARAM_OUT\x10\x02\x12\x14\x0A\x10FUNC_PARAM_INOUT\x10\x03\x12\x17\x0A\x13FUNC_PARAM_VARIADIC\x10\x04\x12\x14\x0A\x10FUNC_PARAM_TABLE\x10\x05\x12\x16\x0A\x12FUNC_PARAM_DEFAULT\x10\x06*\xBE\x02\x0A\x13TransactionStmtKind\x12#\x0A\x1FTRANSACTION_STMT_KIND_UNDEFINED\x10\x00\x12\x14\x0A\x10TRANS_STMT_BEGIN\x10\x01\x12\x14\x0A\x10TRANS_STMT_START\x10\x02\x12\x15\x0A\x11TRANS_STMT_COMMIT\x10\x03\x12\x17\x0A\x13TRANS_STMT_ROLLBACK\x10\x04\x12\x18\x0A\x14TRANS_STMT_SAVEPOINT\x10\x05\x12\x16\x0A\x12TRANS_STMT_RELEASE\x10\x06\x12\x1A\x0A\x16TRANS_STMT_ROLLBACK_TO\x10\x07\x12\x16\x0A\x12TRANS_STMT_PREPARE\x10\x08\x12\x1E\x0A\x1ATRANS_STMT_COMMIT_PREPARED\x10\x09\x12 \x0A\x1CTRANS_STMT_ROLLBACK_PREPARED\x10\x0A*z\x0A\x0FViewCheckOption\x12\x1F\x0A\x1BVIEW_CHECK_OPTION_UNDEFINED\x10\x00\x12\x13\x0A\x0FNO_CHECK_OPTION\x10\x01\x12\x16\x0A\x12LOCAL_CHECK_OPTION\x10\x02\x12\x19\x0A\x15CASCADED_CHECK_OPTION\x10\x03*v\x0A\x0BDiscardMode\x12\x1A\x0A\x16DISCARD_MODE_UNDEFINED\x10\x00\x12\x0F\x0A\x0BDISCARD_ALL\x10\x01\x12\x11\x0A\x0DDISCARD_PLANS\x10\x02\x12\x15\x0A\x11DISCARD_SEQUENCES\x10\x03\x12\x10\x0A\x0CDISCARD_TEMP\x10\x04*\xBD\x01\x0A\x11ReindexObjectType\x12!\x0A\x1DREINDEX_OBJECT_TYPE_UNDEFINED\x10\x00\x12\x18\x0A\x14REINDEX_OBJECT_INDEX\x10\x01\x12\x18\x0A\x14REINDEX_OBJECT_TABLE\x10\x02\x12\x19\x0A\x15REINDEX_OBJECT_SCHEMA\x10\x03\x12\x19\x0A\x15REINDEX_OBJECT_SYSTEM\x10\x04\x12\x1B\x0A\x17REINDEX_OBJECT_DATABASE\x10\x05*\xEF\x01\x0A\x11AlterTSConfigType\x12!\x0A\x1DALTER_TSCONFIG_TYPE_UNDEFINED\x10\x00\x12\x1E\x0A\x1AALTER_TSCONFIG_ADD_MAPPING\x10\x01\x12*\x0A&ALTER_TSCONFIG_ALTER_MAPPING_FOR_TOKEN\x10\x02\x12\x1F\x0A\x1BALTER_TSCONFIG_REPLACE_DICT\x10\x03\x12)\x0A%ALTER_TSCONFIG_REPLACE_DICT_FOR_TOKEN\x10\x04\x12\x1F\x0A\x1BALTER_TSCONFIG_DROP_MAPPING\x10\x05*\xCA\x01\x0A\x16PublicationObjSpecType\x12'\x0A#PUBLICATION_OBJ_SPEC_TYPE_UNDEFINED\x10\x00\x12\x18\x0A\x14PUBLICATIONOBJ_TABLE\x10\x01\x12#\x0A\x1FPUBLICATIONOBJ_TABLES_IN_SCHEMA\x10\x02\x12'\x0A#PUBLICATIONOBJ_TABLES_IN_CUR_SCHEMA\x10\x03\x12\x1F\x0A\x1BPUBLICATIONOBJ_CONTINUATION\x10\x04*z\x0A\x16AlterPublicationAction\x12&\x0A\"ALTER_PUBLICATION_ACTION_UNDEFINED\x10\x00\x12\x11\x0A\x0DAP_AddObjects\x10\x01\x12\x12\x0A\x0EAP_DropObjects\x10\x02\x12\x11\x0A\x0DAP_SetObjects\x10\x03*\xD7\x02\x0A\x15AlterSubscriptionType\x12%\x0A!ALTER_SUBSCRIPTION_TYPE_UNDEFINED\x10\x00\x12\x1E\x0A\x1AALTER_SUBSCRIPTION_OPTIONS\x10\x01\x12!\x0A\x1DALTER_SUBSCRIPTION_CONNECTION\x10\x02\x12&\x0A\"ALTER_SUBSCRIPTION_SET_PUBLICATION\x10\x03\x12&\x0A\"ALTER_SUBSCRIPTION_ADD_PUBLICATION\x10\x04\x12'\x0A#ALTER_SUBSCRIPTION_DROP_PUBLICATION\x10\x05\x12\x1E\x0A\x1AALTER_SUBSCRIPTION_REFRESH\x10\x06\x12\x1E\x0A\x1AALTER_SUBSCRIPTION_ENABLED\x10\x07\x12\x1B\x0A\x17ALTER_SUBSCRIPTION_SKIP\x10\x08*\x7F\x0A\x0EOverridingKind\x12\x1D\x0A\x19OVERRIDING_KIND_UNDEFINED\x10\x00\x12\x16\x0A\x12OVERRIDING_NOT_SET\x10\x01\x12\x19\x0A\x15OVERRIDING_USER_VALUE\x10\x02\x12\x1B\x0A\x17OVERRIDING_SYSTEM_VALUE\x10\x03*\x8C\x01\x0A\x0EOnCommitAction\x12\x1E\x0A\x1AON_COMMIT_ACTION_UNDEFINED\x10\x00\x12\x11\x0A\x0DONCOMMIT_NOOP\x10\x01\x12\x1A\x0A\x16ONCOMMIT_PRESERVE_ROWS\x10\x02\x12\x18\x0A\x14ONCOMMIT_DELETE_ROWS\x10\x03\x12\x11\x0A\x0DONCOMMIT_DROP\x10\x04*T\x0A\x0DTableFuncType\x12\x1D\x0A\x19TABLE_FUNC_TYPE_UNDEFINED\x10\x00\x12\x10\x0A\x0CTFT_XMLTABLE\x10\x01\x12\x12\x0A\x0ETFT_JSON_TABLE\x10\x02*o\x0A\x09ParamKind\x12\x18\x0A\x14PARAM_KIND_UNDEFINED\x10\x00\x12\x10\x0A\x0CPARAM_EXTERN\x10\x01\x12\x0E\x0A\x0APARAM_EXEC\x10\x02\x12\x11\x0A\x0DPARAM_SUBLINK\x10\x03\x12\x13\x0A\x0FPARAM_MULTIEXPR\x10\x04*\x8E\x01\x0A\x0FCoercionContext\x12\x1E\x0A\x1ACOERCION_CONTEXT_UNDEFINED\x10\x00\x12\x15\x0A\x11COERCION_IMPLICIT\x10\x01\x12\x17\x0A\x13COERCION_ASSIGNMENT\x10\x02\x12\x14\x0A\x10COERCION_PLPGSQL\x10\x03\x12\x15\x0A\x11COERCION_EXPLICIT\x10\x04*\x90\x01\x0A\x0CCoercionForm\x12\x1B\x0A\x17COERCION_FORM_UNDEFINED\x10\x00\x12\x18\x0A\x14COERCE_EXPLICIT_CALL\x10\x01\x12\x18\x0A\x14COERCE_EXPLICIT_CAST\x10\x02\x12\x18\x0A\x14COERCE_IMPLICIT_CAST\x10\x03\x12\x15\x0A\x11COERCE_SQL_SYNTAX\x10\x04*U\x0A\x0CBoolExprType\x12\x1C\x0A\x18BOOL_EXPR_TYPE_UNDEFINED\x10\x00\x12\x0C\x0A\x08AND_EXPR\x10\x01\x12\x0B\x0A\x07OR_EXPR\x10\x02\x12\x0C\x0A\x08NOT_EXPR\x10\x03*\xC5\x01\x0A\x0BSubLinkType\x12\x1B\x0A\x17SUB_LINK_TYPE_UNDEFINED\x10\x00\x12\x12\x0A\x0EEXISTS_SUBLINK\x10\x01\x12\x0F\x0A\x0BALL_SUBLINK\x10\x02\x12\x0F\x0A\x0BANY_SUBLINK\x10\x03\x12\x16\x0A\x12ROWCOMPARE_SUBLINK\x10\x04\x12\x10\x0A\x0CEXPR_SUBLINK\x10\x05\x12\x15\x0A\x11MULTIEXPR_SUBLINK\x10\x06\x12\x11\x0A\x0DARRAY_SUBLINK\x10\x07\x12\x0F\x0A\x0BCTE_SUBLINK\x10\x08*\xA2\x01\x0A\x0ERowCompareType\x12\x1E\x0A\x1AROW_COMPARE_TYPE_UNDEFINED\x10\x00\x12\x11\x0A\x0DROWCOMPARE_LT\x10\x01\x12\x11\x0A\x0DROWCOMPARE_LE\x10\x02\x12\x11\x0A\x0DROWCOMPARE_EQ\x10\x03\x12\x11\x0A\x0DROWCOMPARE_GE\x10\x04\x12\x11\x0A\x0DROWCOMPARE_GT\x10\x05\x12\x11\x0A\x0DROWCOMPARE_NE\x10\x06*C\x0A\x08MinMaxOp\x12\x18\x0A\x14MIN_MAX_OP_UNDEFINED\x10\x00\x12\x0F\x0A\x0BIS_GREATEST\x10\x01\x12\x0C\x0A\x08IS_LEAST\x10\x02*\xAD\x03\x0A\x12SQLValueFunctionOp\x12\"\x0A\x1ESQLVALUE_FUNCTION_OP_UNDEFINED\x10\x00\x12\x16\x0A\x12SVFOP_CURRENT_DATE\x10\x01\x12\x16\x0A\x12SVFOP_CURRENT_TIME\x10\x02\x12\x18\x0A\x14SVFOP_CURRENT_TIME_N\x10\x03\x12\x1B\x0A\x17SVFOP_CURRENT_TIMESTAMP\x10\x04\x12\x1D\x0A\x19SVFOP_CURRENT_TIMESTAMP_N\x10\x05\x12\x13\x0A\x0FSVFOP_LOCALTIME\x10\x06\x12\x15\x0A\x11SVFOP_LOCALTIME_N\x10\x07\x12\x18\x0A\x14SVFOP_LOCALTIMESTAMP\x10\x08\x12\x1A\x0A\x16SVFOP_LOCALTIMESTAMP_N\x10\x09\x12\x16\x0A\x12SVFOP_CURRENT_ROLE\x10\x0A\x12\x16\x0A\x12SVFOP_CURRENT_USER\x10\x0B\x12\x0E\x0A\x0ASVFOP_USER\x10\x0C\x12\x16\x0A\x12SVFOP_SESSION_USER\x10\x0D\x12\x19\x0A\x15SVFOP_CURRENT_CATALOG\x10\x0E\x12\x18\x0A\x14SVFOP_CURRENT_SCHEMA\x10\x0F*\xB2\x01\x0A\x09XmlExprOp\x12\x19\x0A\x15XML_EXPR_OP_UNDEFINED\x10\x00\x12\x10\x0A\x0CIS_XMLCONCAT\x10\x01\x12\x11\x0A\x0DIS_XMLELEMENT\x10\x02\x12\x10\x0A\x0CIS_XMLFOREST\x10\x03\x12\x0F\x0A\x0BIS_XMLPARSE\x10\x04\x12\x0C\x0A\x08IS_XMLPI\x10\x05\x12\x0E\x0A\x0AIS_XMLROOT\x10\x06\x12\x13\x0A\x0FIS_XMLSERIALIZE\x10\x07\x12\x0F\x0A\x0BIS_DOCUMENT\x10\x08*]\x0A\x0DXmlOptionType\x12\x1D\x0A\x19XML_OPTION_TYPE_UNDEFINED\x10\x00\x12\x16\x0A\x12XMLOPTION_DOCUMENT\x10\x01\x12\x15\x0A\x11XMLOPTION_CONTENT\x10\x02*t\x0A\x0CJsonEncoding\x12\x1B\x0A\x17JSON_ENCODING_UNDEFINED\x10\x00\x12\x12\x0A\x0EJS_ENC_DEFAULT\x10\x01\x12\x0F\x0A\x0BJS_ENC_UTF8\x10\x02\x12\x10\x0A\x0CJS_ENC_UTF16\x10\x03\x12\x10\x0A\x0CJS_ENC_UTF32\x10\x04*p\x0A\x0EJsonFormatType\x12\x1E\x0A\x1AJSON_FORMAT_TYPE_UNDEFINED\x10\x00\x12\x15\x0A\x11JS_FORMAT_DEFAULT\x10\x01\x12\x12\x0A\x0EJS_FORMAT_JSON\x10\x02\x12\x13\x0A\x0FJS_FORMAT_JSONB\x10\x03*\xE8\x01\x0A\x13JsonConstructorType\x12#\x0A\x1FJSON_CONSTRUCTOR_TYPE_UNDEFINED\x10\x00\x12\x16\x0A\x12JSCTOR_JSON_OBJECT\x10\x01\x12\x15\x0A\x11JSCTOR_JSON_ARRAY\x10\x02\x12\x19\x0A\x15JSCTOR_JSON_OBJECTAGG\x10\x03\x12\x18\x0A\x14JSCTOR_JSON_ARRAYAGG\x10\x04\x12\x15\x0A\x11JSCTOR_JSON_PARSE\x10\x05\x12\x16\x0A\x12JSCTOR_JSON_SCALAR\x10\x06\x12\x19\x0A\x15JSCTOR_JSON_SERIALIZE\x10\x07*z\x0A\x0DJsonValueType\x12\x1D\x0A\x19JSON_VALUE_TYPE_UNDEFINED\x10\x00\x12\x0F\x0A\x0BJS_TYPE_ANY\x10\x01\x12\x12\x0A\x0EJS_TYPE_OBJECT\x10\x02\x12\x11\x0A\x0DJS_TYPE_ARRAY\x10\x03\x12\x12\x0A\x0EJS_TYPE_SCALAR\x10\x04*s\x0A\x0BJsonWrapper\x12\x1A\x0A\x16JSON_WRAPPER_UNDEFINED\x10\x00\x12\x0E\x0A\x0AJSW_UNSPEC\x10\x01\x12\x0C\x0A\x08JSW_NONE\x10\x02\x12\x13\x0A\x0FJSW_CONDITIONAL\x10\x03\x12\x15\x0A\x11JSW_UNCONDITIONAL\x10\x04*\xA4\x02\x0A\x10JsonBehaviorType\x12 \x0A\x1CJSON_BEHAVIOR_TYPE_UNDEFINED\x10\x00\x12\x16\x0A\x12JSON_BEHAVIOR_NULL\x10\x01\x12\x17\x0A\x13JSON_BEHAVIOR_ERROR\x10\x02\x12\x17\x0A\x13JSON_BEHAVIOR_EMPTY\x10\x03\x12\x16\x0A\x12JSON_BEHAVIOR_TRUE\x10\x04\x12\x17\x0A\x13JSON_BEHAVIOR_FALSE\x10\x05\x12\x19\x0A\x15JSON_BEHAVIOR_UNKNOWN\x10\x06\x12\x1D\x0A\x19JSON_BEHAVIOR_EMPTY_ARRAY\x10\x07\x12\x1E\x0A\x1AJSON_BEHAVIOR_EMPTY_OBJECT\x10\x08\x12\x19\x0A\x15JSON_BEHAVIOR_DEFAULT\x10\x09*u\x0A\x0AJsonExprOp\x12\x1A\x0A\x16JSON_EXPR_OP_UNDEFINED\x10\x00\x12\x12\x0A\x0EJSON_EXISTS_OP\x10\x01\x12\x11\x0A\x0DJSON_QUERY_OP\x10\x02\x12\x11\x0A\x0DJSON_VALUE_OP\x10\x03\x12\x11\x0A\x0DJSON_TABLE_OP\x10\x04*J\x0A\x0CNullTestType\x12\x1C\x0A\x18NULL_TEST_TYPE_UNDEFINED\x10\x00\x12\x0B\x0A\x07IS_NULL\x10\x01\x12\x0F\x0A\x0BIS_NOT_NULL\x10\x02*\x8E\x01\x0A\x0CBoolTestType\x12\x1C\x0A\x18BOOL_TEST_TYPE_UNDEFINED\x10\x00\x12\x0B\x0A\x07IS_TRUE\x10\x01\x12\x0F\x0A\x0BIS_NOT_TRUE\x10\x02\x12\x0C\x0A\x08IS_FALSE\x10\x03\x12\x10\x0A\x0CIS_NOT_FALSE\x10\x04\x12\x0E\x0A\x0AIS_UNKNOWN\x10\x05\x12\x12\x0A\x0EIS_NOT_UNKNOWN\x10\x06*\x94\x01\x0A\x0EMergeMatchKind\x12\x1E\x0A\x1AMERGE_MATCH_KIND_UNDEFINED\x10\x00\x12\x16\x0A\x12MERGE_WHEN_MATCHED\x10\x01\x12\$\x0A MERGE_WHEN_NOT_MATCHED_BY_SOURCE\x10\x02\x12\$\x0A MERGE_WHEN_NOT_MATCHED_BY_TARGET\x10\x03*\xA3\x01\x0A\x07CmdType\x12\x16\x0A\x12CMD_TYPE_UNDEFINED\x10\x00\x12\x0F\x0A\x0BCMD_UNKNOWN\x10\x01\x12\x0E\x0A\x0ACMD_SELECT\x10\x02\x12\x0E\x0A\x0ACMD_UPDATE\x10\x03\x12\x0E\x0A\x0ACMD_INSERT\x10\x04\x12\x0E\x0A\x0ACMD_DELETE\x10\x05\x12\x0D\x0A\x09CMD_MERGE\x10\x06\x12\x0F\x0A\x0BCMD_UTILITY\x10\x07\x12\x0F\x0A\x0BCMD_NOTHING\x10\x08*\xC2\x01\x0A\x08JoinType\x12\x17\x0A\x13JOIN_TYPE_UNDEFINED\x10\x00\x12\x0E\x0A\x0AJOIN_INNER\x10\x01\x12\x0D\x0A\x09JOIN_LEFT\x10\x02\x12\x0D\x0A\x09JOIN_FULL\x10\x03\x12\x0E\x0A\x0AJOIN_RIGHT\x10\x04\x12\x0D\x0A\x09JOIN_SEMI\x10\x05\x12\x0D\x0A\x09JOIN_ANTI\x10\x06\x12\x13\x0A\x0FJOIN_RIGHT_ANTI\x10\x07\x12\x15\x0A\x11JOIN_UNIQUE_OUTER\x10\x08\x12\x15\x0A\x11JOIN_UNIQUE_INNER\x10\x09*g\x0A\x0BAggStrategy\x12\x1A\x0A\x16AGG_STRATEGY_UNDEFINED\x10\x00\x12\x0D\x0A\x09AGG_PLAIN\x10\x01\x12\x0E\x0A\x0AAGG_SORTED\x10\x02\x12\x0E\x0A\x0AAGG_HASHED\x10\x03\x12\x0D\x0A\x09AGG_MIXED\x10\x04*r\x0A\x08AggSplit\x12\x17\x0A\x13AGG_SPLIT_UNDEFINED\x10\x00\x12\x13\x0A\x0FAGGSPLIT_SIMPLE\x10\x01\x12\x1B\x0A\x17AGGSPLIT_INITIAL_SERIAL\x10\x02\x12\x1B\x0A\x17AGGSPLIT_FINAL_DESERIAL\x10\x03*\x86\x01\x0A\x08SetOpCmd\x12\x18\x0A\x14SET_OP_CMD_UNDEFINED\x10\x00\x12\x16\x0A\x12SETOPCMD_INTERSECT\x10\x01\x12\x1A\x0A\x16SETOPCMD_INTERSECT_ALL\x10\x02\x12\x13\x0A\x0FSETOPCMD_EXCEPT\x10\x03\x12\x17\x0A\x13SETOPCMD_EXCEPT_ALL\x10\x04*R\x0A\x0DSetOpStrategy\x12\x1D\x0A\x19SET_OP_STRATEGY_UNDEFINED\x10\x00\x12\x10\x0A\x0CSETOP_SORTED\x10\x01\x12\x10\x0A\x0CSETOP_HASHED\x10\x02*x\x0A\x10OnConflictAction\x12 \x0A\x1CON_CONFLICT_ACTION_UNDEFINED\x10\x00\x12\x13\x0A\x0FONCONFLICT_NONE\x10\x01\x12\x16\x0A\x12ONCONFLICT_NOTHING\x10\x02\x12\x15\x0A\x11ONCONFLICT_UPDATE\x10\x03*w\x0A\x0BLimitOption\x12\x1A\x0A\x16LIMIT_OPTION_UNDEFINED\x10\x00\x12\x18\x0A\x14LIMIT_OPTION_DEFAULT\x10\x01\x12\x16\x0A\x12LIMIT_OPTION_COUNT\x10\x02\x12\x1A\x0A\x16LIMIT_OPTION_WITH_TIES\x10\x03*\x98\x01\x0A\x12LockClauseStrength\x12\"\x0A\x1ELOCK_CLAUSE_STRENGTH_UNDEFINED\x10\x00\x12\x0C\x0A\x08LCS_NONE\x10\x01\x12\x13\x0A\x0FLCS_FORKEYSHARE\x10\x02\x12\x10\x0A\x0CLCS_FORSHARE\x10\x03\x12\x16\x0A\x12LCS_FORNOKEYUPDATE\x10\x04\x12\x11\x0A\x0DLCS_FORUPDATE\x10\x05*h\x0A\x0ELockWaitPolicy\x12\x1E\x0A\x1ALOCK_WAIT_POLICY_UNDEFINED\x10\x00\x12\x11\x0A\x0DLockWaitBlock\x10\x01\x12\x10\x0A\x0CLockWaitSkip\x10\x02\x12\x11\x0A\x0DLockWaitError\x10\x03*\x8E\x01\x0A\x0DLockTupleMode\x12\x1D\x0A\x19LOCK_TUPLE_MODE_UNDEFINED\x10\x00\x12\x15\x0A\x11LockTupleKeyShare\x10\x01\x12\x12\x0A\x0ELockTupleShare\x10\x02\x12\x1B\x0A\x17LockTupleNoKeyExclusive\x10\x03\x12\x16\x0A\x12LockTupleExclusive\x10\x04*}\x0A\x0BKeywordKind\x12\x0E\x0A\x0ANO_KEYWORD\x10\x00\x12\x16\x0A\x12UNRESERVED_KEYWORD\x10\x01\x12\x14\x0A\x10COL_NAME_KEYWORD\x10\x02\x12\x1A\x0A\x16TYPE_FUNC_NAME_KEYWORD\x10\x03\x12\x14\x0A\x10RESERVED_KEYWORD\x10\x04*\xE8;\x0A\x05Token\x12\x07\x0A\x03NUL\x10\x00\x12\x0C\x0A\x08ASCII_36\x10\$\x12\x0C\x0A\x08ASCII_37\x10%\x12\x0C\x0A\x08ASCII_40\x10(\x12\x0C\x0A\x08ASCII_41\x10)\x12\x0C\x0A\x08ASCII_42\x10*\x12\x0C\x0A\x08ASCII_43\x10+\x12\x0C\x0A\x08ASCII_44\x10,\x12\x0C\x0A\x08ASCII_45\x10-\x12\x0C\x0A\x08ASCII_46\x10.\x12\x0C\x0A\x08ASCII_47\x10/\x12\x0C\x0A\x08ASCII_58\x10:\x12\x0C\x0A\x08ASCII_59\x10;\x12\x0C\x0A\x08ASCII_60\x10<\x12\x0C\x0A\x08ASCII_61\x10=\x12\x0C\x0A\x08ASCII_62\x10>\x12\x0C\x0A\x08ASCII_63\x10?\x12\x0C\x0A\x08ASCII_91\x10[\x12\x0C\x0A\x08ASCII_92\x10\\\x12\x0C\x0A\x08ASCII_93\x10]\x12\x0C\x0A\x08ASCII_94\x10^\x12\x0A\x0A\x05IDENT\x10\x82\x02\x12\x0B\x0A\x06UIDENT\x10\x83\x02\x12\x0B\x0A\x06FCONST\x10\x84\x02\x12\x0B\x0A\x06SCONST\x10\x85\x02\x12\x0C\x0A\x07USCONST\x10\x86\x02\x12\x0B\x0A\x06BCONST\x10\x87\x02\x12\x0B\x0A\x06XCONST\x10\x88\x02\x12\x07\x0A\x02Op\x10\x89\x02\x12\x0B\x0A\x06ICONST\x10\x8A\x02\x12\x0A\x0A\x05PARAM\x10\x8B\x02\x12\x0D\x0A\x08TYPECAST\x10\x8C\x02\x12\x0C\x0A\x07DOT_DOT\x10\x8D\x02\x12\x11\x0A\x0CCOLON_EQUALS\x10\x8E\x02\x12\x13\x0A\x0EEQUALS_GREATER\x10\x8F\x02\x12\x10\x0A\x0BLESS_EQUALS\x10\x90\x02\x12\x13\x0A\x0EGREATER_EQUALS\x10\x91\x02\x12\x0F\x0A\x0ANOT_EQUALS\x10\x92\x02\x12\x10\x0A\x0BSQL_COMMENT\x10\x93\x02\x12\x0E\x0A\x09C_COMMENT\x10\x94\x02\x12\x0C\x0A\x07ABORT_P\x10\x95\x02\x12\x0B\x0A\x06ABSENT\x10\x96\x02\x12\x0F\x0A\x0AABSOLUTE_P\x10\x97\x02\x12\x0B\x0A\x06ACCESS\x10\x98\x02\x12\x0B\x0A\x06ACTION\x10\x99\x02\x12\x0A\x0A\x05ADD_P\x10\x9A\x02\x12\x0A\x0A\x05ADMIN\x10\x9B\x02\x12\x0A\x0A\x05AFTER\x10\x9C\x02\x12\x0E\x0A\x09AGGREGATE\x10\x9D\x02\x12\x08\x0A\x03ALL\x10\x9E\x02\x12\x09\x0A\x04ALSO\x10\x9F\x02\x12\x0A\x0A\x05ALTER\x10\xA0\x02\x12\x0B\x0A\x06ALWAYS\x10\xA1\x02\x12\x0C\x0A\x07ANALYSE\x10\xA2\x02\x12\x0C\x0A\x07ANALYZE\x10\xA3\x02\x12\x08\x0A\x03AND\x10\xA4\x02\x12\x08\x0A\x03ANY\x10\xA5\x02\x12\x0A\x0A\x05ARRAY\x10\xA6\x02\x12\x07\x0A\x02AS\x10\xA7\x02\x12\x08\x0A\x03ASC\x10\xA8\x02\x12\x0F\x0A\x0AASENSITIVE\x10\xA9\x02\x12\x0E\x0A\x09ASSERTION\x10\xAA\x02\x12\x0F\x0A\x0AASSIGNMENT\x10\xAB\x02\x12\x0F\x0A\x0AASYMMETRIC\x10\xAC\x02\x12\x0B\x0A\x06ATOMIC\x10\xAD\x02\x12\x07\x0A\x02AT\x10\xAE\x02\x12\x0B\x0A\x06ATTACH\x10\xAF\x02\x12\x0E\x0A\x09ATTRIBUTE\x10\xB0\x02\x12\x12\x0A\x0DAUTHORIZATION\x10\xB1\x02\x12\x0D\x0A\x08BACKWARD\x10\xB2\x02\x12\x0B\x0A\x06BEFORE\x10\xB3\x02\x12\x0C\x0A\x07BEGIN_P\x10\xB4\x02\x12\x0C\x0A\x07BETWEEN\x10\xB5\x02\x12\x0B\x0A\x06BIGINT\x10\xB6\x02\x12\x0B\x0A\x06BINARY\x10\xB7\x02\x12\x08\x0A\x03BIT\x10\xB8\x02\x12\x0E\x0A\x09BOOLEAN_P\x10\xB9\x02\x12\x09\x0A\x04BOTH\x10\xBA\x02\x12\x0C\x0A\x07BREADTH\x10\xBB\x02\x12\x07\x0A\x02BY\x10\xBC\x02\x12\x0A\x0A\x05CACHE\x10\xBD\x02\x12\x09\x0A\x04CALL\x10\xBE\x02\x12\x0B\x0A\x06CALLED\x10\xBF\x02\x12\x0C\x0A\x07CASCADE\x10\xC0\x02\x12\x0D\x0A\x08CASCADED\x10\xC1\x02\x12\x09\x0A\x04CASE\x10\xC2\x02\x12\x09\x0A\x04CAST\x10\xC3\x02\x12\x0E\x0A\x09CATALOG_P\x10\xC4\x02\x12\x0A\x0A\x05CHAIN\x10\xC5\x02\x12\x0B\x0A\x06CHAR_P\x10\xC6\x02\x12\x0E\x0A\x09CHARACTER\x10\xC7\x02\x12\x14\x0A\x0FCHARACTERISTICS\x10\xC8\x02\x12\x0A\x0A\x05CHECK\x10\xC9\x02\x12\x0F\x0A\x0ACHECKPOINT\x10\xCA\x02\x12\x0A\x0A\x05CLASS\x10\xCB\x02\x12\x0A\x0A\x05CLOSE\x10\xCC\x02\x12\x0C\x0A\x07CLUSTER\x10\xCD\x02\x12\x0D\x0A\x08COALESCE\x10\xCE\x02\x12\x0C\x0A\x07COLLATE\x10\xCF\x02\x12\x0E\x0A\x09COLLATION\x10\xD0\x02\x12\x0B\x0A\x06COLUMN\x10\xD1\x02\x12\x0C\x0A\x07COLUMNS\x10\xD2\x02\x12\x0C\x0A\x07COMMENT\x10\xD3\x02\x12\x0D\x0A\x08COMMENTS\x10\xD4\x02\x12\x0B\x0A\x06COMMIT\x10\xD5\x02\x12\x0E\x0A\x09COMMITTED\x10\xD6\x02\x12\x10\x0A\x0BCOMPRESSION\x10\xD7\x02\x12\x11\x0A\x0CCONCURRENTLY\x10\xD8\x02\x12\x10\x0A\x0BCONDITIONAL\x10\xD9\x02\x12\x12\x0A\x0DCONFIGURATION\x10\xDA\x02\x12\x0D\x0A\x08CONFLICT\x10\xDB\x02\x12\x0F\x0A\x0ACONNECTION\x10\xDC\x02\x12\x0F\x0A\x0ACONSTRAINT\x10\xDD\x02\x12\x10\x0A\x0BCONSTRAINTS\x10\xDE\x02\x12\x0E\x0A\x09CONTENT_P\x10\xDF\x02\x12\x0F\x0A\x0ACONTINUE_P\x10\xE0\x02\x12\x11\x0A\x0CCONVERSION_P\x10\xE1\x02\x12\x09\x0A\x04COPY\x10\xE2\x02\x12\x09\x0A\x04COST\x10\xE3\x02\x12\x0B\x0A\x06CREATE\x10\xE4\x02\x12\x0A\x0A\x05CROSS\x10\xE5\x02\x12\x08\x0A\x03CSV\x10\xE6\x02\x12\x09\x0A\x04CUBE\x10\xE7\x02\x12\x0E\x0A\x09CURRENT_P\x10\xE8\x02\x12\x14\x0A\x0FCURRENT_CATALOG\x10\xE9\x02\x12\x11\x0A\x0CCURRENT_DATE\x10\xEA\x02\x12\x11\x0A\x0CCURRENT_ROLE\x10\xEB\x02\x12\x13\x0A\x0ECURRENT_SCHEMA\x10\xEC\x02\x12\x11\x0A\x0CCURRENT_TIME\x10\xED\x02\x12\x16\x0A\x11CURRENT_TIMESTAMP\x10\xEE\x02\x12\x11\x0A\x0CCURRENT_USER\x10\xEF\x02\x12\x0B\x0A\x06CURSOR\x10\xF0\x02\x12\x0A\x0A\x05CYCLE\x10\xF1\x02\x12\x0B\x0A\x06DATA_P\x10\xF2\x02\x12\x0D\x0A\x08DATABASE\x10\xF3\x02\x12\x0A\x0A\x05DAY_P\x10\xF4\x02\x12\x0F\x0A\x0ADEALLOCATE\x10\xF5\x02\x12\x08\x0A\x03DEC\x10\xF6\x02\x12\x0E\x0A\x09DECIMAL_P\x10\xF7\x02\x12\x0C\x0A\x07DECLARE\x10\xF8\x02\x12\x0C\x0A\x07DEFAULT\x10\xF9\x02\x12\x0D\x0A\x08DEFAULTS\x10\xFA\x02\x12\x0F\x0A\x0ADEFERRABLE\x10\xFB\x02\x12\x0D\x0A\x08DEFERRED\x10\xFC\x02\x12\x0C\x0A\x07DEFINER\x10\xFD\x02\x12\x0D\x0A\x08DELETE_P\x10\xFE\x02\x12\x0E\x0A\x09DELIMITER\x10\xFF\x02\x12\x0F\x0A\x0ADELIMITERS\x10\x80\x03\x12\x0C\x0A\x07DEPENDS\x10\x81\x03\x12\x0A\x0A\x05DEPTH\x10\x82\x03\x12\x09\x0A\x04DESC\x10\x83\x03\x12\x0B\x0A\x06DETACH\x10\x84\x03\x12\x0F\x0A\x0ADICTIONARY\x10\x85\x03\x12\x0E\x0A\x09DISABLE_P\x10\x86\x03\x12\x0C\x0A\x07DISCARD\x10\x87\x03\x12\x0D\x0A\x08DISTINCT\x10\x88\x03\x12\x07\x0A\x02DO\x10\x89\x03\x12\x0F\x0A\x0ADOCUMENT_P\x10\x8A\x03\x12\x0D\x0A\x08DOMAIN_P\x10\x8B\x03\x12\x0D\x0A\x08DOUBLE_P\x10\x8C\x03\x12\x09\x0A\x04DROP\x10\x8D\x03\x12\x09\x0A\x04EACH\x10\x8E\x03\x12\x09\x0A\x04ELSE\x10\x8F\x03\x12\x0C\x0A\x07EMPTY_P\x10\x90\x03\x12\x0D\x0A\x08ENABLE_P\x10\x91\x03\x12\x0D\x0A\x08ENCODING\x10\x92\x03\x12\x0E\x0A\x09ENCRYPTED\x10\x93\x03\x12\x0A\x0A\x05END_P\x10\x94\x03\x12\x0B\x0A\x06ENUM_P\x10\x95\x03\x12\x0C\x0A\x07ERROR_P\x10\x96\x03\x12\x0B\x0A\x06ESCAPE\x10\x97\x03\x12\x0A\x0A\x05EVENT\x10\x98\x03\x12\x0B\x0A\x06EXCEPT\x10\x99\x03\x12\x0C\x0A\x07EXCLUDE\x10\x9A\x03\x12\x0E\x0A\x09EXCLUDING\x10\x9B\x03\x12\x0E\x0A\x09EXCLUSIVE\x10\x9C\x03\x12\x0C\x0A\x07EXECUTE\x10\x9D\x03\x12\x0B\x0A\x06EXISTS\x10\x9E\x03\x12\x0C\x0A\x07EXPLAIN\x10\x9F\x03\x12\x0F\x0A\x0AEXPRESSION\x10\xA0\x03\x12\x0E\x0A\x09EXTENSION\x10\xA1\x03\x12\x0D\x0A\x08EXTERNAL\x10\xA2\x03\x12\x0C\x0A\x07EXTRACT\x10\xA3\x03\x12\x0C\x0A\x07FALSE_P\x10\xA4\x03\x12\x0B\x0A\x06FAMILY\x10\xA5\x03\x12\x0A\x0A\x05FETCH\x10\xA6\x03\x12\x0B\x0A\x06FILTER\x10\xA7\x03\x12\x0D\x0A\x08FINALIZE\x10\xA8\x03\x12\x0C\x0A\x07FIRST_P\x10\xA9\x03\x12\x0C\x0A\x07FLOAT_P\x10\xAA\x03\x12\x0E\x0A\x09FOLLOWING\x10\xAB\x03\x12\x08\x0A\x03FOR\x10\xAC\x03\x12\x0A\x0A\x05FORCE\x10\xAD\x03\x12\x0C\x0A\x07FOREIGN\x10\xAE\x03\x12\x0B\x0A\x06FORMAT\x10\xAF\x03\x12\x0C\x0A\x07FORWARD\x10\xB0\x03\x12\x0B\x0A\x06FREEZE\x10\xB1\x03\x12\x09\x0A\x04FROM\x10\xB2\x03\x12\x09\x0A\x04FULL\x10\xB3\x03\x12\x0D\x0A\x08FUNCTION\x10\xB4\x03\x12\x0E\x0A\x09FUNCTIONS\x10\xB5\x03\x12\x0E\x0A\x09GENERATED\x10\xB6\x03\x12\x0B\x0A\x06GLOBAL\x10\xB7\x03\x12\x0A\x0A\x05GRANT\x10\xB8\x03\x12\x0C\x0A\x07GRANTED\x10\xB9\x03\x12\x0D\x0A\x08GREATEST\x10\xBA\x03\x12\x0C\x0A\x07GROUP_P\x10\xBB\x03\x12\x0D\x0A\x08GROUPING\x10\xBC\x03\x12\x0B\x0A\x06GROUPS\x10\xBD\x03\x12\x0C\x0A\x07HANDLER\x10\xBE\x03\x12\x0B\x0A\x06HAVING\x10\xBF\x03\x12\x0D\x0A\x08HEADER_P\x10\xC0\x03\x12\x09\x0A\x04HOLD\x10\xC1\x03\x12\x0B\x0A\x06HOUR_P\x10\xC2\x03\x12\x0F\x0A\x0AIDENTITY_P\x10\xC3\x03\x12\x09\x0A\x04IF_P\x10\xC4\x03\x12\x0A\x0A\x05ILIKE\x10\xC5\x03\x12\x0E\x0A\x09IMMEDIATE\x10\xC6\x03\x12\x0E\x0A\x09IMMUTABLE\x10\xC7\x03\x12\x0F\x0A\x0AIMPLICIT_P\x10\xC8\x03\x12\x0D\x0A\x08IMPORT_P\x10\xC9\x03\x12\x09\x0A\x04IN_P\x10\xCA\x03\x12\x0C\x0A\x07INCLUDE\x10\xCB\x03\x12\x0E\x0A\x09INCLUDING\x10\xCC\x03\x12\x0E\x0A\x09INCREMENT\x10\xCD\x03\x12\x0B\x0A\x06INDENT\x10\xCE\x03\x12\x0A\x0A\x05INDEX\x10\xCF\x03\x12\x0C\x0A\x07INDEXES\x10\xD0\x03\x12\x0C\x0A\x07INHERIT\x10\xD1\x03\x12\x0D\x0A\x08INHERITS\x10\xD2\x03\x12\x0E\x0A\x09INITIALLY\x10\xD3\x03\x12\x0D\x0A\x08INLINE_P\x10\xD4\x03\x12\x0C\x0A\x07INNER_P\x10\xD5\x03\x12\x0A\x0A\x05INOUT\x10\xD6\x03\x12\x0C\x0A\x07INPUT_P\x10\xD7\x03\x12\x10\x0A\x0BINSENSITIVE\x10\xD8\x03\x12\x0B\x0A\x06INSERT\x10\xD9\x03\x12\x0C\x0A\x07INSTEAD\x10\xDA\x03\x12\x0A\x0A\x05INT_P\x10\xDB\x03\x12\x0C\x0A\x07INTEGER\x10\xDC\x03\x12\x0E\x0A\x09INTERSECT\x10\xDD\x03\x12\x0D\x0A\x08INTERVAL\x10\xDE\x03\x12\x09\x0A\x04INTO\x10\xDF\x03\x12\x0C\x0A\x07INVOKER\x10\xE0\x03\x12\x07\x0A\x02IS\x10\xE1\x03\x12\x0B\x0A\x06ISNULL\x10\xE2\x03\x12\x0E\x0A\x09ISOLATION\x10\xE3\x03\x12\x09\x0A\x04JOIN\x10\xE4\x03\x12\x09\x0A\x04JSON\x10\xE5\x03\x12\x0F\x0A\x0AJSON_ARRAY\x10\xE6\x03\x12\x12\x0A\x0DJSON_ARRAYAGG\x10\xE7\x03\x12\x10\x0A\x0BJSON_EXISTS\x10\xE8\x03\x12\x10\x0A\x0BJSON_OBJECT\x10\xE9\x03\x12\x13\x0A\x0EJSON_OBJECTAGG\x10\xEA\x03\x12\x0F\x0A\x0AJSON_QUERY\x10\xEB\x03\x12\x10\x0A\x0BJSON_SCALAR\x10\xEC\x03\x12\x13\x0A\x0EJSON_SERIALIZE\x10\xED\x03\x12\x0F\x0A\x0AJSON_TABLE\x10\xEE\x03\x12\x0F\x0A\x0AJSON_VALUE\x10\xEF\x03\x12\x09\x0A\x04KEEP\x10\xF0\x03\x12\x08\x0A\x03KEY\x10\xF1\x03\x12\x09\x0A\x04KEYS\x10\xF2\x03\x12\x0A\x0A\x05LABEL\x10\xF3\x03\x12\x0D\x0A\x08LANGUAGE\x10\xF4\x03\x12\x0C\x0A\x07LARGE_P\x10\xF5\x03\x12\x0B\x0A\x06LAST_P\x10\xF6\x03\x12\x0E\x0A\x09LATERAL_P\x10\xF7\x03\x12\x0C\x0A\x07LEADING\x10\xF8\x03\x12\x0E\x0A\x09LEAKPROOF\x10\xF9\x03\x12\x0A\x0A\x05LEAST\x10\xFA\x03\x12\x09\x0A\x04LEFT\x10\xFB\x03\x12\x0A\x0A\x05LEVEL\x10\xFC\x03\x12\x09\x0A\x04LIKE\x10\xFD\x03\x12\x0A\x0A\x05LIMIT\x10\xFE\x03\x12\x0B\x0A\x06LISTEN\x10\xFF\x03\x12\x09\x0A\x04LOAD\x10\x80\x04\x12\x0A\x0A\x05LOCAL\x10\x81\x04\x12\x0E\x0A\x09LOCALTIME\x10\x82\x04\x12\x13\x0A\x0ELOCALTIMESTAMP\x10\x83\x04\x12\x0D\x0A\x08LOCATION\x10\x84\x04\x12\x0B\x0A\x06LOCK_P\x10\x85\x04\x12\x0B\x0A\x06LOCKED\x10\x86\x04\x12\x0B\x0A\x06LOGGED\x10\x87\x04\x12\x0C\x0A\x07MAPPING\x10\x88\x04\x12\x0A\x0A\x05MATCH\x10\x89\x04\x12\x0C\x0A\x07MATCHED\x10\x8A\x04\x12\x11\x0A\x0CMATERIALIZED\x10\x8B\x04\x12\x0D\x0A\x08MAXVALUE\x10\x8C\x04\x12\x0A\x0A\x05MERGE\x10\x8D\x04\x12\x11\x0A\x0CMERGE_ACTION\x10\x8E\x04\x12\x0B\x0A\x06METHOD\x10\x8F\x04\x12\x0D\x0A\x08MINUTE_P\x10\x90\x04\x12\x0D\x0A\x08MINVALUE\x10\x91\x04\x12\x09\x0A\x04MODE\x10\x92\x04\x12\x0C\x0A\x07MONTH_P\x10\x93\x04\x12\x09\x0A\x04MOVE\x10\x94\x04\x12\x0B\x0A\x06NAME_P\x10\x95\x04\x12\x0A\x0A\x05NAMES\x10\x96\x04\x12\x0D\x0A\x08NATIONAL\x10\x97\x04\x12\x0C\x0A\x07NATURAL\x10\x98\x04\x12\x0A\x0A\x05NCHAR\x10\x99\x04\x12\x0B\x0A\x06NESTED\x10\x9A\x04\x12\x08\x0A\x03NEW\x10\x9B\x04\x12\x09\x0A\x04NEXT\x10\x9C\x04\x12\x08\x0A\x03NFC\x10\x9D\x04\x12\x08\x0A\x03NFD\x10\x9E\x04\x12\x09\x0A\x04NFKC\x10\x9F\x04\x12\x09\x0A\x04NFKD\x10\xA0\x04\x12\x07\x0A\x02NO\x10\xA1\x04\x12\x09\x0A\x04NONE\x10\xA2\x04\x12\x0E\x0A\x09NORMALIZE\x10\xA3\x04\x12\x0F\x0A\x0ANORMALIZED\x10\xA4\x04\x12\x08\x0A\x03NOT\x10\xA5\x04\x12\x0C\x0A\x07NOTHING\x10\xA6\x04\x12\x0B\x0A\x06NOTIFY\x10\xA7\x04\x12\x0C\x0A\x07NOTNULL\x10\xA8\x04\x12\x0B\x0A\x06NOWAIT\x10\xA9\x04\x12\x0B\x0A\x06NULL_P\x10\xAA\x04\x12\x0B\x0A\x06NULLIF\x10\xAB\x04\x12\x0C\x0A\x07NULLS_P\x10\xAC\x04\x12\x0C\x0A\x07NUMERIC\x10\xAD\x04\x12\x0D\x0A\x08OBJECT_P\x10\xAE\x04\x12\x07\x0A\x02OF\x10\xAF\x04\x12\x08\x0A\x03OFF\x10\xB0\x04\x12\x0B\x0A\x06OFFSET\x10\xB1\x04\x12\x09\x0A\x04OIDS\x10\xB2\x04\x12\x08\x0A\x03OLD\x10\xB3\x04\x12\x09\x0A\x04OMIT\x10\xB4\x04\x12\x07\x0A\x02ON\x10\xB5\x04\x12\x09\x0A\x04ONLY\x10\xB6\x04\x12\x0D\x0A\x08OPERATOR\x10\xB7\x04\x12\x0B\x0A\x06OPTION\x10\xB8\x04\x12\x0C\x0A\x07OPTIONS\x10\xB9\x04\x12\x07\x0A\x02OR\x10\xBA\x04\x12\x0A\x0A\x05ORDER\x10\xBB\x04\x12\x0F\x0A\x0AORDINALITY\x10\xBC\x04\x12\x0B\x0A\x06OTHERS\x10\xBD\x04\x12\x0A\x0A\x05OUT_P\x10\xBE\x04\x12\x0C\x0A\x07OUTER_P\x10\xBF\x04\x12\x09\x0A\x04OVER\x10\xC0\x04\x12\x0D\x0A\x08OVERLAPS\x10\xC1\x04\x12\x0C\x0A\x07OVERLAY\x10\xC2\x04\x12\x0F\x0A\x0AOVERRIDING\x10\xC3\x04\x12\x0A\x0A\x05OWNED\x10\xC4\x04\x12\x0A\x0A\x05OWNER\x10\xC5\x04\x12\x0D\x0A\x08PARALLEL\x10\xC6\x04\x12\x0E\x0A\x09PARAMETER\x10\xC7\x04\x12\x0B\x0A\x06PARSER\x10\xC8\x04\x12\x0C\x0A\x07PARTIAL\x10\xC9\x04\x12\x0E\x0A\x09PARTITION\x10\xCA\x04\x12\x0C\x0A\x07PASSING\x10\xCB\x04\x12\x0D\x0A\x08PASSWORD\x10\xCC\x04\x12\x09\x0A\x04PATH\x10\xCD\x04\x12\x0C\x0A\x07PLACING\x10\xCE\x04\x12\x09\x0A\x04PLAN\x10\xCF\x04\x12\x0A\x0A\x05PLANS\x10\xD0\x04\x12\x0B\x0A\x06POLICY\x10\xD1\x04\x12\x0D\x0A\x08POSITION\x10\xD2\x04\x12\x0E\x0A\x09PRECEDING\x10\xD3\x04\x12\x0E\x0A\x09PRECISION\x10\xD4\x04\x12\x0D\x0A\x08PRESERVE\x10\xD5\x04\x12\x0C\x0A\x07PREPARE\x10\xD6\x04\x12\x0D\x0A\x08PREPARED\x10\xD7\x04\x12\x0C\x0A\x07PRIMARY\x10\xD8\x04\x12\x0A\x0A\x05PRIOR\x10\xD9\x04\x12\x0F\x0A\x0APRIVILEGES\x10\xDA\x04\x12\x0F\x0A\x0APROCEDURAL\x10\xDB\x04\x12\x0E\x0A\x09PROCEDURE\x10\xDC\x04\x12\x0F\x0A\x0APROCEDURES\x10\xDD\x04\x12\x0C\x0A\x07PROGRAM\x10\xDE\x04\x12\x10\x0A\x0BPUBLICATION\x10\xDF\x04\x12\x0A\x0A\x05QUOTE\x10\xE0\x04\x12\x0B\x0A\x06QUOTES\x10\xE1\x04\x12\x0A\x0A\x05RANGE\x10\xE2\x04\x12\x09\x0A\x04READ\x10\xE3\x04\x12\x09\x0A\x04REAL\x10\xE4\x04\x12\x0D\x0A\x08REASSIGN\x10\xE5\x04\x12\x0C\x0A\x07RECHECK\x10\xE6\x04\x12\x0E\x0A\x09RECURSIVE\x10\xE7\x04\x12\x0A\x0A\x05REF_P\x10\xE8\x04\x12\x0F\x0A\x0AREFERENCES\x10\xE9\x04\x12\x10\x0A\x0BREFERENCING\x10\xEA\x04\x12\x0C\x0A\x07REFRESH\x10\xEB\x04\x12\x0C\x0A\x07REINDEX\x10\xEC\x04\x12\x0F\x0A\x0ARELATIVE_P\x10\xED\x04\x12\x0C\x0A\x07RELEASE\x10\xEE\x04\x12\x0B\x0A\x06RENAME\x10\xEF\x04\x12\x0F\x0A\x0AREPEATABLE\x10\xF0\x04\x12\x0C\x0A\x07REPLACE\x10\xF1\x04\x12\x0C\x0A\x07REPLICA\x10\xF2\x04\x12\x0A\x0A\x05RESET\x10\xF3\x04\x12\x0C\x0A\x07RESTART\x10\xF4\x04\x12\x0D\x0A\x08RESTRICT\x10\xF5\x04\x12\x0B\x0A\x06RETURN\x10\xF6\x04\x12\x0E\x0A\x09RETURNING\x10\xF7\x04\x12\x0C\x0A\x07RETURNS\x10\xF8\x04\x12\x0B\x0A\x06REVOKE\x10\xF9\x04\x12\x0A\x0A\x05RIGHT\x10\xFA\x04\x12\x09\x0A\x04ROLE\x10\xFB\x04\x12\x0D\x0A\x08ROLLBACK\x10\xFC\x04\x12\x0B\x0A\x06ROLLUP\x10\xFD\x04\x12\x0C\x0A\x07ROUTINE\x10\xFE\x04\x12\x0D\x0A\x08ROUTINES\x10\xFF\x04\x12\x08\x0A\x03ROW\x10\x80\x05\x12\x09\x0A\x04ROWS\x10\x81\x05\x12\x09\x0A\x04RULE\x10\x82\x05\x12\x0E\x0A\x09SAVEPOINT\x10\x83\x05\x12\x0B\x0A\x06SCALAR\x10\x84\x05\x12\x0B\x0A\x06SCHEMA\x10\x85\x05\x12\x0C\x0A\x07SCHEMAS\x10\x86\x05\x12\x0B\x0A\x06SCROLL\x10\x87\x05\x12\x0B\x0A\x06SEARCH\x10\x88\x05\x12\x0D\x0A\x08SECOND_P\x10\x89\x05\x12\x0D\x0A\x08SECURITY\x10\x8A\x05\x12\x0B\x0A\x06SELECT\x10\x8B\x05\x12\x0D\x0A\x08SEQUENCE\x10\x8C\x05\x12\x0E\x0A\x09SEQUENCES\x10\x8D\x05\x12\x11\x0A\x0CSERIALIZABLE\x10\x8E\x05\x12\x0B\x0A\x06SERVER\x10\x8F\x05\x12\x0C\x0A\x07SESSION\x10\x90\x05\x12\x11\x0A\x0CSESSION_USER\x10\x91\x05\x12\x08\x0A\x03SET\x10\x92\x05\x12\x09\x0A\x04SETS\x10\x93\x05\x12\x0A\x0A\x05SETOF\x10\x94\x05\x12\x0A\x0A\x05SHARE\x10\x95\x05\x12\x09\x0A\x04SHOW\x10\x96\x05\x12\x0C\x0A\x07SIMILAR\x10\x97\x05\x12\x0B\x0A\x06SIMPLE\x10\x98\x05\x12\x09\x0A\x04SKIP\x10\x99\x05\x12\x0D\x0A\x08SMALLINT\x10\x9A\x05\x12\x0D\x0A\x08SNAPSHOT\x10\x9B\x05\x12\x09\x0A\x04SOME\x10\x9C\x05\x12\x0B\x0A\x06SOURCE\x10\x9D\x05\x12\x0A\x0A\x05SQL_P\x10\x9E\x05\x12\x0B\x0A\x06STABLE\x10\x9F\x05\x12\x11\x0A\x0CSTANDALONE_P\x10\xA0\x05\x12\x0A\x0A\x05START\x10\xA1\x05\x12\x0E\x0A\x09STATEMENT\x10\xA2\x05\x12\x0F\x0A\x0ASTATISTICS\x10\xA3\x05\x12\x0A\x0A\x05STDIN\x10\xA4\x05\x12\x0B\x0A\x06STDOUT\x10\xA5\x05\x12\x0C\x0A\x07STORAGE\x10\xA6\x05\x12\x0B\x0A\x06STORED\x10\xA7\x05\x12\x0D\x0A\x08STRICT_P\x10\xA8\x05\x12\x0D\x0A\x08STRING_P\x10\xA9\x05\x12\x0C\x0A\x07STRIP_P\x10\xAA\x05\x12\x11\x0A\x0CSUBSCRIPTION\x10\xAB\x05\x12\x0E\x0A\x09SUBSTRING\x10\xAC\x05\x12\x0C\x0A\x07SUPPORT\x10\xAD\x05\x12\x0E\x0A\x09SYMMETRIC\x10\xAE\x05\x12\x0A\x0A\x05SYSID\x10\xAF\x05\x12\x0D\x0A\x08SYSTEM_P\x10\xB0\x05\x12\x10\x0A\x0BSYSTEM_USER\x10\xB1\x05\x12\x0A\x0A\x05TABLE\x10\xB2\x05\x12\x0B\x0A\x06TABLES\x10\xB3\x05\x12\x10\x0A\x0BTABLESAMPLE\x10\xB4\x05\x12\x0F\x0A\x0ATABLESPACE\x10\xB5\x05\x12\x0B\x0A\x06TARGET\x10\xB6\x05\x12\x09\x0A\x04TEMP\x10\xB7\x05\x12\x0D\x0A\x08TEMPLATE\x10\xB8\x05\x12\x0E\x0A\x09TEMPORARY\x10\xB9\x05\x12\x0B\x0A\x06TEXT_P\x10\xBA\x05\x12\x09\x0A\x04THEN\x10\xBB\x05\x12\x09\x0A\x04TIES\x10\xBC\x05\x12\x09\x0A\x04TIME\x10\xBD\x05\x12\x0E\x0A\x09TIMESTAMP\x10\xBE\x05\x12\x07\x0A\x02TO\x10\xBF\x05\x12\x0D\x0A\x08TRAILING\x10\xC0\x05\x12\x10\x0A\x0BTRANSACTION\x10\xC1\x05\x12\x0E\x0A\x09TRANSFORM\x10\xC2\x05\x12\x0A\x0A\x05TREAT\x10\xC3\x05\x12\x0C\x0A\x07TRIGGER\x10\xC4\x05\x12\x09\x0A\x04TRIM\x10\xC5\x05\x12\x0B\x0A\x06TRUE_P\x10\xC6\x05\x12\x0D\x0A\x08TRUNCATE\x10\xC7\x05\x12\x0C\x0A\x07TRUSTED\x10\xC8\x05\x12\x0B\x0A\x06TYPE_P\x10\xC9\x05\x12\x0C\x0A\x07TYPES_P\x10\xCA\x05\x12\x0C\x0A\x07UESCAPE\x10\xCB\x05\x12\x0E\x0A\x09UNBOUNDED\x10\xCC\x05\x12\x12\x0A\x0DUNCONDITIONAL\x10\xCD\x05\x12\x10\x0A\x0BUNCOMMITTED\x10\xCE\x05\x12\x10\x0A\x0BUNENCRYPTED\x10\xCF\x05\x12\x0A\x0A\x05UNION\x10\xD0\x05\x12\x0B\x0A\x06UNIQUE\x10\xD1\x05\x12\x0C\x0A\x07UNKNOWN\x10\xD2\x05\x12\x0D\x0A\x08UNLISTEN\x10\xD3\x05\x12\x0D\x0A\x08UNLOGGED\x10\xD4\x05\x12\x0A\x0A\x05UNTIL\x10\xD5\x05\x12\x0B\x0A\x06UPDATE\x10\xD6\x05\x12\x09\x0A\x04USER\x10\xD7\x05\x12\x0A\x0A\x05USING\x10\xD8\x05\x12\x0B\x0A\x06VACUUM\x10\xD9\x05\x12\x0A\x0A\x05VALID\x10\xDA\x05\x12\x0D\x0A\x08VALIDATE\x10\xDB\x05\x12\x0E\x0A\x09VALIDATOR\x10\xDC\x05\x12\x0C\x0A\x07VALUE_P\x10\xDD\x05\x12\x0B\x0A\x06VALUES\x10\xDE\x05\x12\x0C\x0A\x07VARCHAR\x10\xDF\x05\x12\x0D\x0A\x08VARIADIC\x10\xE0\x05\x12\x0C\x0A\x07VARYING\x10\xE1\x05\x12\x0C\x0A\x07VERBOSE\x10\xE2\x05\x12\x0E\x0A\x09VERSION_P\x10\xE3\x05\x12\x09\x0A\x04VIEW\x10\xE4\x05\x12\x0A\x0A\x05VIEWS\x10\xE5\x05\x12\x0D\x0A\x08VOLATILE\x10\xE6\x05\x12\x09\x0A\x04WHEN\x10\xE7\x05\x12\x0A\x0A\x05WHERE\x10\xE8\x05\x12\x11\x0A\x0CWHITESPACE_P\x10\xE9\x05\x12\x0B\x0A\x06WINDOW\x10\xEA\x05\x12\x09\x0A\x04WITH\x10\xEB\x05\x12\x0B\x0A\x06WITHIN\x10\xEC\x05\x12\x0C\x0A\x07WITHOUT\x10\xED\x05\x12\x09\x0A\x04WORK\x10\xEE\x05\x12\x0C\x0A\x07WRAPPER\x10\xEF\x05\x12\x0A\x0A\x05WRITE\x10\xF0\x05\x12\x0A\x0A\x05XML_P\x10\xF1\x05\x12\x12\x0A\x0DXMLATTRIBUTES\x10\xF2\x05\x12\x0E\x0A\x09XMLCONCAT\x10\xF3\x05\x12\x0F\x0A\x0AXMLELEMENT\x10\xF4\x05\x12\x0E\x0A\x09XMLEXISTS\x10\xF5\x05\x12\x0E\x0A\x09XMLFOREST\x10\xF6\x05\x12\x12\x0A\x0DXMLNAMESPACES\x10\xF7\x05\x12\x0D\x0A\x08XMLPARSE\x10\xF8\x05\x12\x0A\x0A\x05XMLPI\x10\xF9\x05\x12\x0C\x0A\x07XMLROOT\x10\xFA\x05\x12\x11\x0A\x0CXMLSERIALIZE\x10\xFB\x05\x12\x0D\x0A\x08XMLTABLE\x10\xFC\x05\x12\x0B\x0A\x06YEAR_P\x10\xFD\x05\x12\x0A\x0A\x05YES_P\x10\xFE\x05\x12\x09\x0A\x04ZONE\x10\xFF\x05\x12\x0E\x0A\x09FORMAT_LA\x10\x80\x06\x12\x0B\x0A\x06NOT_LA\x10\x81\x06\x12\x0D\x0A\x08NULLS_LA\x10\x82\x06\x12\x0C\x0A\x07WITH_LA\x10\x83\x06\x12\x0F\x0A\x0AWITHOUT_LA\x10\x84\x06\x12\x13\x0A\x0EMODE_TYPE_NAME\x10\x85\x06\x12\x16\x0A\x11MODE_PLPGSQL_EXPR\x10\x86\x06\x12\x19\x0A\x14MODE_PLPGSQL_ASSIGN1\x10\x87\x06\x12\x19\x0A\x14MODE_PLPGSQL_ASSIGN2\x10\x88\x06\x12\x19\x0A\x14MODE_PLPGSQL_ASSIGN3\x10\x89\x06\x12\x0B\x0A\x06UMINUS\x10\x8A\x06BC\xCA\x02\x1CFlow\\PostgreSql\\Protobuf\\AST\xE2\x02!Flow\\PostgreSql\\Protobuf\\Metadatab\x06proto3",
true
);
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/AstToSql.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/AstToSql.php
new file mode 100644
index 000000000..7b4537475
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/AstToSql.php
@@ -0,0 +1,37 @@
+toAst());
+ }
+
+ private static function deparseAst(object $ast) : string
+ {
+ $nodeKey = self::getNodeKeyForAst($ast);
+ $node = new Node([$nodeKey => $ast]);
+
+ $rawStmt = new RawStmt(['stmt' => $node]);
+ $parseResult = new ParseResult();
+ $parseResult->setStmts([$rawStmt]);
+
+ return (new ParsedQuery($parseResult))->deparse();
+ }
+
+ private static function getNodeKeyForAst(object $ast) : string
+ {
+ $className = $ast::class;
+ $shortName = \substr($className, (int) \strrpos($className, '\\') + 1);
+ $result = \preg_replace('/([a-z])([A-Z])/', '$1_$2', $shortName);
+
+ return \strtolower($result ?? $shortName);
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Bridge/AstConvertible.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Bridge/AstConvertible.php
new file mode 100644
index 000000000..95ecd2b46
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Bridge/AstConvertible.php
@@ -0,0 +1,27 @@
+ $columnNames
+ */
+ public function __construct(
+ private string $name,
+ private Node $query,
+ private array $columnNames = [],
+ private CTEMaterialization $materialization = CTEMaterialization::DEFAULT,
+ private bool $recursive = false,
+ ) {
+ }
+
+ public static function fromAst(Node $node) : static
+ {
+ $commonTableExpr = $node->getCommonTableExpr();
+
+ if ($commonTableExpr === null) {
+ throw InvalidAstException::unexpectedNodeType('CommonTableExpr', 'unknown');
+ }
+
+ $cteName = $commonTableExpr->getCtename();
+
+ if ($cteName === '') {
+ throw InvalidAstException::missingRequiredField('ctename', 'CommonTableExpr');
+ }
+
+ $cteQuery = $commonTableExpr->getCtequery();
+
+ if ($cteQuery === null) {
+ throw InvalidAstException::missingRequiredField('ctequery', 'CommonTableExpr');
+ }
+
+ $columnNames = [];
+ $aliasColumns = $commonTableExpr->getAliascolnames();
+
+ if ($aliasColumns !== null) {
+ foreach ($aliasColumns as $aliasNode) {
+ $stringNode = $aliasNode->getString();
+
+ if ($stringNode === null) {
+ throw InvalidAstException::invalidFieldValue('aliascolnames', 'CommonTableExpr', 'Expected String node');
+ }
+
+ $columnNames[] = $stringNode->getSval();
+ }
+ }
+
+ $materialization = CTEMaterialization::fromProtobuf($commonTableExpr->getCtematerialized());
+ $recursive = $commonTableExpr->getCterecursive();
+
+ return new self($cteName, $cteQuery, $columnNames, $materialization, $recursive);
+ }
+
+ /**
+ * @return array
+ */
+ public function columnNames() : array
+ {
+ return $this->columnNames;
+ }
+
+ public function materialization() : CTEMaterialization
+ {
+ return $this->materialization;
+ }
+
+ public function materialized() : self
+ {
+ return new self($this->name, $this->query, $this->columnNames, CTEMaterialization::MATERIALIZED, $this->recursive);
+ }
+
+ public function name() : string
+ {
+ return $this->name;
+ }
+
+ public function notMaterialized() : self
+ {
+ return new self($this->name, $this->query, $this->columnNames, CTEMaterialization::NOT_MATERIALIZED, $this->recursive);
+ }
+
+ public function query() : Node
+ {
+ return $this->query;
+ }
+
+ public function recursive() : bool
+ {
+ return $this->recursive;
+ }
+
+ public function toAst() : Node
+ {
+ $commonTableExpr = new CommonTableExpr();
+ $commonTableExpr->setCtename($this->name);
+ $commonTableExpr->setCtequery($this->query);
+ $commonTableExpr->setCtematerialized($this->materialization->toProtobuf());
+ $commonTableExpr->setCterecursive($this->recursive);
+
+ if ($this->columnNames !== []) {
+ $aliasNodes = [];
+
+ foreach ($this->columnNames as $columnName) {
+ $stringNode = new PBString();
+ $stringNode->setSval($columnName);
+
+ $node = new Node();
+ $node->setString($stringNode);
+
+ $aliasNodes[] = $node;
+ }
+
+ $commonTableExpr->setAliascolnames($aliasNodes);
+ }
+
+ $node = new Node();
+ $node->setCommonTableExpr($commonTableExpr);
+
+ return $node;
+ }
+
+ /**
+ * @param array $columns
+ */
+ public function withColumns(array $columns) : self
+ {
+ return new self($this->name, $this->query, $columns, $this->materialization, $this->recursive);
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/CTEMaterialization.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/CTEMaterialization.php
new file mode 100644
index 000000000..c10d65614
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/CTEMaterialization.php
@@ -0,0 +1,35 @@
+ self::MATERIALIZED,
+ CTEMaterialize::CTEMaterializeNever => self::NOT_MATERIALIZED,
+ default => self::DEFAULT,
+ };
+ }
+
+ public function toProtobuf() : int
+ {
+ return match ($this) {
+ self::DEFAULT => CTEMaterialize::CTEMaterializeDefault,
+ self::MATERIALIZED => CTEMaterialize::CTEMaterializeAlways,
+ self::NOT_MATERIALIZED => CTEMaterialize::CTEMaterializeNever,
+ };
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/ConflictAction.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/ConflictAction.php
new file mode 100644
index 000000000..78a1f36f0
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/ConflictAction.php
@@ -0,0 +1,32 @@
+ self::UPDATE,
+ default => self::NOTHING,
+ };
+ }
+
+ public function toProtobuf() : int
+ {
+ return match ($this) {
+ self::NOTHING => OnConflictAction::ONCONFLICT_NOTHING,
+ self::UPDATE => OnConflictAction::ONCONFLICT_UPDATE,
+ };
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/ConflictTarget.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/ConflictTarget.php
new file mode 100644
index 000000000..35edfe730
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/ConflictTarget.php
@@ -0,0 +1,137 @@
+ $columns
+ */
+ public function __construct(
+ private array $columns = [],
+ private ?string $constraint = null,
+ private ?Condition $whereClause = null,
+ ) {
+ }
+
+ /**
+ * @param list $columns
+ */
+ public static function columns(array $columns) : self
+ {
+ return new self($columns);
+ }
+
+ public static function constraint(string $name) : self
+ {
+ return new self([], $name);
+ }
+
+ public static function fromAst(Node $node) : static
+ {
+ $inferClause = $node->getInferClause();
+
+ if ($inferClause === null) {
+ throw InvalidAstException::unexpectedNodeType('InferClause', 'unknown');
+ }
+
+ $constraint = $inferClause->getConname();
+
+ if ($constraint === '') {
+ $constraint = null;
+ }
+
+ $columns = [];
+ $indexElems = $inferClause->getIndexElems();
+
+ if ($indexElems !== null) {
+ foreach ($indexElems as $indexElem) {
+ $indexElemNode = $indexElem->getIndexElem();
+
+ if ($indexElemNode !== null) {
+ $name = $indexElemNode->getName();
+
+ if ($name !== '') {
+ $columns[] = $name;
+ }
+ }
+ }
+ }
+
+ $whereClause = null;
+ $whereNode = $inferClause->getWhereClause();
+
+ if ($whereNode !== null) {
+ $whereClause = ConditionFactory::fromAst($whereNode);
+ }
+
+ return new self($columns, $constraint, $whereClause);
+ }
+
+ /**
+ * @return list
+ */
+ public function getColumns() : array
+ {
+ return $this->columns;
+ }
+
+ public function getConstraint() : ?string
+ {
+ return $this->constraint;
+ }
+
+ public function toAst() : Node
+ {
+ $inferClause = new InferClause();
+
+ if ($this->constraint !== null) {
+ $inferClause->setConname($this->constraint);
+ }
+
+ if ($this->columns !== []) {
+ $indexElems = [];
+
+ foreach ($this->columns as $column) {
+ $indexElem = new IndexElem();
+ $indexElem->setName($column);
+
+ $node = new Node();
+ $node->setIndexElem($indexElem);
+
+ $indexElems[] = $node;
+ }
+
+ $inferClause->setIndexElems($indexElems);
+ }
+
+ if ($this->whereClause !== null) {
+ $inferClause->setWhereClause($this->whereClause->toAst());
+ }
+
+ $node = new Node();
+ $node->setInferClause($inferClause);
+
+ return $node;
+ }
+
+ public function where(Condition $condition) : self
+ {
+ return new self($this->columns, $this->constraint, $condition);
+ }
+
+ public function whereClause() : ?Condition
+ {
+ return $this->whereClause;
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/FrameBound.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/FrameBound.php
new file mode 100644
index 000000000..b590319f9
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/FrameBound.php
@@ -0,0 +1,78 @@
+type === FrameBoundType::PRECEDING || $this->type === FrameBoundType::FOLLOWING) && $this->offset === null) {
+ throw InvalidExpressionException::invalidValue('FrameBound offset', 'null for PRECEDING/FOLLOWING');
+ }
+
+ if (($this->type === FrameBoundType::CURRENT_ROW || $this->type === FrameBoundType::UNBOUNDED_PRECEDING || $this->type === FrameBoundType::UNBOUNDED_FOLLOWING) && $this->offset !== null) {
+ throw InvalidExpressionException::invalidValue('FrameBound offset', 'non-null for CURRENT_ROW/UNBOUNDED');
+ }
+ }
+
+ public static function currentRow() : self
+ {
+ return new self(FrameBoundType::CURRENT_ROW);
+ }
+
+ public static function following(Expression $offset) : self
+ {
+ return new self(FrameBoundType::FOLLOWING, $offset);
+ }
+
+ public static function fromAst(Node $node) : static
+ {
+ return new self(FrameBoundType::CURRENT_ROW);
+ }
+
+ public static function preceding(Expression $offset) : self
+ {
+ return new self(FrameBoundType::PRECEDING, $offset);
+ }
+
+ public static function unboundedFollowing() : self
+ {
+ return new self(FrameBoundType::UNBOUNDED_FOLLOWING);
+ }
+
+ public static function unboundedPreceding() : self
+ {
+ return new self(FrameBoundType::UNBOUNDED_PRECEDING);
+ }
+
+ public function offset() : ?Expression
+ {
+ return $this->offset;
+ }
+
+ public function toAst() : Node
+ {
+ if ($this->offset !== null) {
+ return $this->offset->toAst();
+ }
+
+ return new Node();
+ }
+
+ public function type() : FrameBoundType
+ {
+ return $this->type;
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/FrameBoundType.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/FrameBoundType.php
new file mode 100644
index 000000000..966e02afe
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/FrameBoundType.php
@@ -0,0 +1,17 @@
+ self::UPDATE,
+ LockClauseStrength::LCS_FORNOKEYUPDATE => self::NO_KEY_UPDATE,
+ LockClauseStrength::LCS_FORSHARE => self::SHARE,
+ LockClauseStrength::LCS_FORKEYSHARE => self::KEY_SHARE,
+ default => self::UPDATE,
+ };
+ }
+
+ public function toProtobuf() : int
+ {
+ return match ($this) {
+ self::UPDATE => LockClauseStrength::LCS_FORUPDATE,
+ self::NO_KEY_UPDATE => LockClauseStrength::LCS_FORNOKEYUPDATE,
+ self::SHARE => LockClauseStrength::LCS_FORSHARE,
+ self::KEY_SHARE => LockClauseStrength::LCS_FORKEYSHARE,
+ };
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/LockWaitPolicy.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/LockWaitPolicy.php
new file mode 100644
index 000000000..800098602
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/LockWaitPolicy.php
@@ -0,0 +1,35 @@
+ self::NOWAIT,
+ ProtobufLockWaitPolicy::LockWaitSkip => self::SKIP_LOCKED,
+ default => self::DEFAULT,
+ };
+ }
+
+ public function toProtobuf() : int
+ {
+ return match ($this) {
+ self::DEFAULT => ProtobufLockWaitPolicy::LockWaitBlock,
+ self::NOWAIT => ProtobufLockWaitPolicy::LockWaitError,
+ self::SKIP_LOCKED => ProtobufLockWaitPolicy::LockWaitSkip,
+ };
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/LockingClause.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/LockingClause.php
new file mode 100644
index 000000000..a5936137c
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/LockingClause.php
@@ -0,0 +1,144 @@
+ $tables
+ */
+ public function __construct(
+ private LockStrength $strength,
+ private array $tables = [],
+ private LockWaitPolicy $waitPolicy = LockWaitPolicy::DEFAULT,
+ ) {
+ }
+
+ /**
+ * @param list $tables
+ */
+ public static function forKeyShare(array $tables = []) : self
+ {
+ return new self(LockStrength::KEY_SHARE, $tables);
+ }
+
+ /**
+ * @param list $tables
+ */
+ public static function forNoKeyUpdate(array $tables = []) : self
+ {
+ return new self(LockStrength::NO_KEY_UPDATE, $tables);
+ }
+
+ /**
+ * @param list $tables
+ */
+ public static function forShare(array $tables = []) : self
+ {
+ return new self(LockStrength::SHARE, $tables);
+ }
+
+ /**
+ * @param list $tables
+ */
+ public static function forUpdate(array $tables = []) : self
+ {
+ return new self(LockStrength::UPDATE, $tables);
+ }
+
+ public static function fromAst(Node $node) : static
+ {
+ $lockingClause = $node->getLockingClause();
+
+ if ($lockingClause === null) {
+ throw InvalidAstException::unexpectedNodeType('LockingClause', 'unknown');
+ }
+
+ $strength = LockStrength::fromProtobuf($lockingClause->getStrength());
+ $waitPolicy = LockWaitPolicy::fromProtobuf($lockingClause->getWaitPolicy());
+
+ $tables = [];
+ $lockedRels = $lockingClause->getLockedRels();
+
+ if ($lockedRels !== null) {
+ foreach ($lockedRels as $relNode) {
+ $rangeVar = $relNode->getRangeVar();
+
+ if ($rangeVar !== null) {
+ $relname = $rangeVar->getRelname();
+
+ if ($relname !== '') {
+ $tables[] = $relname;
+ }
+ }
+ }
+ }
+
+ return new self($strength, $tables, $waitPolicy);
+ }
+
+ public function nowait() : self
+ {
+ return new self($this->strength, $this->tables, LockWaitPolicy::NOWAIT);
+ }
+
+ public function skipLocked() : self
+ {
+ return new self($this->strength, $this->tables, LockWaitPolicy::SKIP_LOCKED);
+ }
+
+ public function strength() : LockStrength
+ {
+ return $this->strength;
+ }
+
+ /**
+ * @return list
+ */
+ public function tables() : array
+ {
+ return $this->tables;
+ }
+
+ public function toAst() : Node
+ {
+ $lockingClause = new ProtobufLockingClause();
+ $lockingClause->setStrength($this->strength->toProtobuf());
+ $lockingClause->setWaitPolicy($this->waitPolicy->toProtobuf());
+
+ if ($this->tables !== []) {
+ $lockedRels = [];
+
+ foreach ($this->tables as $table) {
+ $rangeVar = new RangeVar();
+ $rangeVar->setRelname($table);
+
+ $relNode = new Node();
+ $relNode->setRangeVar($rangeVar);
+
+ $lockedRels[] = $relNode;
+ }
+
+ $lockingClause->setLockedRels($lockedRels);
+ }
+
+ $node = new Node();
+ $node->setLockingClause($lockingClause);
+
+ return $node;
+ }
+
+ public function waitPolicy() : LockWaitPolicy
+ {
+ return $this->waitPolicy;
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/NullsPosition.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/NullsPosition.php
new file mode 100644
index 000000000..af1dec64f
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/NullsPosition.php
@@ -0,0 +1,35 @@
+ self::FIRST,
+ SortByNulls::SORTBY_NULLS_LAST => self::LAST,
+ default => self::DEFAULT,
+ };
+ }
+
+ public function toProtobuf() : int
+ {
+ return match ($this) {
+ self::FIRST => SortByNulls::SORTBY_NULLS_FIRST,
+ self::LAST => SortByNulls::SORTBY_NULLS_LAST,
+ self::DEFAULT => SortByNulls::SORTBY_NULLS_DEFAULT,
+ };
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/OnConflictClause.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/OnConflictClause.php
new file mode 100644
index 000000000..2fa5d2c47
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/OnConflictClause.php
@@ -0,0 +1,157 @@
+ $updates
+ */
+ public function __construct(
+ private ConflictAction $action,
+ private ?ConflictTarget $target = null,
+ private array $updates = [],
+ private ?Condition $whereClause = null,
+ ) {
+ }
+
+ public static function doNothing(?ConflictTarget $target = null) : self
+ {
+ return new self(ConflictAction::NOTHING, $target);
+ }
+
+ /**
+ * @param array $updates
+ */
+ public static function doUpdate(ConflictTarget $target, array $updates) : self
+ {
+ return new self(ConflictAction::UPDATE, $target, $updates);
+ }
+
+ public static function fromAst(Node $node) : static
+ {
+ $onConflictClause = $node->getOnConflictClause();
+
+ if ($onConflictClause === null) {
+ throw InvalidAstException::unexpectedNodeType('OnConflictClause', 'unknown');
+ }
+
+ $action = ConflictAction::fromProtobuf($onConflictClause->getAction());
+
+ $target = null;
+ $inferNode = $onConflictClause->getInfer();
+
+ if ($inferNode !== null) {
+ $inferWrapperNode = new Node();
+ $inferWrapperNode->setInferClause($inferNode);
+ $target = ConflictTarget::fromAst($inferWrapperNode);
+ }
+
+ $updates = [];
+ $targetList = $onConflictClause->getTargetList();
+
+ if ($targetList !== null) {
+ foreach ($targetList as $targetNode) {
+ $resTarget = $targetNode->getResTarget();
+
+ if ($resTarget !== null) {
+ $name = $resTarget->getName();
+ $valNode = $resTarget->getVal();
+
+ if ($name !== '' && $valNode !== null) {
+ $updates[$name] = ExpressionFactory::fromAst($valNode);
+ }
+ }
+ }
+ }
+
+ $whereClause = null;
+ $whereNode = $onConflictClause->getWhereClause();
+
+ if ($whereNode !== null) {
+ $whereClause = ConditionFactory::fromAst($whereNode);
+ }
+
+ return new self($action, $target, $updates, $whereClause);
+ }
+
+ public function action() : ConflictAction
+ {
+ return $this->action;
+ }
+
+ public function target() : ?ConflictTarget
+ {
+ return $this->target;
+ }
+
+ public function toAst() : Node
+ {
+ $onConflictClause = new ProtobufOnConflictClause();
+ $onConflictClause->setAction($this->action->toProtobuf());
+
+ if ($this->target !== null) {
+ $targetNode = $this->target->toAst();
+ $inferClause = $targetNode->getInferClause();
+
+ if ($inferClause !== null) {
+ $onConflictClause->setInfer($inferClause);
+ }
+ }
+
+ if ($this->updates !== []) {
+ $targetList = [];
+
+ foreach ($this->updates as $column => $expr) {
+ $resTarget = new ResTarget();
+ $resTarget->setName($column);
+ $resTarget->setVal($expr->toAst());
+
+ $targetNode = new Node();
+ $targetNode->setResTarget($resTarget);
+
+ $targetList[] = $targetNode;
+ }
+
+ $onConflictClause->setTargetList($targetList);
+ }
+
+ if ($this->whereClause !== null) {
+ $onConflictClause->setWhereClause($this->whereClause->toAst());
+ }
+
+ $node = new Node();
+ $node->setOnConflictClause($onConflictClause);
+
+ return $node;
+ }
+
+ /**
+ * @return array
+ */
+ public function updates() : array
+ {
+ return $this->updates;
+ }
+
+ public function where(Condition $condition) : self
+ {
+ return new self($this->action, $this->target, $this->updates, $condition);
+ }
+
+ public function whereClause() : ?Condition
+ {
+ return $this->whereClause;
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/OrderBy.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/OrderBy.php
new file mode 100644
index 000000000..bb3485f6a
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/OrderBy.php
@@ -0,0 +1,81 @@
+getSortBy();
+
+ if ($sortBy === null) {
+ throw InvalidAstException::unexpectedNodeType('SortBy', 'unknown');
+ }
+
+ $nodeExpr = $sortBy->getNode();
+
+ if ($nodeExpr === null) {
+ throw InvalidAstException::missingRequiredField('node', 'SortBy');
+ }
+
+ $expression = ExpressionFactory::fromAst($nodeExpr);
+
+ $direction = SortDirection::fromProtobuf($sortBy->getSortbyDir());
+ $nullsPosition = NullsPosition::fromProtobuf($sortBy->getSortbyNulls());
+
+ return new self($expression, $direction, $nullsPosition);
+ }
+
+ public function getDirection() : SortDirection
+ {
+ return $this->direction;
+ }
+
+ public function getExpression() : Expression
+ {
+ return $this->expression;
+ }
+
+ public function getNullsPosition() : NullsPosition
+ {
+ return $this->nullsPosition;
+ }
+
+ public function toAst() : Node
+ {
+ $sortBy = new SortBy([
+ 'node' => $this->expression->toAst(),
+ 'sortby_dir' => $this->direction->toProtobuf(),
+ 'sortby_nulls' => $this->nullsPosition->toProtobuf(),
+ ]);
+
+ return new Node(['sort_by' => $sortBy]);
+ }
+
+ public function withDirection(SortDirection $direction) : self
+ {
+ return new self($this->expression, $direction, $this->nullsPosition);
+ }
+
+ public function withNullsPosition(NullsPosition $nullsPosition) : self
+ {
+ return new self($this->expression, $this->direction, $nullsPosition);
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/OrderByItem.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/OrderByItem.php
new file mode 100644
index 000000000..9707044b7
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/OrderByItem.php
@@ -0,0 +1,81 @@
+getNode();
+
+ if ($nodeExpr === null) {
+ throw InvalidAstException::missingRequiredField('node', 'SortBy');
+ }
+
+ $expression = ExpressionFactory::fromAst($nodeExpr);
+ $direction = SortDirection::fromProtobuf($node->getSortbyDir());
+ $nulls = NullsPosition::fromProtobuf($node->getSortbyNulls());
+
+ return new self($expression, $direction, $nulls);
+ }
+
+ public function asc() : self
+ {
+ return new self($this->expression, SortDirection::ASC, $this->nulls);
+ }
+
+ public function desc() : self
+ {
+ return new self($this->expression, SortDirection::DESC, $this->nulls);
+ }
+
+ public function direction() : SortDirection
+ {
+ return $this->direction;
+ }
+
+ public function expression() : Expression
+ {
+ return $this->expression;
+ }
+
+ public function nulls() : NullsPosition
+ {
+ return $this->nulls;
+ }
+
+ public function nullsFirst() : self
+ {
+ return new self($this->expression, $this->direction, NullsPosition::FIRST);
+ }
+
+ public function nullsLast() : self
+ {
+ return new self($this->expression, $this->direction, NullsPosition::LAST);
+ }
+
+ public function toAst() : SortBy
+ {
+ return new SortBy([
+ 'node' => $this->expression->toAst(),
+ 'sortby_dir' => $this->direction->toProtobuf(),
+ 'sortby_nulls' => $this->nulls->toProtobuf(),
+ ]);
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/ReturningClause.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/ReturningClause.php
new file mode 100644
index 000000000..c2ee24e3d
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/ReturningClause.php
@@ -0,0 +1,102 @@
+ $expressions
+ */
+ public function __construct(
+ private array $expressions,
+ ) {
+ }
+
+ public static function all() : self
+ {
+ return new self([Star::all()]);
+ }
+
+ public static function columns(string ...$columns) : self
+ {
+ $expressions = [];
+
+ foreach ($columns as $column) {
+ $expressions[] = Column::name($column);
+ }
+
+ return new self($expressions);
+ }
+
+ public static function fromAst(Node $node) : static
+ {
+ $resTarget = $node->getResTarget();
+
+ if ($resTarget === null) {
+ throw InvalidAstException::unexpectedNodeType('ResTarget', 'unknown');
+ }
+
+ $valNode = $resTarget->getVal();
+
+ if ($valNode === null) {
+ throw InvalidAstException::missingRequiredField('val', 'ResTarget');
+ }
+
+ $expression = ExpressionFactory::fromAst($valNode);
+
+ return new self([$expression]);
+ }
+
+ /**
+ * @return list
+ */
+ public static function toAstNodes(self $clause) : array
+ {
+ $nodes = [];
+
+ foreach ($clause->expressions as $expr) {
+ $resTarget = new ResTarget();
+ $resTarget->setVal($expr->toAst());
+
+ $node = new Node();
+ $node->setResTarget($resTarget);
+
+ $nodes[] = $node;
+ }
+
+ return $nodes;
+ }
+
+ /**
+ * @return list
+ */
+ public function expressions() : array
+ {
+ return $this->expressions;
+ }
+
+ public function toAst() : Node
+ {
+ if ($this->expressions === []) {
+ throw InvalidAstException::missingRequiredField('expressions', 'ReturningClause');
+ }
+
+ $resTarget = new ResTarget();
+ $resTarget->setVal($this->expressions[0]->toAst());
+
+ $node = new Node();
+ $node->setResTarget($resTarget);
+
+ return $node;
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/SortDirection.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/SortDirection.php
new file mode 100644
index 000000000..1731334e8
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/SortDirection.php
@@ -0,0 +1,35 @@
+ self::ASC,
+ SortByDir::SORTBY_DESC => self::DESC,
+ default => self::DEFAULT,
+ };
+ }
+
+ public function toProtobuf() : int
+ {
+ return match ($this) {
+ self::ASC => SortByDir::SORTBY_ASC,
+ self::DESC => SortByDir::SORTBY_DESC,
+ self::DEFAULT => SortByDir::SORTBY_DEFAULT,
+ };
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/WindowDefinition.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/WindowDefinition.php
new file mode 100644
index 000000000..77354f7cc
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/WindowDefinition.php
@@ -0,0 +1,174 @@
+ $partitionBy
+ * @param list $orderBy
+ */
+ public function __construct(
+ private string $name,
+ private array $partitionBy = [],
+ private array $orderBy = [],
+ private ?WindowFrame $frame = null,
+ private ?string $refName = null,
+ ) {
+ }
+
+ public static function fromAst(Node $node) : static
+ {
+ $windowDef = $node->getWindowDef();
+
+ if ($windowDef === null) {
+ throw InvalidAstException::unexpectedNodeType('WindowDef', 'unknown');
+ }
+
+ $name = $windowDef->getName();
+ $refName = $windowDef->getRefname();
+
+ if ($refName === '') {
+ $refName = null;
+ }
+
+ $partitionBy = [];
+ $partitionClause = $windowDef->getPartitionClause();
+
+ if ($partitionClause !== null) {
+ foreach ($partitionClause as $partNode) {
+ $partitionBy[] = ExpressionFactory::fromAst($partNode);
+ }
+ }
+
+ $orderBy = [];
+ $orderClause = $windowDef->getOrderClause();
+
+ if ($orderClause !== null) {
+ foreach ($orderClause as $orderNode) {
+ $orderBy[] = OrderBy::fromAst($orderNode);
+ }
+ }
+
+ $frame = null;
+
+ if ($windowDef->getFrameOptions() !== 0) {
+ $frame = WindowFrame::fromAst($node);
+ }
+
+ return new self($name, $partitionBy, $orderBy, $frame, $refName);
+ }
+
+ public function frame() : ?WindowFrame
+ {
+ return $this->frame;
+ }
+
+ public function name() : string
+ {
+ return $this->name;
+ }
+
+ /**
+ * @return list
+ */
+ public function orderBy() : array
+ {
+ return $this->orderBy;
+ }
+
+ /**
+ * @return list
+ */
+ public function partitionBy() : array
+ {
+ return $this->partitionBy;
+ }
+
+ public function refName() : ?string
+ {
+ return $this->refName;
+ }
+
+ public function toAst() : Node
+ {
+ $windowDef = new WindowDef();
+ $windowDef->setName($this->name);
+
+ if ($this->refName !== null) {
+ $windowDef->setRefname($this->refName);
+ }
+
+ if ($this->partitionBy !== []) {
+ $partitionNodes = [];
+
+ foreach ($this->partitionBy as $expr) {
+ $partitionNodes[] = $expr->toAst();
+ }
+
+ $windowDef->setPartitionClause($partitionNodes);
+ }
+
+ if ($this->orderBy !== []) {
+ $orderNodes = [];
+
+ foreach ($this->orderBy as $orderItem) {
+ if ($orderItem instanceof OrderByItem) {
+ $orderNodes[] = new Node(['sort_by' => $orderItem->toAst()]);
+ } else {
+ $orderNodes[] = $orderItem->toAst();
+ }
+ }
+
+ $windowDef->setOrderClause($orderNodes);
+ }
+
+ if ($this->frame !== null) {
+ $windowDef->setFrameOptions(0);
+
+ if ($this->frame->startBound()->offset() !== null) {
+ $windowDef->setStartOffset($this->frame->startBound()->toAst());
+ }
+
+ if ($this->frame->endBound() !== null && $this->frame->endBound()->offset() !== null) {
+ $windowDef->setEndOffset($this->frame->endBound()->toAst());
+ }
+ }
+
+ $node = new Node();
+ $node->setWindowDef($windowDef);
+
+ return $node;
+ }
+
+ public function withFrame(?WindowFrame $frame) : self
+ {
+ return new self($this->name, $this->partitionBy, $this->orderBy, $frame, $this->refName);
+ }
+
+ /**
+ * @param list $orderBy
+ */
+ public function withOrderBy(array $orderBy) : self
+ {
+ return new self($this->name, $this->partitionBy, $orderBy, $this->frame, $this->refName);
+ }
+
+ /**
+ * @param list $partitionBy
+ */
+ public function withPartitionBy(array $partitionBy) : self
+ {
+ return new self($this->name, $partitionBy, $this->orderBy, $this->frame, $this->refName);
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/WindowFrame.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/WindowFrame.php
new file mode 100644
index 000000000..0998236d9
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/WindowFrame.php
@@ -0,0 +1,75 @@
+endBound;
+ }
+
+ public function exclusion() : FrameExclusion
+ {
+ return $this->exclusion;
+ }
+
+ public function mode() : FrameMode
+ {
+ return $this->mode;
+ }
+
+ public function startBound() : FrameBound
+ {
+ return $this->startBound;
+ }
+
+ public function toAst() : Node
+ {
+ return new Node();
+ }
+
+ public function withExclusion(FrameExclusion $exclusion) : self
+ {
+ return new self($this->mode, $this->startBound, $this->endBound, $exclusion);
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/WithClause.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/WithClause.php
new file mode 100644
index 000000000..cccb63173
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Clause/WithClause.php
@@ -0,0 +1,86 @@
+ $ctes
+ */
+ public function __construct(
+ private array $ctes,
+ private bool $recursive = false,
+ ) {
+ }
+
+ public static function fromAst(Node $node) : static
+ {
+ $withClause = $node->getWithClause();
+
+ if ($withClause === null) {
+ throw InvalidAstException::unexpectedNodeType('WithClause', 'unknown');
+ }
+
+ $cteNodes = $withClause->getCtes();
+
+ if ($cteNodes === null || \count($cteNodes) === 0) {
+ throw InvalidAstException::missingRequiredField('ctes', 'WithClause');
+ }
+
+ $ctes = [];
+
+ foreach ($cteNodes as $cteNode) {
+ $ctes[] = CTE::fromAst($cteNode);
+ }
+
+ $recursive = $withClause->getRecursive();
+
+ return new self($ctes, $recursive);
+ }
+
+ public function add(CTE $cte) : self
+ {
+ return new self([...$this->ctes, $cte], $this->recursive);
+ }
+
+ /**
+ * @return array
+ */
+ public function ctes() : array
+ {
+ return $this->ctes;
+ }
+
+ public function recursive() : bool
+ {
+ return $this->recursive;
+ }
+
+ public function toAst() : Node
+ {
+ $withClause = new ProtobufWithClause();
+ $withClause->setRecursive($this->recursive);
+
+ $cteNodes = [];
+
+ foreach ($this->ctes as $cte) {
+ $cteNodes[] = $cte->toAst();
+ }
+
+ $withClause->setCtes($cteNodes);
+
+ $node = new Node();
+ $node->setWithClause($withClause);
+
+ return $node;
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/All.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/All.php
new file mode 100644
index 000000000..d369b370d
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/All.php
@@ -0,0 +1,177 @@
+hasSubLink()) {
+ $subLink = $node->getSubLink();
+
+ if ($subLink === null) {
+ throw InvalidAstException::unexpectedNodeType('SubLink', 'unknown');
+ }
+
+ if ($subLink->getSubLinkType() !== SubLinkType::ALL_SUBLINK) {
+ throw InvalidAstException::invalidFieldValue('sub_link_type', 'SubLink', 'Expected ALL_SUBLINK for All condition');
+ }
+
+ $testexpr = $subLink->getTestexpr();
+
+ if ($testexpr === null) {
+ throw InvalidAstException::missingRequiredField('testexpr', 'SubLink');
+ }
+
+ $subselect = $subLink->getSubselect();
+
+ if ($subselect === null) {
+ throw InvalidAstException::missingRequiredField('subselect', 'SubLink');
+ }
+
+ $operNames = $subLink->getOperName();
+
+ if ($operNames === null || $operNames->count() === 0) {
+ throw InvalidAstException::missingRequiredField('oper_name', 'SubLink');
+ }
+
+ $operNode = $operNames->offsetGet(0);
+ $stringNode = $operNode->getString();
+
+ if ($stringNode === null) {
+ throw InvalidAstException::unexpectedNodeType('String', 'unknown');
+ }
+
+ $operatorString = $stringNode->getSval();
+
+ $operator = match ($operatorString) {
+ '=' => ComparisonOperator::EQ,
+ '<>' => ComparisonOperator::NEQ,
+ '<' => ComparisonOperator::LT,
+ '<=' => ComparisonOperator::LTE,
+ '>' => ComparisonOperator::GT,
+ '>=' => ComparisonOperator::GTE,
+ default => throw InvalidAstException::invalidFieldValue('oper_name', 'SubLink', "Unsupported comparison operator: {$operatorString}"),
+ };
+
+ return new self(
+ ExpressionFactory::fromAst($testexpr),
+ $operator,
+ $subselect
+ );
+ }
+
+ if ($node->hasAExpr()) {
+ $aExpr = $node->getAExpr();
+
+ if ($aExpr === null) {
+ throw InvalidAstException::unexpectedNodeType('A_Expr', 'unknown');
+ }
+
+ if ($aExpr->getKind() !== A_Expr_Kind::AEXPR_OP_ALL) {
+ throw InvalidAstException::invalidFieldValue('kind', 'A_Expr', 'Expected AEXPR_OP_ALL for All condition');
+ }
+
+ $lexpr = $aExpr->getLexpr();
+
+ if ($lexpr === null) {
+ throw InvalidAstException::missingRequiredField('lexpr', 'A_Expr');
+ }
+
+ $rexpr = $aExpr->getRexpr();
+
+ if ($rexpr === null) {
+ throw InvalidAstException::missingRequiredField('rexpr', 'A_Expr');
+ }
+
+ $nameNodes = $aExpr->getName();
+
+ if ($nameNodes === null || $nameNodes->count() === 0) {
+ throw InvalidAstException::missingRequiredField('name', 'A_Expr');
+ }
+
+ $nameNode = $nameNodes->offsetGet(0);
+ $stringNode = $nameNode->getString();
+
+ if ($stringNode === null) {
+ throw InvalidAstException::unexpectedNodeType('String', 'unknown');
+ }
+
+ $operatorString = $stringNode->getSval();
+
+ $operator = match ($operatorString) {
+ '=' => ComparisonOperator::EQ,
+ '<>' => ComparisonOperator::NEQ,
+ '<' => ComparisonOperator::LT,
+ '<=' => ComparisonOperator::LTE,
+ '>' => ComparisonOperator::GT,
+ '>=' => ComparisonOperator::GTE,
+ default => throw InvalidAstException::invalidFieldValue('name', 'A_Expr', "Unsupported comparison operator: {$operatorString}"),
+ };
+
+ return new self(
+ ExpressionFactory::fromAst($lexpr),
+ $operator,
+ ExpressionFactory::fromAst($rexpr)
+ );
+ }
+
+ throw InvalidAstException::unexpectedNodeType('SubLink or A_Expr', 'unknown');
+ }
+
+ 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
+ {
+ if ($this->arrayOrSubquery instanceof Node) {
+ $subLink = new SubLink([
+ 'sub_link_type' => SubLinkType::ALL_SUBLINK,
+ 'subselect' => $this->arrayOrSubquery,
+ 'testexpr' => $this->expression->toAst(),
+ 'oper_name' => [
+ new Node(['string' => new PBString(['sval' => $this->operator->value])]),
+ ],
+ ]);
+
+ return new Node(['sub_link' => $subLink]);
+ }
+
+ $operatorString = new PBString(['sval' => $this->operator->value]);
+ $operatorNode = new Node(['string' => $operatorString]);
+
+ $aExpr = new A_Expr([
+ 'kind' => A_Expr_Kind::AEXPR_OP_ALL,
+ 'name' => [$operatorNode],
+ 'lexpr' => $this->expression->toAst(),
+ 'rexpr' => $this->arrayOrSubquery->toAst(),
+ ]);
+
+ return new Node(['a_expr' => $aExpr]);
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/AndCondition.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/AndCondition.php
new file mode 100644
index 000000000..01460f1ae
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/AndCondition.php
@@ -0,0 +1,148 @@
+
+ */
+ private array $conditions;
+
+ public function __construct(
+ Condition ...$conditions,
+ ) {
+ $this->conditions = $conditions;
+ }
+
+ public static function fromAst(Node $node) : static
+ {
+ if (!$node->hasBoolExpr()) {
+ throw InvalidAstException::unexpectedNodeType('BoolExpr', 'unknown');
+ }
+
+ $boolExpr = $node->getBoolExpr();
+
+ if ($boolExpr === null) {
+ throw InvalidAstException::missingRequiredField('bool_expr', 'Node');
+ }
+
+ if ($boolExpr->getBoolop() !== BoolExprType::AND_EXPR) {
+ throw InvalidAstException::unexpectedNodeType(
+ 'BoolExpr with AND_EXPR',
+ 'BoolExpr with ' . BoolExprType::name($boolExpr->getBoolop())
+ );
+ }
+
+ $conditions = [];
+
+ foreach ($boolExpr->getArgs() as $argNode) {
+ $conditions[] = self::conditionFromNode($argNode);
+ }
+
+ return new self(...$conditions);
+ }
+
+ public function and(Condition $other) : self
+ {
+ if ($other instanceof self) {
+ return new self(...[...$this->conditions, ...$other->conditions]);
+ }
+
+ return new self(...[...$this->conditions, $other]);
+ }
+
+ public function not() : NotCondition
+ {
+ return new NotCondition($this);
+ }
+
+ public function or(Condition $other) : OrCondition
+ {
+ return new OrCondition($this, $other);
+ }
+
+ public function toAst() : Node
+ {
+ $boolExpr = new BoolExpr();
+ $boolExpr->setBoolop(BoolExprType::AND_EXPR);
+
+ $args = [];
+
+ foreach ($this->conditions as $condition) {
+ $args[] = $condition->toAst();
+ }
+
+ $boolExpr->setArgs($args);
+
+ $node = new Node();
+ $node->setBoolExpr($boolExpr);
+
+ return $node;
+ }
+
+ private static function conditionFromNode(Node $node) : Condition
+ {
+ if ($node->hasBoolExpr()) {
+ $boolExpr = $node->getBoolExpr();
+
+ if ($boolExpr === null) {
+ throw InvalidAstException::missingRequiredField('bool_expr', 'Node');
+ }
+
+ return match ($boolExpr->getBoolop()) {
+ BoolExprType::AND_EXPR => self::fromAst($node),
+ BoolExprType::OR_EXPR => OrCondition::fromAst($node),
+ BoolExprType::NOT_EXPR => NotCondition::fromAst($node),
+ default => throw UnsupportedNodeException::forNodeType('BoolExpr with ' . BoolExprType::name($boolExpr->getBoolop())),
+ };
+ }
+
+ if ($node->hasAExpr()) {
+ $aExpr = $node->getAExpr();
+
+ if ($aExpr === null) {
+ throw InvalidAstException::missingRequiredField('a_expr', 'Node');
+ }
+
+ return match ($aExpr->getKind()) {
+ A_Expr_Kind::AEXPR_OP => Comparison::fromAst($node),
+ A_Expr_Kind::AEXPR_LIKE => Like::fromAst($node),
+ A_Expr_Kind::AEXPR_ILIKE => Like::fromAst($node),
+ A_Expr_Kind::AEXPR_SIMILAR => SimilarTo::fromAst($node),
+ A_Expr_Kind::AEXPR_DISTINCT => IsDistinctFrom::fromAst($node),
+ A_Expr_Kind::AEXPR_NOT_DISTINCT => IsDistinctFrom::fromAst($node),
+ A_Expr_Kind::AEXPR_OP_ANY => Any::fromAst($node),
+ A_Expr_Kind::AEXPR_OP_ALL => All::fromAst($node),
+ A_Expr_Kind::AEXPR_BETWEEN => Between::fromAst($node),
+ A_Expr_Kind::AEXPR_NOT_BETWEEN => Between::fromAst($node),
+ A_Expr_Kind::AEXPR_BETWEEN_SYM => Between::fromAst($node),
+ A_Expr_Kind::AEXPR_NOT_BETWEEN_SYM => Between::fromAst($node),
+ default => throw UnsupportedNodeException::forNodeType('A_Expr with kind: ' . A_Expr_Kind::name($aExpr->getKind())),
+ };
+ }
+
+ if ($node->hasSubLink()) {
+ $subLink = $node->getSubLink();
+
+ if ($subLink === null) {
+ throw InvalidAstException::missingRequiredField('sub_link', 'Node');
+ }
+
+ return match ($subLink->getSubLinkType()) {
+ SubLinkType::EXISTS_SUBLINK => Exists::fromAst($node),
+ SubLinkType::ANY_SUBLINK => Any::fromAst($node),
+ SubLinkType::ALL_SUBLINK => All::fromAst($node),
+ default => throw UnsupportedNodeException::forNodeType('SubLink with type: ' . SubLinkType::name($subLink->getSubLinkType())),
+ };
+ }
+
+ throw UnsupportedNodeException::forNodeType('unknown node type in condition');
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/Any.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/Any.php
new file mode 100644
index 000000000..43c1404b4
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/Any.php
@@ -0,0 +1,177 @@
+hasSubLink()) {
+ $subLink = $node->getSubLink();
+
+ if ($subLink === null) {
+ throw InvalidAstException::unexpectedNodeType('SubLink', 'unknown');
+ }
+
+ if ($subLink->getSubLinkType() !== SubLinkType::ANY_SUBLINK) {
+ throw InvalidAstException::invalidFieldValue('sub_link_type', 'SubLink', 'Expected ANY_SUBLINK for Any condition');
+ }
+
+ $testexpr = $subLink->getTestexpr();
+
+ if ($testexpr === null) {
+ throw InvalidAstException::missingRequiredField('testexpr', 'SubLink');
+ }
+
+ $subselect = $subLink->getSubselect();
+
+ if ($subselect === null) {
+ throw InvalidAstException::missingRequiredField('subselect', 'SubLink');
+ }
+
+ $operNames = $subLink->getOperName();
+
+ if ($operNames === null || $operNames->count() === 0) {
+ throw InvalidAstException::missingRequiredField('oper_name', 'SubLink');
+ }
+
+ $operNode = $operNames->offsetGet(0);
+ $stringNode = $operNode->getString();
+
+ if ($stringNode === null) {
+ throw InvalidAstException::unexpectedNodeType('String', 'unknown');
+ }
+
+ $operatorString = $stringNode->getSval();
+
+ $operator = match ($operatorString) {
+ '=' => ComparisonOperator::EQ,
+ '<>' => ComparisonOperator::NEQ,
+ '<' => ComparisonOperator::LT,
+ '<=' => ComparisonOperator::LTE,
+ '>' => ComparisonOperator::GT,
+ '>=' => ComparisonOperator::GTE,
+ default => throw InvalidAstException::invalidFieldValue('oper_name', 'SubLink', "Unsupported comparison operator: {$operatorString}"),
+ };
+
+ return new self(
+ ExpressionFactory::fromAst($testexpr),
+ $operator,
+ $subselect
+ );
+ }
+
+ if ($node->hasAExpr()) {
+ $aExpr = $node->getAExpr();
+
+ if ($aExpr === null) {
+ throw InvalidAstException::unexpectedNodeType('A_Expr', 'unknown');
+ }
+
+ if ($aExpr->getKind() !== A_Expr_Kind::AEXPR_OP_ANY) {
+ throw InvalidAstException::invalidFieldValue('kind', 'A_Expr', 'Expected AEXPR_OP_ANY for Any condition');
+ }
+
+ $lexpr = $aExpr->getLexpr();
+
+ if ($lexpr === null) {
+ throw InvalidAstException::missingRequiredField('lexpr', 'A_Expr');
+ }
+
+ $rexpr = $aExpr->getRexpr();
+
+ if ($rexpr === null) {
+ throw InvalidAstException::missingRequiredField('rexpr', 'A_Expr');
+ }
+
+ $nameNodes = $aExpr->getName();
+
+ if ($nameNodes === null || $nameNodes->count() === 0) {
+ throw InvalidAstException::missingRequiredField('name', 'A_Expr');
+ }
+
+ $nameNode = $nameNodes->offsetGet(0);
+ $stringNode = $nameNode->getString();
+
+ if ($stringNode === null) {
+ throw InvalidAstException::unexpectedNodeType('String', 'unknown');
+ }
+
+ $operatorString = $stringNode->getSval();
+
+ $operator = match ($operatorString) {
+ '=' => ComparisonOperator::EQ,
+ '<>' => ComparisonOperator::NEQ,
+ '<' => ComparisonOperator::LT,
+ '<=' => ComparisonOperator::LTE,
+ '>' => ComparisonOperator::GT,
+ '>=' => ComparisonOperator::GTE,
+ default => throw InvalidAstException::invalidFieldValue('name', 'A_Expr', "Unsupported comparison operator: {$operatorString}"),
+ };
+
+ return new self(
+ ExpressionFactory::fromAst($lexpr),
+ $operator,
+ ExpressionFactory::fromAst($rexpr)
+ );
+ }
+
+ throw InvalidAstException::unexpectedNodeType('SubLink or A_Expr', 'unknown');
+ }
+
+ 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
+ {
+ if ($this->arrayOrSubquery instanceof Node) {
+ $subLink = new SubLink([
+ 'sub_link_type' => SubLinkType::ANY_SUBLINK,
+ 'subselect' => $this->arrayOrSubquery,
+ 'testexpr' => $this->expression->toAst(),
+ 'oper_name' => [
+ new Node(['string' => new PBString(['sval' => $this->operator->value])]),
+ ],
+ ]);
+
+ return new Node(['sub_link' => $subLink]);
+ }
+
+ $operatorString = new PBString(['sval' => $this->operator->value]);
+ $operatorNode = new Node(['string' => $operatorString]);
+
+ $aExpr = new A_Expr([
+ 'kind' => A_Expr_Kind::AEXPR_OP_ANY,
+ 'name' => [$operatorNode],
+ 'lexpr' => $this->expression->toAst(),
+ 'rexpr' => $this->arrayOrSubquery->toAst(),
+ ]);
+
+ return new Node(['a_expr' => $aExpr]);
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/Between.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/Between.php
new file mode 100644
index 000000000..63bd0814f
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/Between.php
@@ -0,0 +1,123 @@
+getAExpr();
+
+ if ($aExpr === null) {
+ throw InvalidAstException::unexpectedNodeType('A_Expr', 'unknown');
+ }
+
+ $kind = $aExpr->getKind();
+
+ if (
+ $kind !== A_Expr_Kind::AEXPR_BETWEEN
+ && $kind !== A_Expr_Kind::AEXPR_NOT_BETWEEN
+ && $kind !== A_Expr_Kind::AEXPR_BETWEEN_SYM
+ && $kind !== A_Expr_Kind::AEXPR_NOT_BETWEEN_SYM
+ ) {
+ throw InvalidAstException::invalidFieldValue('kind', 'A_Expr', 'Expected BETWEEN variant for Between condition');
+ }
+
+ $symmetric = $kind === A_Expr_Kind::AEXPR_BETWEEN_SYM || $kind === A_Expr_Kind::AEXPR_NOT_BETWEEN_SYM;
+ $negated = $kind === A_Expr_Kind::AEXPR_NOT_BETWEEN || $kind === A_Expr_Kind::AEXPR_NOT_BETWEEN_SYM;
+
+ $lexpr = $aExpr->getLexpr();
+
+ if ($lexpr === null) {
+ throw InvalidAstException::missingRequiredField('lexpr', 'A_Expr');
+ }
+
+ $rexpr = $aExpr->getRexpr();
+
+ if ($rexpr === null) {
+ throw InvalidAstException::missingRequiredField('rexpr', 'A_Expr');
+ }
+
+ $list = $rexpr->getList();
+
+ if ($list === null) {
+ throw InvalidAstException::unexpectedNodeType('List', 'unknown');
+ }
+
+ $items = $list->getItems();
+
+ if ($items === null || $items->count() !== 2) {
+ throw InvalidAstException::invalidFieldValue('rexpr', 'A_Expr', 'Expected List with exactly 2 items for BETWEEN');
+ }
+
+ return new self(
+ ExpressionFactory::fromAst($lexpr),
+ ExpressionFactory::fromAst($items->offsetGet(0)),
+ ExpressionFactory::fromAst($items->offsetGet(1)),
+ $symmetric,
+ $negated
+ );
+ }
+
+ 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
+ {
+ $kind = match (true) {
+ $this->symmetric && $this->negated => A_Expr_Kind::AEXPR_NOT_BETWEEN_SYM,
+ $this->symmetric => A_Expr_Kind::AEXPR_BETWEEN_SYM,
+ $this->negated => A_Expr_Kind::AEXPR_NOT_BETWEEN,
+ default => A_Expr_Kind::AEXPR_BETWEEN,
+ };
+
+ $list = new PBList([
+ 'items' => [
+ $this->low->toAst(),
+ $this->high->toAst(),
+ ],
+ ]);
+
+ $listNode = new Node(['list' => $list]);
+
+ $nameString = new PBString();
+ $nameString->setSval('BETWEEN');
+ $nameNode = new Node(['string' => $nameString]);
+
+ $aExpr = new A_Expr([
+ 'kind' => $kind,
+ 'name' => [$nameNode],
+ 'lexpr' => $this->expression->toAst(),
+ 'rexpr' => $listNode,
+ ]);
+
+ return new Node(['a_expr' => $aExpr]);
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/Comparison.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/Comparison.php
new file mode 100644
index 000000000..0bdff5941
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/Comparison.php
@@ -0,0 +1,104 @@
+getAExpr();
+
+ if ($aExpr === null) {
+ throw InvalidAstException::unexpectedNodeType('A_Expr', 'unknown');
+ }
+
+ if ($aExpr->getKind() !== A_Expr_Kind::AEXPR_OP) {
+ throw InvalidAstException::invalidFieldValue('kind', 'A_Expr', 'Expected AEXPR_OP for Comparison');
+ }
+
+ $lexpr = $aExpr->getLexpr();
+ $rexpr = $aExpr->getRexpr();
+
+ if ($lexpr === null) {
+ throw InvalidAstException::missingRequiredField('lexpr', 'A_Expr');
+ }
+
+ if ($rexpr === null) {
+ throw InvalidAstException::missingRequiredField('rexpr', 'A_Expr');
+ }
+
+ $nameNodes = $aExpr->getName();
+
+ if ($nameNodes === null || $nameNodes->count() === 0) {
+ throw InvalidAstException::missingRequiredField('name', 'A_Expr');
+ }
+
+ $nameNode = $nameNodes->offsetGet(0);
+ $stringNode = $nameNode->getString();
+
+ if ($stringNode === null) {
+ throw InvalidAstException::unexpectedNodeType('String', 'unknown');
+ }
+
+ $operatorString = $stringNode->getSval();
+
+ $operator = match ($operatorString) {
+ '=' => ComparisonOperator::EQ,
+ '<>' => ComparisonOperator::NEQ,
+ '<' => ComparisonOperator::LT,
+ '<=' => ComparisonOperator::LTE,
+ '>' => ComparisonOperator::GT,
+ '>=' => ComparisonOperator::GTE,
+ default => throw InvalidAstException::invalidFieldValue('name', 'A_Expr', "Unsupported comparison operator: {$operatorString}"),
+ };
+
+ return new self(
+ ExpressionFactory::fromAst($lexpr),
+ $operator,
+ ExpressionFactory::fromAst($rexpr)
+ );
+ }
+
+ 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
+ {
+ $operatorString = new PBString(['sval' => $this->operator->value]);
+ $operatorNode = new Node(['string' => $operatorString]);
+
+ $aExpr = new A_Expr([
+ 'kind' => A_Expr_Kind::AEXPR_OP,
+ 'name' => [$operatorNode],
+ 'lexpr' => $this->left->toAst(),
+ 'rexpr' => $this->right->toAst(),
+ ]);
+
+ return new Node(['a_expr' => $aExpr]);
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/ComparisonOperator.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/ComparisonOperator.php
new file mode 100644
index 000000000..6a988de7b
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/ComparisonOperator.php
@@ -0,0 +1,18 @@
+';
+ case GTE = '>=';
+ case LT = '<';
+ case LTE = '<=';
+ case NEQ = '<>';
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/Condition.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/Condition.php
new file mode 100644
index 000000000..9e4e232ea
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/Condition.php
@@ -0,0 +1,19 @@
+getAExpr() !== null) {
+ $aExpr = $node->getAExpr();
+ $kind = $aExpr->getKind();
+
+ return match ($kind) {
+ A_Expr_Kind::AEXPR_OP => self::parseOperatorCondition($node),
+ A_Expr_Kind::AEXPR_LIKE => Like::fromAst($node),
+ A_Expr_Kind::AEXPR_ILIKE => Like::fromAst($node),
+ A_Expr_Kind::AEXPR_SIMILAR => SimilarTo::fromAst($node),
+ A_Expr_Kind::AEXPR_BETWEEN => Between::fromAst($node),
+ A_Expr_Kind::AEXPR_NOT_BETWEEN => Between::fromAst($node),
+ A_Expr_Kind::AEXPR_IN => In::fromAst($node),
+ A_Expr_Kind::AEXPR_OP_ANY => Any::fromAst($node),
+ A_Expr_Kind::AEXPR_OP_ALL => All::fromAst($node),
+ A_Expr_Kind::AEXPR_DISTINCT => IsDistinctFrom::fromAst($node),
+ A_Expr_Kind::AEXPR_NOT_DISTINCT => IsDistinctFrom::fromAst($node),
+ default => throw UnsupportedNodeException::forNodeType("A_Expr kind: {$kind}"),
+ };
+ }
+
+ if ($node->getBoolExpr() !== null) {
+ $boolExpr = $node->getBoolExpr();
+ $boolOp = $boolExpr->getBoolop();
+
+ return match ($boolOp) {
+ BoolExprType::AND_EXPR => AndCondition::fromAst($node),
+ BoolExprType::OR_EXPR => OrCondition::fromAst($node),
+ BoolExprType::NOT_EXPR => NotCondition::fromAst($node),
+ default => throw UnsupportedNodeException::forNodeType("BoolExpr type: {$boolOp}"),
+ };
+ }
+
+ if ($node->getNullTest() !== null) {
+ return IsNull::fromAst($node);
+ }
+
+ if ($node->getSubLink() !== null) {
+ $subLink = $node->getSubLink();
+ $subLinkType = $subLink->getSubLinkType();
+
+ return match ($subLinkType) {
+ SubLinkType::EXISTS_SUBLINK => Exists::fromAst($node),
+ SubLinkType::ANY_SUBLINK => Any::fromAst($node),
+ SubLinkType::ALL_SUBLINK => All::fromAst($node),
+ default => throw UnsupportedNodeException::forNodeType("SubLink type: {$subLinkType}"),
+ };
+ }
+
+ if ($node->getTypeCast() !== null) {
+ return RawCondition::fromTypeCast($node);
+ }
+
+ if ($node->getAConst() !== null) {
+ return RawCondition::fromAConst($node);
+ }
+
+ throw UnsupportedNodeException::forNodeType('Unknown condition node type');
+ }
+
+ /**
+ * Parse an AEXPR_OP node, trying Comparison first for standard operators,
+ * falling back to OperatorCondition for other operators.
+ */
+ private static function parseOperatorCondition(Node $node) : Condition
+ {
+ $aExpr = $node->getAExpr();
+
+ if ($aExpr === null) {
+ return OperatorCondition::fromAst($node);
+ }
+
+ $nameNodes = $aExpr->getName();
+
+ if ($nameNodes !== null && $nameNodes->count() > 0) {
+ $nameNode = $nameNodes->offsetGet(0);
+ $stringNode = $nameNode->getString();
+
+ if ($stringNode !== null) {
+ $operator = $stringNode->getSval();
+
+ if (\in_array($operator, ['=', '<>', '<', '<=', '>', '>='], true)) {
+ return Comparison::fromAst($node);
+ }
+ }
+ }
+
+ return OperatorCondition::fromAst($node);
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/Exists.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/Exists.php
new file mode 100644
index 000000000..7c3bff8a3
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/Exists.php
@@ -0,0 +1,62 @@
+getSubLink();
+
+ if ($subLink === null) {
+ throw InvalidAstException::unexpectedNodeType('SubLink', 'unknown');
+ }
+
+ if ($subLink->getSubLinkType() !== SubLinkType::EXISTS_SUBLINK) {
+ throw InvalidAstException::invalidFieldValue('sub_link_type', 'SubLink', 'Expected EXISTS_SUBLINK for Exists condition');
+ }
+
+ $subselect = $subLink->getSubselect();
+
+ if ($subselect === null) {
+ throw InvalidAstException::missingRequiredField('subselect', 'SubLink');
+ }
+
+ return new self($subselect);
+ }
+
+ 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
+ {
+ $subLink = new SubLink([
+ 'sub_link_type' => SubLinkType::EXISTS_SUBLINK,
+ 'subselect' => $this->subquery,
+ ]);
+
+ return new Node(['sub_link' => $subLink]);
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/In.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/In.php
new file mode 100644
index 000000000..ab434f6f8
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/In.php
@@ -0,0 +1,110 @@
+ $values
+ */
+ public function __construct(
+ public Expression $expression,
+ public array $values,
+ ) {
+ }
+
+ public static function fromAst(Node $node) : static
+ {
+ $aExpr = $node->getAExpr();
+
+ if ($aExpr === null) {
+ throw InvalidAstException::unexpectedNodeType('A_Expr', 'unknown');
+ }
+
+ if ($aExpr->getKind() !== A_Expr_Kind::AEXPR_IN) {
+ throw InvalidAstException::invalidFieldValue('kind', 'A_Expr', 'Expected AEXPR_IN for In condition');
+ }
+
+ $lexpr = $aExpr->getLexpr();
+
+ if ($lexpr === null) {
+ throw InvalidAstException::missingRequiredField('lexpr', 'A_Expr');
+ }
+
+ $rexpr = $aExpr->getRexpr();
+
+ if ($rexpr === null) {
+ throw InvalidAstException::missingRequiredField('rexpr', 'A_Expr');
+ }
+
+ $list = $rexpr->getList();
+
+ if ($list === null) {
+ throw InvalidAstException::unexpectedNodeType('List', 'unknown');
+ }
+
+ $items = $list->getItems();
+
+ if ($items === null) {
+ throw InvalidAstException::missingRequiredField('items', 'List');
+ }
+
+ $values = [];
+
+ foreach ($items as $item) {
+ $values[] = ExpressionFactory::fromAst($item);
+ }
+
+ return new self(
+ ExpressionFactory::fromAst($lexpr),
+ $values
+ );
+ }
+
+ 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
+ {
+ $valueNodes = [];
+
+ foreach ($this->values as $value) {
+ $valueNodes[] = $value->toAst();
+ }
+
+ $list = new PBList(['items' => $valueNodes]);
+ $listNode = new Node(['list' => $list]);
+
+ $nameString = new PBString();
+ $nameString->setSval('=');
+ $nameNode = new Node(['string' => $nameString]);
+
+ $aExpr = new A_Expr([
+ 'kind' => A_Expr_Kind::AEXPR_IN,
+ 'name' => [$nameNode],
+ 'lexpr' => $this->expression->toAst(),
+ 'rexpr' => $listNode,
+ ]);
+
+ return new Node(['a_expr' => $aExpr]);
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/IsDistinctFrom.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/IsDistinctFrom.php
new file mode 100644
index 000000000..ea7ba19e4
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/IsDistinctFrom.php
@@ -0,0 +1,86 @@
+getAExpr();
+
+ if ($aExpr === null) {
+ throw InvalidAstException::unexpectedNodeType('A_Expr', 'unknown');
+ }
+
+ $kind = $aExpr->getKind();
+
+ if ($kind !== A_Expr_Kind::AEXPR_DISTINCT && $kind !== A_Expr_Kind::AEXPR_NOT_DISTINCT) {
+ throw InvalidAstException::invalidFieldValue('kind', 'A_Expr', 'Expected AEXPR_DISTINCT or AEXPR_NOT_DISTINCT for IsDistinctFrom condition');
+ }
+
+ $negated = $kind === A_Expr_Kind::AEXPR_NOT_DISTINCT;
+
+ $lexpr = $aExpr->getLexpr();
+
+ if ($lexpr === null) {
+ throw InvalidAstException::missingRequiredField('lexpr', 'A_Expr');
+ }
+
+ $rexpr = $aExpr->getRexpr();
+
+ if ($rexpr === null) {
+ throw InvalidAstException::missingRequiredField('rexpr', 'A_Expr');
+ }
+
+ return new self(
+ ExpressionFactory::fromAst($lexpr),
+ ExpressionFactory::fromAst($rexpr),
+ $negated
+ );
+ }
+
+ 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
+ {
+ $kind = $this->negated ? A_Expr_Kind::AEXPR_NOT_DISTINCT : A_Expr_Kind::AEXPR_DISTINCT;
+
+ $operatorString = new PBString(['sval' => '=']);
+ $operatorNode = new Node(['string' => $operatorString]);
+
+ $aExpr = new A_Expr([
+ 'kind' => $kind,
+ 'name' => [$operatorNode],
+ 'lexpr' => $this->left->toAst(),
+ 'rexpr' => $this->right->toAst(),
+ ]);
+
+ return new Node(['a_expr' => $aExpr]);
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/IsNull.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/IsNull.php
new file mode 100644
index 000000000..fe3f3a32c
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/IsNull.php
@@ -0,0 +1,73 @@
+getNullTest();
+
+ if ($nullTest === null) {
+ throw InvalidAstException::unexpectedNodeType('NullTest', 'unknown');
+ }
+
+ $arg = $nullTest->getArg();
+
+ if ($arg === null) {
+ throw InvalidAstException::missingRequiredField('arg', 'NullTest');
+ }
+
+ $nullTestType = $nullTest->getNulltesttype();
+
+ if ($nullTestType !== NullTestType::IS_NULL && $nullTestType !== NullTestType::IS_NOT_NULL) {
+ throw InvalidAstException::invalidFieldValue('nulltesttype', 'NullTest', 'Expected IS_NULL or IS_NOT_NULL');
+ }
+
+ $negated = $nullTestType === NullTestType::IS_NOT_NULL;
+
+ return new self(
+ ExpressionFactory::fromAst($arg),
+ $negated
+ );
+ }
+
+ 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
+ {
+ $nullTestType = $this->negated ? NullTestType::IS_NOT_NULL : NullTestType::IS_NULL;
+
+ $nullTest = new NullTest([
+ 'arg' => $this->expression->toAst(),
+ 'nulltesttype' => $nullTestType,
+ ]);
+
+ return new Node(['null_test' => $nullTest]);
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/Like.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/Like.php
new file mode 100644
index 000000000..e95860ecf
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/Like.php
@@ -0,0 +1,88 @@
+getAExpr();
+
+ if ($aExpr === null) {
+ throw InvalidAstException::unexpectedNodeType('A_Expr', 'unknown');
+ }
+
+ $kind = $aExpr->getKind();
+
+ if ($kind !== A_Expr_Kind::AEXPR_LIKE && $kind !== A_Expr_Kind::AEXPR_ILIKE) {
+ throw InvalidAstException::invalidFieldValue('kind', 'A_Expr', 'Expected AEXPR_LIKE or AEXPR_ILIKE for Like condition');
+ }
+
+ $caseInsensitive = $kind === A_Expr_Kind::AEXPR_ILIKE;
+
+ $lexpr = $aExpr->getLexpr();
+
+ if ($lexpr === null) {
+ throw InvalidAstException::missingRequiredField('lexpr', 'A_Expr');
+ }
+
+ $rexpr = $aExpr->getRexpr();
+
+ if ($rexpr === null) {
+ throw InvalidAstException::missingRequiredField('rexpr', 'A_Expr');
+ }
+
+ return new self(
+ ExpressionFactory::fromAst($lexpr),
+ ExpressionFactory::fromAst($rexpr),
+ $caseInsensitive,
+ null
+ );
+ }
+
+ 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
+ {
+ $kind = $this->caseInsensitive ? A_Expr_Kind::AEXPR_ILIKE : A_Expr_Kind::AEXPR_LIKE;
+
+ $operatorString = new PBString(['sval' => $this->caseInsensitive ? '~~*' : '~~']);
+ $operatorNode = new Node(['string' => $operatorString]);
+
+ $aExpr = new A_Expr([
+ 'kind' => $kind,
+ 'name' => [$operatorNode],
+ 'lexpr' => $this->expression->toAst(),
+ 'rexpr' => $this->pattern->toAst(),
+ ]);
+
+ return new Node(['a_expr' => $aExpr]);
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/NotCondition.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/NotCondition.php
new file mode 100644
index 000000000..7a143f228
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/NotCondition.php
@@ -0,0 +1,137 @@
+hasBoolExpr()) {
+ throw InvalidAstException::unexpectedNodeType('BoolExpr', 'unknown');
+ }
+
+ $boolExpr = $node->getBoolExpr();
+
+ if ($boolExpr === null) {
+ throw InvalidAstException::missingRequiredField('bool_expr', 'Node');
+ }
+
+ if ($boolExpr->getBoolop() !== BoolExprType::NOT_EXPR) {
+ throw InvalidAstException::unexpectedNodeType(
+ 'BoolExpr with NOT_EXPR',
+ 'BoolExpr with ' . BoolExprType::name($boolExpr->getBoolop())
+ );
+ }
+
+ $args = $boolExpr->getArgs();
+
+ if (\count($args) !== 1) {
+ throw InvalidAstException::invalidFieldValue(
+ 'args',
+ 'BoolExpr',
+ 'NOT_EXPR must have exactly one argument, got ' . \count($args)
+ );
+ }
+
+ $argNode = $args[0];
+
+ return new self(self::conditionFromNode($argNode));
+ }
+
+ public function and(Condition $other) : AndCondition
+ {
+ return new AndCondition($this, $other);
+ }
+
+ public function not() : self
+ {
+ return new self($this);
+ }
+
+ public function or(Condition $other) : OrCondition
+ {
+ return new OrCondition($this, $other);
+ }
+
+ public function toAst() : Node
+ {
+ $boolExpr = new BoolExpr();
+ $boolExpr->setBoolop(BoolExprType::NOT_EXPR);
+ $boolExpr->setArgs([$this->condition->toAst()]);
+
+ $node = new Node();
+ $node->setBoolExpr($boolExpr);
+
+ return $node;
+ }
+
+ private static function conditionFromNode(Node $node) : Condition
+ {
+ if ($node->hasBoolExpr()) {
+ $boolExpr = $node->getBoolExpr();
+
+ if ($boolExpr === null) {
+ throw InvalidAstException::missingRequiredField('bool_expr', 'Node');
+ }
+
+ return match ($boolExpr->getBoolop()) {
+ BoolExprType::AND_EXPR => AndCondition::fromAst($node),
+ BoolExprType::OR_EXPR => OrCondition::fromAst($node),
+ BoolExprType::NOT_EXPR => self::fromAst($node),
+ default => throw UnsupportedNodeException::forNodeType('BoolExpr with ' . BoolExprType::name($boolExpr->getBoolop())),
+ };
+ }
+
+ if ($node->hasAExpr()) {
+ $aExpr = $node->getAExpr();
+
+ if ($aExpr === null) {
+ throw InvalidAstException::missingRequiredField('a_expr', 'Node');
+ }
+
+ return match ($aExpr->getKind()) {
+ A_Expr_Kind::AEXPR_OP => Comparison::fromAst($node),
+ A_Expr_Kind::AEXPR_LIKE => Like::fromAst($node),
+ A_Expr_Kind::AEXPR_ILIKE => Like::fromAst($node),
+ A_Expr_Kind::AEXPR_SIMILAR => SimilarTo::fromAst($node),
+ A_Expr_Kind::AEXPR_DISTINCT => IsDistinctFrom::fromAst($node),
+ A_Expr_Kind::AEXPR_NOT_DISTINCT => IsDistinctFrom::fromAst($node),
+ A_Expr_Kind::AEXPR_OP_ANY => Any::fromAst($node),
+ A_Expr_Kind::AEXPR_OP_ALL => All::fromAst($node),
+ A_Expr_Kind::AEXPR_BETWEEN => Between::fromAst($node),
+ A_Expr_Kind::AEXPR_NOT_BETWEEN => Between::fromAst($node),
+ A_Expr_Kind::AEXPR_BETWEEN_SYM => Between::fromAst($node),
+ A_Expr_Kind::AEXPR_NOT_BETWEEN_SYM => Between::fromAst($node),
+ default => throw UnsupportedNodeException::forNodeType('A_Expr with kind: ' . A_Expr_Kind::name($aExpr->getKind())),
+ };
+ }
+
+ if ($node->hasSubLink()) {
+ $subLink = $node->getSubLink();
+
+ if ($subLink === null) {
+ throw InvalidAstException::missingRequiredField('sub_link', 'Node');
+ }
+
+ return match ($subLink->getSubLinkType()) {
+ SubLinkType::EXISTS_SUBLINK => Exists::fromAst($node),
+ SubLinkType::ANY_SUBLINK => Any::fromAst($node),
+ SubLinkType::ALL_SUBLINK => All::fromAst($node),
+ default => throw UnsupportedNodeException::forNodeType('SubLink with type: ' . SubLinkType::name($subLink->getSubLinkType())),
+ };
+ }
+
+ throw UnsupportedNodeException::forNodeType('unknown node type in condition');
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/OperatorCondition.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/OperatorCondition.php
new file mode 100644
index 000000000..db10d3539
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/OperatorCondition.php
@@ -0,0 +1,98 @@
+, <@, &&, ~, @@).
+ *
+ * Unlike Comparison which only supports standard comparison operators (=, <>, <, <=, >, >=),
+ * OperatorCondition accepts any valid PostgreSQL operator string.
+ */
+final readonly class OperatorCondition implements Condition
+{
+ public function __construct(
+ public Expression $left,
+ public string $operator,
+ public Expression $right,
+ ) {
+ }
+
+ public static function fromAst(Node $node) : static
+ {
+ $aExpr = $node->getAExpr();
+
+ if ($aExpr === null) {
+ throw InvalidAstException::unexpectedNodeType('A_Expr', 'unknown');
+ }
+
+ if ($aExpr->getKind() !== A_Expr_Kind::AEXPR_OP) {
+ throw InvalidAstException::invalidFieldValue('kind', 'A_Expr', 'Expected AEXPR_OP for OperatorCondition');
+ }
+
+ $lexpr = $aExpr->getLexpr();
+ $rexpr = $aExpr->getRexpr();
+
+ if ($lexpr === null) {
+ throw InvalidAstException::missingRequiredField('lexpr', 'A_Expr');
+ }
+
+ if ($rexpr === null) {
+ throw InvalidAstException::missingRequiredField('rexpr', 'A_Expr');
+ }
+
+ $nameNodes = $aExpr->getName();
+
+ if ($nameNodes === null || $nameNodes->count() === 0) {
+ throw InvalidAstException::missingRequiredField('name', 'A_Expr');
+ }
+
+ $nameNode = $nameNodes->offsetGet(0);
+ $stringNode = $nameNode->getString();
+
+ if ($stringNode === null) {
+ throw InvalidAstException::unexpectedNodeType('String', 'unknown');
+ }
+
+ return new self(
+ ExpressionFactory::fromAst($lexpr),
+ $stringNode->getSval(),
+ ExpressionFactory::fromAst($rexpr)
+ );
+ }
+
+ 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
+ {
+ $operatorString = new PBString(['sval' => $this->operator]);
+ $operatorNode = new Node(['string' => $operatorString]);
+
+ $aExpr = new A_Expr([
+ 'kind' => A_Expr_Kind::AEXPR_OP,
+ 'name' => [$operatorNode],
+ 'lexpr' => $this->left->toAst(),
+ 'rexpr' => $this->right->toAst(),
+ ]);
+
+ return new Node(['a_expr' => $aExpr]);
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/OrCondition.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/OrCondition.php
new file mode 100644
index 000000000..3d5be8199
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/OrCondition.php
@@ -0,0 +1,148 @@
+
+ */
+ private array $conditions;
+
+ public function __construct(
+ Condition ...$conditions,
+ ) {
+ $this->conditions = $conditions;
+ }
+
+ public static function fromAst(Node $node) : static
+ {
+ if (!$node->hasBoolExpr()) {
+ throw InvalidAstException::unexpectedNodeType('BoolExpr', 'unknown');
+ }
+
+ $boolExpr = $node->getBoolExpr();
+
+ if ($boolExpr === null) {
+ throw InvalidAstException::missingRequiredField('bool_expr', 'Node');
+ }
+
+ if ($boolExpr->getBoolop() !== BoolExprType::OR_EXPR) {
+ throw InvalidAstException::unexpectedNodeType(
+ 'BoolExpr with OR_EXPR',
+ 'BoolExpr with ' . BoolExprType::name($boolExpr->getBoolop())
+ );
+ }
+
+ $conditions = [];
+
+ foreach ($boolExpr->getArgs() as $argNode) {
+ $conditions[] = self::conditionFromNode($argNode);
+ }
+
+ return new self(...$conditions);
+ }
+
+ public function and(Condition $other) : AndCondition
+ {
+ return new AndCondition($this, $other);
+ }
+
+ public function not() : NotCondition
+ {
+ return new NotCondition($this);
+ }
+
+ public function or(Condition $other) : self
+ {
+ if ($other instanceof self) {
+ return new self(...[...$this->conditions, ...$other->conditions]);
+ }
+
+ return new self(...[...$this->conditions, $other]);
+ }
+
+ public function toAst() : Node
+ {
+ $boolExpr = new BoolExpr();
+ $boolExpr->setBoolop(BoolExprType::OR_EXPR);
+
+ $args = [];
+
+ foreach ($this->conditions as $condition) {
+ $args[] = $condition->toAst();
+ }
+
+ $boolExpr->setArgs($args);
+
+ $node = new Node();
+ $node->setBoolExpr($boolExpr);
+
+ return $node;
+ }
+
+ private static function conditionFromNode(Node $node) : Condition
+ {
+ if ($node->hasBoolExpr()) {
+ $boolExpr = $node->getBoolExpr();
+
+ if ($boolExpr === null) {
+ throw InvalidAstException::missingRequiredField('bool_expr', 'Node');
+ }
+
+ return match ($boolExpr->getBoolop()) {
+ BoolExprType::AND_EXPR => AndCondition::fromAst($node),
+ BoolExprType::OR_EXPR => self::fromAst($node),
+ BoolExprType::NOT_EXPR => NotCondition::fromAst($node),
+ default => throw UnsupportedNodeException::forNodeType('BoolExpr with ' . BoolExprType::name($boolExpr->getBoolop())),
+ };
+ }
+
+ if ($node->hasAExpr()) {
+ $aExpr = $node->getAExpr();
+
+ if ($aExpr === null) {
+ throw InvalidAstException::missingRequiredField('a_expr', 'Node');
+ }
+
+ return match ($aExpr->getKind()) {
+ A_Expr_Kind::AEXPR_OP => Comparison::fromAst($node),
+ A_Expr_Kind::AEXPR_LIKE => Like::fromAst($node),
+ A_Expr_Kind::AEXPR_ILIKE => Like::fromAst($node),
+ A_Expr_Kind::AEXPR_SIMILAR => SimilarTo::fromAst($node),
+ A_Expr_Kind::AEXPR_DISTINCT => IsDistinctFrom::fromAst($node),
+ A_Expr_Kind::AEXPR_NOT_DISTINCT => IsDistinctFrom::fromAst($node),
+ A_Expr_Kind::AEXPR_OP_ANY => Any::fromAst($node),
+ A_Expr_Kind::AEXPR_OP_ALL => All::fromAst($node),
+ A_Expr_Kind::AEXPR_BETWEEN => Between::fromAst($node),
+ A_Expr_Kind::AEXPR_NOT_BETWEEN => Between::fromAst($node),
+ A_Expr_Kind::AEXPR_BETWEEN_SYM => Between::fromAst($node),
+ A_Expr_Kind::AEXPR_NOT_BETWEEN_SYM => Between::fromAst($node),
+ default => throw UnsupportedNodeException::forNodeType('A_Expr with kind: ' . A_Expr_Kind::name($aExpr->getKind())),
+ };
+ }
+
+ if ($node->hasSubLink()) {
+ $subLink = $node->getSubLink();
+
+ if ($subLink === null) {
+ throw InvalidAstException::missingRequiredField('sub_link', 'Node');
+ }
+
+ return match ($subLink->getSubLinkType()) {
+ SubLinkType::EXISTS_SUBLINK => Exists::fromAst($node),
+ SubLinkType::ANY_SUBLINK => Any::fromAst($node),
+ SubLinkType::ALL_SUBLINK => All::fromAst($node),
+ default => throw UnsupportedNodeException::forNodeType('SubLink with type: ' . SubLinkType::name($subLink->getSubLinkType())),
+ };
+ }
+
+ throw UnsupportedNodeException::forNodeType('unknown node type in condition');
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/RawCondition.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/RawCondition.php
new file mode 100644
index 000000000..4726b6b82
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/RawCondition.php
@@ -0,0 +1,142 @@
+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
new file mode 100644
index 000000000..2a9b3e0b3
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Condition/SimilarTo.php
@@ -0,0 +1,121 @@
+getAExpr();
+
+ if ($aExpr === null) {
+ throw InvalidAstException::unexpectedNodeType('A_Expr', 'unknown');
+ }
+
+ $kind = $aExpr->getKind();
+
+ if ($kind !== A_Expr_Kind::AEXPR_SIMILAR) {
+ throw InvalidAstException::invalidFieldValue('kind', 'A_Expr', 'Expected AEXPR_SIMILAR for SimilarTo condition');
+ }
+
+ $lexpr = $aExpr->getLexpr();
+
+ if ($lexpr === null) {
+ throw InvalidAstException::missingRequiredField('lexpr', 'A_Expr');
+ }
+
+ $rexpr = $aExpr->getRexpr();
+
+ if ($rexpr === null) {
+ throw InvalidAstException::missingRequiredField('rexpr', 'A_Expr');
+ }
+
+ $pattern = null;
+ $escape = null;
+
+ if ($rexpr->hasFuncCall()) {
+ $funcCall = $rexpr->getFuncCall();
+ $args = $funcCall?->getArgs();
+
+ if ($args !== null && \count($args) > 0) {
+ $pattern = ExpressionFactory::fromAst($args[0]);
+ }
+
+ if ($args !== null && \count($args) > 1) {
+ $escape = ExpressionFactory::fromAst($args[1]);
+ }
+ } else {
+ $pattern = ExpressionFactory::fromAst($rexpr);
+ }
+
+ if ($pattern === null) {
+ throw InvalidAstException::missingRequiredField('pattern', 'SimilarTo');
+ }
+
+ return new self(
+ ExpressionFactory::fromAst($lexpr),
+ $pattern,
+ $escape
+ );
+ }
+
+ 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
+ {
+ $operatorString = new PBString(['sval' => '~']);
+ $operatorNode = new Node(['string' => $operatorString]);
+
+ $funcArgs = [$this->pattern->toAst()];
+
+ if ($this->escape !== null) {
+ $funcArgs[] = $this->escape->toAst();
+ }
+
+ $funcCall = new FuncCall([
+ 'funcname' => [
+ new Node(['string' => new PBString(['sval' => 'pg_catalog'])]),
+ new Node(['string' => new PBString(['sval' => 'similar_to_escape'])]),
+ ],
+ 'args' => $funcArgs,
+ 'funcformat' => CoercionForm::COERCE_EXPLICIT_CALL,
+ 'location' => -1,
+ ]);
+
+ $aExpr = new A_Expr([
+ 'kind' => A_Expr_Kind::AEXPR_SIMILAR,
+ 'name' => [$operatorNode],
+ 'lexpr' => $this->expression->toAst(),
+ 'rexpr' => new Node(['func_call' => $funcCall]),
+ 'location' => -1,
+ ]);
+
+ return new Node(['a_expr' => $aExpr]);
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Copy/CopyFormat.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Copy/CopyFormat.php
new file mode 100644
index 000000000..08bd77b77
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Copy/CopyFormat.php
@@ -0,0 +1,12 @@
+ $columns
+ * @param list $forceNotNullColumns
+ * @param list $forceNullColumns
+ */
+ private function __construct(
+ private ?string $table = null,
+ private ?string $schema = null,
+ private array $columns = [],
+ private ?string $filename = null,
+ private bool $isProgram = false,
+ private bool $isStdin = false,
+ private ?CopyFormat $format = null,
+ private ?string $delimiter = null,
+ private ?string $nullString = null,
+ private ?bool $header = null,
+ private ?string $quote = null,
+ private ?string $escape = null,
+ private array $forceNotNullColumns = [],
+ private array $forceNullColumns = [],
+ private ?string $encoding = null,
+ private ?CopyOnError $onError = null,
+ ) {
+ }
+
+ public static function create() : CopyFromTableStep
+ {
+ return new self();
+ }
+
+ public function columns(string ...$columns) : CopyFromSourceStep
+ {
+ return new self(
+ $this->table,
+ $this->schema,
+ \array_values($columns),
+ $this->filename,
+ $this->isProgram,
+ $this->isStdin,
+ $this->format,
+ $this->delimiter,
+ $this->nullString,
+ $this->header,
+ $this->quote,
+ $this->escape,
+ $this->forceNotNullColumns,
+ $this->forceNullColumns,
+ $this->encoding,
+ $this->onError,
+ );
+ }
+
+ public function delimiter(string $delimiter) : CopyFromOptionsStep
+ {
+ return new self(
+ $this->table,
+ $this->schema,
+ $this->columns,
+ $this->filename,
+ $this->isProgram,
+ $this->isStdin,
+ $this->format,
+ $delimiter,
+ $this->nullString,
+ $this->header,
+ $this->quote,
+ $this->escape,
+ $this->forceNotNullColumns,
+ $this->forceNullColumns,
+ $this->encoding,
+ $this->onError,
+ );
+ }
+
+ public function encoding(string $encoding) : CopyFromOptionsStep
+ {
+ return new self(
+ $this->table,
+ $this->schema,
+ $this->columns,
+ $this->filename,
+ $this->isProgram,
+ $this->isStdin,
+ $this->format,
+ $this->delimiter,
+ $this->nullString,
+ $this->header,
+ $this->quote,
+ $this->escape,
+ $this->forceNotNullColumns,
+ $this->forceNullColumns,
+ $encoding,
+ $this->onError,
+ );
+ }
+
+ public function escape(string $escape) : CopyFromOptionsStep
+ {
+ return new self(
+ $this->table,
+ $this->schema,
+ $this->columns,
+ $this->filename,
+ $this->isProgram,
+ $this->isStdin,
+ $this->format,
+ $this->delimiter,
+ $this->nullString,
+ $this->header,
+ $this->quote,
+ $escape,
+ $this->forceNotNullColumns,
+ $this->forceNullColumns,
+ $this->encoding,
+ $this->onError,
+ );
+ }
+
+ public function file(string $filename) : CopyFromOptionsStep
+ {
+ return new self(
+ $this->table,
+ $this->schema,
+ $this->columns,
+ $filename,
+ false,
+ false,
+ $this->format,
+ $this->delimiter,
+ $this->nullString,
+ $this->header,
+ $this->quote,
+ $this->escape,
+ $this->forceNotNullColumns,
+ $this->forceNullColumns,
+ $this->encoding,
+ $this->onError,
+ );
+ }
+
+ public function forceNotNull(string ...$columns) : CopyFromOptionsStep
+ {
+ return new self(
+ $this->table,
+ $this->schema,
+ $this->columns,
+ $this->filename,
+ $this->isProgram,
+ $this->isStdin,
+ $this->format,
+ $this->delimiter,
+ $this->nullString,
+ $this->header,
+ $this->quote,
+ $this->escape,
+ \array_values($columns),
+ $this->forceNullColumns,
+ $this->encoding,
+ $this->onError,
+ );
+ }
+
+ public function forceNull(string ...$columns) : CopyFromOptionsStep
+ {
+ return new self(
+ $this->table,
+ $this->schema,
+ $this->columns,
+ $this->filename,
+ $this->isProgram,
+ $this->isStdin,
+ $this->format,
+ $this->delimiter,
+ $this->nullString,
+ $this->header,
+ $this->quote,
+ $this->escape,
+ $this->forceNotNullColumns,
+ \array_values($columns),
+ $this->encoding,
+ $this->onError,
+ );
+ }
+
+ public function format(CopyFormat $format) : CopyFromOptionsStep
+ {
+ return new self(
+ $this->table,
+ $this->schema,
+ $this->columns,
+ $this->filename,
+ $this->isProgram,
+ $this->isStdin,
+ $format,
+ $this->delimiter,
+ $this->nullString,
+ $this->header,
+ $this->quote,
+ $this->escape,
+ $this->forceNotNullColumns,
+ $this->forceNullColumns,
+ $this->encoding,
+ $this->onError,
+ );
+ }
+
+ public function nullAs(string $nullString) : CopyFromOptionsStep
+ {
+ return new self(
+ $this->table,
+ $this->schema,
+ $this->columns,
+ $this->filename,
+ $this->isProgram,
+ $this->isStdin,
+ $this->format,
+ $this->delimiter,
+ $nullString,
+ $this->header,
+ $this->quote,
+ $this->escape,
+ $this->forceNotNullColumns,
+ $this->forceNullColumns,
+ $this->encoding,
+ $this->onError,
+ );
+ }
+
+ public function onError(CopyOnError $behavior) : CopyFromOptionsStep
+ {
+ return new self(
+ $this->table,
+ $this->schema,
+ $this->columns,
+ $this->filename,
+ $this->isProgram,
+ $this->isStdin,
+ $this->format,
+ $this->delimiter,
+ $this->nullString,
+ $this->header,
+ $this->quote,
+ $this->escape,
+ $this->forceNotNullColumns,
+ $this->forceNullColumns,
+ $this->encoding,
+ $behavior,
+ );
+ }
+
+ public function program(string $command) : CopyFromOptionsStep
+ {
+ return new self(
+ $this->table,
+ $this->schema,
+ $this->columns,
+ $command,
+ true,
+ false,
+ $this->format,
+ $this->delimiter,
+ $this->nullString,
+ $this->header,
+ $this->quote,
+ $this->escape,
+ $this->forceNotNullColumns,
+ $this->forceNullColumns,
+ $this->encoding,
+ $this->onError,
+ );
+ }
+
+ public function quote(string $quote) : CopyFromOptionsStep
+ {
+ return new self(
+ $this->table,
+ $this->schema,
+ $this->columns,
+ $this->filename,
+ $this->isProgram,
+ $this->isStdin,
+ $this->format,
+ $this->delimiter,
+ $this->nullString,
+ $this->header,
+ $quote,
+ $this->escape,
+ $this->forceNotNullColumns,
+ $this->forceNullColumns,
+ $this->encoding,
+ $this->onError,
+ );
+ }
+
+ public function stdin() : CopyFromOptionsStep
+ {
+ return new self(
+ $this->table,
+ $this->schema,
+ $this->columns,
+ null,
+ false,
+ true,
+ $this->format,
+ $this->delimiter,
+ $this->nullString,
+ $this->header,
+ $this->quote,
+ $this->escape,
+ $this->forceNotNullColumns,
+ $this->forceNullColumns,
+ $this->encoding,
+ $this->onError,
+ );
+ }
+
+ public function table(string $table, string ...$columns) : CopyFromSourceStep
+ {
+ $identifier = QualifiedIdentifier::parse($table);
+
+ return new self(
+ $identifier->name(),
+ $identifier->schema(),
+ \array_values($columns),
+ $this->filename,
+ $this->isProgram,
+ $this->isStdin,
+ $this->format,
+ $this->delimiter,
+ $this->nullString,
+ $this->header,
+ $this->quote,
+ $this->escape,
+ $this->forceNotNullColumns,
+ $this->forceNullColumns,
+ $this->encoding,
+ $this->onError,
+ );
+ }
+
+ public function toAst() : CopyStmt
+ {
+ if ($this->table === null || $this->table === '') {
+ throw InvalidExpressionException::invalidValue('table', 'null or empty');
+ }
+
+ if (!$this->isStdin && ($this->filename === null || $this->filename === '')) {
+ throw InvalidExpressionException::invalidValue('filename', 'null or empty');
+ }
+
+ $copyStmt = new CopyStmt();
+ $copyStmt->setIsFrom(true);
+ $copyStmt->setIsProgram($this->isProgram);
+
+ if ($this->isStdin) {
+ $copyStmt->setFilename('');
+ } else {
+ $copyStmt->setFilename($this->filename ?? '');
+ }
+
+ $rangeVar = new RangeVar([
+ 'relname' => $this->table,
+ 'inh' => true,
+ ]);
+
+ if ($this->schema !== null) {
+ $rangeVar->setSchemaname($this->schema);
+ }
+
+ $copyStmt->setRelation($rangeVar);
+
+ if ($this->columns !== []) {
+ $attlist = [];
+
+ foreach ($this->columns as $column) {
+ $str = new PBString();
+ $str->setSval($column);
+ $node = new Node();
+ $node->setString($str);
+ $attlist[] = $node;
+ }
+
+ $copyStmt->setAttlist($attlist);
+ }
+
+ $options = $this->buildOptions();
+
+ if ($options !== []) {
+ $copyStmt->setOptions($options);
+ }
+
+ return $copyStmt;
+ }
+
+ public function withHeader(bool $header = true) : CopyFromOptionsStep
+ {
+ return new self(
+ $this->table,
+ $this->schema,
+ $this->columns,
+ $this->filename,
+ $this->isProgram,
+ $this->isStdin,
+ $this->format,
+ $this->delimiter,
+ $this->nullString,
+ $header,
+ $this->quote,
+ $this->escape,
+ $this->forceNotNullColumns,
+ $this->forceNullColumns,
+ $this->encoding,
+ $this->onError,
+ );
+ }
+
+ /**
+ * @return list
+ */
+ private function buildOptions() : array
+ {
+ $options = [];
+
+ if ($this->format !== null) {
+ $options[] = $this->createStringOption('format', $this->format->value);
+ }
+
+ if ($this->delimiter !== null) {
+ $options[] = $this->createStringOption('delimiter', $this->delimiter);
+ }
+
+ if ($this->nullString !== null) {
+ $options[] = $this->createStringOption('null', $this->nullString);
+ }
+
+ if ($this->header !== null) {
+ $options[] = $this->createBoolOption('header', $this->header);
+ }
+
+ if ($this->quote !== null) {
+ $options[] = $this->createStringOption('quote', $this->quote);
+ }
+
+ if ($this->escape !== null) {
+ $options[] = $this->createStringOption('escape', $this->escape);
+ }
+
+ if ($this->forceNotNullColumns !== []) {
+ $options[] = $this->createColumnListOption('force_not_null', $this->forceNotNullColumns);
+ }
+
+ if ($this->forceNullColumns !== []) {
+ $options[] = $this->createColumnListOption('force_null', $this->forceNullColumns);
+ }
+
+ if ($this->encoding !== null) {
+ $options[] = $this->createStringOption('encoding', $this->encoding);
+ }
+
+ if ($this->onError !== null) {
+ $options[] = $this->createStringOption('on_error', $this->onError->value);
+ }
+
+ return $options;
+ }
+
+ private function createBoolOption(string $name, bool $value) : Node
+ {
+ $defElem = new DefElem();
+ $defElem->setDefname($name);
+
+ $str = new PBString();
+ $str->setSval($value ? 'true' : 'false');
+ $argNode = new Node();
+ $argNode->setString($str);
+ $defElem->setArg($argNode);
+
+ $node = new Node();
+ $node->setDefElem($defElem);
+
+ return $node;
+ }
+
+ /**
+ * @param list $columns
+ */
+ private function createColumnListOption(string $name, array $columns) : Node
+ {
+ $defElem = new DefElem();
+ $defElem->setDefname($name);
+
+ $columnNodes = [];
+
+ foreach ($columns as $column) {
+ $str = new PBString();
+ $str->setSval($column);
+ $colNode = new Node();
+ $colNode->setString($str);
+ $columnNodes[] = $colNode;
+ }
+
+ $listNode = new Node();
+ $listNode->setList(new PBList(['items' => $columnNodes]));
+ $defElem->setArg($listNode);
+
+ $node = new Node();
+ $node->setDefElem($defElem);
+
+ return $node;
+ }
+
+ private function createStringOption(string $name, string $value) : Node
+ {
+ $defElem = new DefElem();
+ $defElem->setDefname($name);
+
+ $str = new PBString();
+ $str->setSval($value);
+ $argNode = new Node();
+ $argNode->setString($str);
+ $defElem->setArg($argNode);
+
+ $node = new Node();
+ $node->setDefElem($defElem);
+
+ return $node;
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Copy/CopyFromFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Copy/CopyFromFinalStep.php
new file mode 100644
index 000000000..aafecbeca
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Copy/CopyFromFinalStep.php
@@ -0,0 +1,12 @@
+ $columns
+ * @param list $forceQuoteColumns
+ */
+ private function __construct(
+ private ?string $table = null,
+ private ?string $schema = null,
+ private array $columns = [],
+ private ?SelectFinalStep $query = null,
+ private ?string $filename = null,
+ private bool $isProgram = false,
+ private bool $isStdout = false,
+ private ?CopyFormat $format = null,
+ private ?string $delimiter = null,
+ private ?string $nullString = null,
+ private ?bool $header = null,
+ private ?string $quote = null,
+ private ?string $escape = null,
+ private array $forceQuoteColumns = [],
+ private bool $forceQuoteAll = false,
+ private ?string $encoding = null,
+ ) {
+ }
+
+ public static function create() : CopyToTableStep
+ {
+ return new self();
+ }
+
+ public function columns(string ...$columns) : CopyToDestinationStep
+ {
+ return new self(
+ $this->table,
+ $this->schema,
+ \array_values($columns),
+ $this->query,
+ $this->filename,
+ $this->isProgram,
+ $this->isStdout,
+ $this->format,
+ $this->delimiter,
+ $this->nullString,
+ $this->header,
+ $this->quote,
+ $this->escape,
+ $this->forceQuoteColumns,
+ $this->forceQuoteAll,
+ $this->encoding,
+ );
+ }
+
+ public function delimiter(string $delimiter) : CopyToOptionsStep
+ {
+ return new self(
+ $this->table,
+ $this->schema,
+ $this->columns,
+ $this->query,
+ $this->filename,
+ $this->isProgram,
+ $this->isStdout,
+ $this->format,
+ $delimiter,
+ $this->nullString,
+ $this->header,
+ $this->quote,
+ $this->escape,
+ $this->forceQuoteColumns,
+ $this->forceQuoteAll,
+ $this->encoding,
+ );
+ }
+
+ public function encoding(string $encoding) : CopyToOptionsStep
+ {
+ return new self(
+ $this->table,
+ $this->schema,
+ $this->columns,
+ $this->query,
+ $this->filename,
+ $this->isProgram,
+ $this->isStdout,
+ $this->format,
+ $this->delimiter,
+ $this->nullString,
+ $this->header,
+ $this->quote,
+ $this->escape,
+ $this->forceQuoteColumns,
+ $this->forceQuoteAll,
+ $encoding,
+ );
+ }
+
+ public function escape(string $escape) : CopyToOptionsStep
+ {
+ return new self(
+ $this->table,
+ $this->schema,
+ $this->columns,
+ $this->query,
+ $this->filename,
+ $this->isProgram,
+ $this->isStdout,
+ $this->format,
+ $this->delimiter,
+ $this->nullString,
+ $this->header,
+ $this->quote,
+ $escape,
+ $this->forceQuoteColumns,
+ $this->forceQuoteAll,
+ $this->encoding,
+ );
+ }
+
+ public function file(string $filename) : CopyToOptionsStep
+ {
+ return new self(
+ $this->table,
+ $this->schema,
+ $this->columns,
+ $this->query,
+ $filename,
+ false,
+ false,
+ $this->format,
+ $this->delimiter,
+ $this->nullString,
+ $this->header,
+ $this->quote,
+ $this->escape,
+ $this->forceQuoteColumns,
+ $this->forceQuoteAll,
+ $this->encoding,
+ );
+ }
+
+ public function forceQuote(string ...$columns) : CopyToOptionsStep
+ {
+ return new self(
+ $this->table,
+ $this->schema,
+ $this->columns,
+ $this->query,
+ $this->filename,
+ $this->isProgram,
+ $this->isStdout,
+ $this->format,
+ $this->delimiter,
+ $this->nullString,
+ $this->header,
+ $this->quote,
+ $this->escape,
+ \array_values($columns),
+ false,
+ $this->encoding,
+ );
+ }
+
+ public function forceQuoteAll() : CopyToOptionsStep
+ {
+ return new self(
+ $this->table,
+ $this->schema,
+ $this->columns,
+ $this->query,
+ $this->filename,
+ $this->isProgram,
+ $this->isStdout,
+ $this->format,
+ $this->delimiter,
+ $this->nullString,
+ $this->header,
+ $this->quote,
+ $this->escape,
+ [],
+ true,
+ $this->encoding,
+ );
+ }
+
+ public function format(CopyFormat $format) : CopyToOptionsStep
+ {
+ return new self(
+ $this->table,
+ $this->schema,
+ $this->columns,
+ $this->query,
+ $this->filename,
+ $this->isProgram,
+ $this->isStdout,
+ $format,
+ $this->delimiter,
+ $this->nullString,
+ $this->header,
+ $this->quote,
+ $this->escape,
+ $this->forceQuoteColumns,
+ $this->forceQuoteAll,
+ $this->encoding,
+ );
+ }
+
+ public function nullAs(string $nullString) : CopyToOptionsStep
+ {
+ return new self(
+ $this->table,
+ $this->schema,
+ $this->columns,
+ $this->query,
+ $this->filename,
+ $this->isProgram,
+ $this->isStdout,
+ $this->format,
+ $this->delimiter,
+ $nullString,
+ $this->header,
+ $this->quote,
+ $this->escape,
+ $this->forceQuoteColumns,
+ $this->forceQuoteAll,
+ $this->encoding,
+ );
+ }
+
+ public function program(string $command) : CopyToOptionsStep
+ {
+ return new self(
+ $this->table,
+ $this->schema,
+ $this->columns,
+ $this->query,
+ $command,
+ true,
+ false,
+ $this->format,
+ $this->delimiter,
+ $this->nullString,
+ $this->header,
+ $this->quote,
+ $this->escape,
+ $this->forceQuoteColumns,
+ $this->forceQuoteAll,
+ $this->encoding,
+ );
+ }
+
+ public function query(SelectFinalStep $query) : CopyToDestinationStep
+ {
+ return new self(
+ null,
+ null,
+ [],
+ $query,
+ $this->filename,
+ $this->isProgram,
+ $this->isStdout,
+ $this->format,
+ $this->delimiter,
+ $this->nullString,
+ $this->header,
+ $this->quote,
+ $this->escape,
+ $this->forceQuoteColumns,
+ $this->forceQuoteAll,
+ $this->encoding,
+ );
+ }
+
+ public function quote(string $quote) : CopyToOptionsStep
+ {
+ return new self(
+ $this->table,
+ $this->schema,
+ $this->columns,
+ $this->query,
+ $this->filename,
+ $this->isProgram,
+ $this->isStdout,
+ $this->format,
+ $this->delimiter,
+ $this->nullString,
+ $this->header,
+ $quote,
+ $this->escape,
+ $this->forceQuoteColumns,
+ $this->forceQuoteAll,
+ $this->encoding,
+ );
+ }
+
+ public function stdout() : CopyToOptionsStep
+ {
+ return new self(
+ $this->table,
+ $this->schema,
+ $this->columns,
+ $this->query,
+ null,
+ false,
+ true,
+ $this->format,
+ $this->delimiter,
+ $this->nullString,
+ $this->header,
+ $this->quote,
+ $this->escape,
+ $this->forceQuoteColumns,
+ $this->forceQuoteAll,
+ $this->encoding,
+ );
+ }
+
+ public function table(string $table, string ...$columns) : CopyToDestinationStep
+ {
+ $identifier = QualifiedIdentifier::parse($table);
+
+ return new self(
+ $identifier->name(),
+ $identifier->schema(),
+ \array_values($columns),
+ null,
+ $this->filename,
+ $this->isProgram,
+ $this->isStdout,
+ $this->format,
+ $this->delimiter,
+ $this->nullString,
+ $this->header,
+ $this->quote,
+ $this->escape,
+ $this->forceQuoteColumns,
+ $this->forceQuoteAll,
+ $this->encoding,
+ );
+ }
+
+ public function toAst() : CopyStmt
+ {
+ if ($this->table === null && $this->query === null) {
+ throw InvalidExpressionException::invalidValue('table or query', 'null');
+ }
+
+ if (!$this->isStdout && ($this->filename === null || $this->filename === '')) {
+ throw InvalidExpressionException::invalidValue('filename', 'null or empty');
+ }
+
+ $copyStmt = new CopyStmt();
+ $copyStmt->setIsFrom(false);
+ $copyStmt->setIsProgram($this->isProgram);
+
+ if ($this->isStdout) {
+ $copyStmt->setFilename('');
+ } else {
+ $copyStmt->setFilename($this->filename ?? '');
+ }
+
+ if ($this->table !== null) {
+ $rangeVar = new RangeVar([
+ 'relname' => $this->table,
+ 'inh' => true,
+ ]);
+
+ if ($this->schema !== null) {
+ $rangeVar->setSchemaname($this->schema);
+ }
+
+ $copyStmt->setRelation($rangeVar);
+
+ if ($this->columns !== []) {
+ $attlist = [];
+
+ foreach ($this->columns as $column) {
+ $str = new PBString();
+ $str->setSval($column);
+ $node = new Node();
+ $node->setString($str);
+ $attlist[] = $node;
+ }
+
+ $copyStmt->setAttlist($attlist);
+ }
+ } else {
+ /** @var SelectFinalStep $query */
+ $query = $this->query;
+ $queryNode = new Node();
+ $queryNode->setSelectStmt($query->toAst());
+ $copyStmt->setQuery($queryNode);
+ }
+
+ $options = $this->buildOptions();
+
+ if ($options !== []) {
+ $copyStmt->setOptions($options);
+ }
+
+ return $copyStmt;
+ }
+
+ public function withHeader(bool $header = true) : CopyToOptionsStep
+ {
+ return new self(
+ $this->table,
+ $this->schema,
+ $this->columns,
+ $this->query,
+ $this->filename,
+ $this->isProgram,
+ $this->isStdout,
+ $this->format,
+ $this->delimiter,
+ $this->nullString,
+ $header,
+ $this->quote,
+ $this->escape,
+ $this->forceQuoteColumns,
+ $this->forceQuoteAll,
+ $this->encoding,
+ );
+ }
+
+ /**
+ * @return list
+ */
+ private function buildOptions() : array
+ {
+ $options = [];
+
+ if ($this->format !== null) {
+ $options[] = $this->createStringOption('format', $this->format->value);
+ }
+
+ if ($this->delimiter !== null) {
+ $options[] = $this->createStringOption('delimiter', $this->delimiter);
+ }
+
+ if ($this->nullString !== null) {
+ $options[] = $this->createStringOption('null', $this->nullString);
+ }
+
+ if ($this->header !== null) {
+ $options[] = $this->createBoolOption('header', $this->header);
+ }
+
+ if ($this->quote !== null) {
+ $options[] = $this->createStringOption('quote', $this->quote);
+ }
+
+ if ($this->escape !== null) {
+ $options[] = $this->createStringOption('escape', $this->escape);
+ }
+
+ if ($this->forceQuoteAll) {
+ $options[] = $this->createStarOption('force_quote');
+ } elseif ($this->forceQuoteColumns !== []) {
+ $options[] = $this->createColumnListOption('force_quote', $this->forceQuoteColumns);
+ }
+
+ if ($this->encoding !== null) {
+ $options[] = $this->createStringOption('encoding', $this->encoding);
+ }
+
+ return $options;
+ }
+
+ private function createBoolOption(string $name, bool $value) : Node
+ {
+ $defElem = new DefElem();
+ $defElem->setDefname($name);
+
+ $str = new PBString();
+ $str->setSval($value ? 'true' : 'false');
+ $argNode = new Node();
+ $argNode->setString($str);
+ $defElem->setArg($argNode);
+
+ $node = new Node();
+ $node->setDefElem($defElem);
+
+ return $node;
+ }
+
+ /**
+ * @param list $columns
+ */
+ private function createColumnListOption(string $name, array $columns) : Node
+ {
+ $defElem = new DefElem();
+ $defElem->setDefname($name);
+
+ $columnNodes = [];
+
+ foreach ($columns as $column) {
+ $str = new PBString();
+ $str->setSval($column);
+ $colNode = new Node();
+ $colNode->setString($str);
+ $columnNodes[] = $colNode;
+ }
+
+ $listNode = new Node();
+ $listNode->setList(new PBList(['items' => $columnNodes]));
+ $defElem->setArg($listNode);
+
+ $node = new Node();
+ $node->setDefElem($defElem);
+
+ return $node;
+ }
+
+ private function createStarOption(string $name) : Node
+ {
+ $defElem = new DefElem();
+ $defElem->setDefname($name);
+
+ $star = new A_Star();
+ $starNode = new Node();
+ $starNode->setAStar($star);
+ $defElem->setArg($starNode);
+
+ $node = new Node();
+ $node->setDefElem($defElem);
+
+ return $node;
+ }
+
+ private function createStringOption(string $name, string $value) : Node
+ {
+ $defElem = new DefElem();
+ $defElem->setDefname($name);
+
+ $str = new PBString();
+ $str->setSval($value);
+ $argNode = new Node();
+ $argNode->setString($str);
+ $defElem->setArg($argNode);
+
+ $node = new Node();
+ $node->setDefElem($defElem);
+
+ return $node;
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Copy/CopyToDestinationStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Copy/CopyToDestinationStep.php
new file mode 100644
index 000000000..646f1da43
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Copy/CopyToDestinationStep.php
@@ -0,0 +1,16 @@
+ $using
+ * @param array $returning
+ */
+ private function __construct(
+ private ?WithClause $with = null,
+ private ?string $table = null,
+ private ?string $alias = null,
+ private array $using = [],
+ private ?Condition $where = null,
+ private array $returning = [],
+ ) {
+ }
+
+ public static function create() : DeleteFromStep
+ {
+ return new self();
+ }
+
+ public static function fromAst(Node $node) : static
+ {
+ $deleteStmt = $node->getDeleteStmt();
+
+ if ($deleteStmt === null) {
+ throw InvalidAstException::invalidFieldValue('node', 'DeleteBuilder', 'Expected DeleteStmt');
+ }
+
+ $relation = $deleteStmt->getRelation();
+
+ if ($relation === null) {
+ throw InvalidAstException::missingRequiredField('relation', 'DeleteStmt');
+ }
+
+ $tableName = $relation->getRelname();
+
+ if ($tableName === '') {
+ throw InvalidAstException::missingRequiredField('relname', 'RangeVar');
+ }
+
+ $alias = $relation->getAlias();
+ $aliasName = $alias !== null ? $alias->getAliasname() : null;
+
+ $withClause = null;
+
+ if ($deleteStmt->hasWithClause()) {
+ $protoWithClause = $deleteStmt->getWithClause();
+
+ if ($protoWithClause !== null) {
+ $withNode = new Node();
+ $withNode->setWithClause($protoWithClause);
+ $withClause = WithClause::fromAst($withNode);
+ }
+ }
+
+ $using = [];
+ $usingClause = $deleteStmt->getUsingClause();
+
+ if ($usingClause !== null && \count($usingClause) > 0) {
+ foreach ($usingClause as $usingNode) {
+ if ($usingNode->getRangeVar() !== null) {
+ $rangeVar = $usingNode->getRangeVar();
+
+ if ($rangeVar->hasAlias()) {
+ $using[] = AliasedTable::fromAst($usingNode);
+ } else {
+ $using[] = Table::fromAst($usingNode);
+ }
+ } else {
+ throw InvalidAstException::invalidFieldValue('using_clause', 'DeleteStmt', 'Only RangeVar nodes are supported');
+ }
+ }
+ }
+
+ $whereCondition = null;
+
+ if ($deleteStmt->hasWhereClause()) {
+ $whereNode = $deleteStmt->getWhereClause();
+
+ if ($whereNode !== null) {
+ $whereCondition = ConditionFactory::fromAst($whereNode);
+ }
+ }
+
+ $returningExpressions = [];
+ $returningList = $deleteStmt->getReturningList();
+
+ if ($returningList !== null && \count($returningList) > 0) {
+ foreach ($returningList as $resTargetNode) {
+ $resTarget = $resTargetNode->getResTarget();
+
+ if ($resTarget === null) {
+ throw InvalidAstException::invalidFieldValue('returning_list', 'DeleteStmt', 'Expected ResTarget node');
+ }
+
+ $val = $resTarget->getVal();
+
+ if ($val === null) {
+ throw InvalidAstException::missingRequiredField('val', 'ResTarget');
+ }
+
+ $returningExpressions[] = ExpressionFactory::fromAst($val);
+ }
+ }
+
+ return new self(
+ with: $withClause,
+ table: $tableName,
+ alias: $aliasName,
+ using: $using,
+ where: $whereCondition,
+ returning: $returningExpressions,
+ );
+ }
+
+ public static function with(WithClause $with) : DeleteFromStep
+ {
+ return new self(with: $with);
+ }
+
+ public function from(string $table, ?string $alias = null) : DeleteUsingStep
+ {
+ return new self(
+ with: $this->with,
+ table: $table,
+ alias: $alias,
+ using: $this->using,
+ where: $this->where,
+ returning: $this->returning,
+ );
+ }
+
+ public function returning(Expression ...$expressions) : DeleteFinalStep
+ {
+ return new self(
+ with: $this->with,
+ table: $this->table,
+ alias: $this->alias,
+ using: $this->using,
+ where: $this->where,
+ returning: $expressions,
+ );
+ }
+
+ public function returningAll() : DeleteFinalStep
+ {
+ return new self(
+ with: $this->with,
+ table: $this->table,
+ alias: $this->alias,
+ using: $this->using,
+ where: $this->where,
+ returning: [Star::all()],
+ );
+ }
+
+ public function toAst() : DeleteStmt
+ {
+ if ($this->table === null) {
+ throw new \LogicException('Cannot create DeleteStmt without table name. Call from() first.');
+ }
+
+ $deleteStmt = new DeleteStmt();
+
+ $rangeVar = new RangeVar([
+ 'relname' => $this->table,
+ 'inh' => true,
+ ]);
+
+ if ($this->alias !== null) {
+ $alias = new Alias([
+ 'aliasname' => $this->alias,
+ ]);
+ $rangeVar->setAlias($alias);
+ }
+
+ $deleteStmt->setRelation($rangeVar);
+
+ if ($this->with !== null) {
+ $withNode = $this->with->toAst();
+ $protoWithClause = $withNode->getWithClause();
+
+ if ($protoWithClause !== null) {
+ $deleteStmt->setWithClause($protoWithClause);
+ }
+ }
+
+ if ($this->using !== []) {
+ $usingNodes = [];
+
+ foreach ($this->using as $tableRef) {
+ $usingNodes[] = $tableRef->toAst();
+ }
+
+ $deleteStmt->setUsingClause($usingNodes);
+ }
+
+ if ($this->where !== null) {
+ $deleteStmt->setWhereClause($this->where->toAst());
+ }
+
+ if ($this->returning !== []) {
+ $returningNodes = [];
+
+ foreach ($this->returning as $expression) {
+ $resTarget = new ResTarget();
+ $resTarget->setVal($expression->toAst());
+
+ $resTargetNode = new Node();
+ $resTargetNode->setResTarget($resTarget);
+
+ $returningNodes[] = $resTargetNode;
+ }
+
+ $deleteStmt->setReturningList($returningNodes);
+ }
+
+ return $deleteStmt;
+ }
+
+ public function using(TableReference ...$tables) : DeleteWhereStep
+ {
+ return new self(
+ with: $this->with,
+ table: $this->table,
+ alias: $this->alias,
+ using: $tables,
+ where: $this->where,
+ returning: $this->returning,
+ );
+ }
+
+ public function where(Condition $condition) : DeleteReturningStep
+ {
+ return new self(
+ with: $this->with,
+ table: $this->table,
+ alias: $this->alias,
+ using: $this->using,
+ where: $condition,
+ returning: $this->returning,
+ );
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Delete/DeleteFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Delete/DeleteFinalStep.php
new file mode 100644
index 000000000..dd4449cd0
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Delete/DeleteFinalStep.php
@@ -0,0 +1,24 @@
+ $funcName Function name parts (e.g., ['pg_catalog', 'count'] or ['sum'])
+ * @param list $args Function arguments (empty for COUNT(*))
+ * @param bool $star Whether this is COUNT(*) aggregate
+ * @param bool $distinct Whether DISTINCT is applied to arguments
+ * @param list $orderBy ORDER BY clauses for aggregates that support ordering
+ * @param null|Expression $filter FILTER (WHERE ...) clause
+ */
+ public function __construct(
+ private array $funcName,
+ private array $args = [],
+ private bool $star = false,
+ private bool $distinct = false,
+ private array $orderBy = [],
+ private ?Expression $filter = null,
+ ) {
+ if ($this->funcName === []) {
+ throw InvalidExpressionException::emptyArray('Function name');
+ }
+
+ if ($this->star && $this->args !== []) {
+ throw InvalidExpressionException::invalidValue('AggregateCall', 'Cannot have both star and arguments');
+ }
+ }
+
+ public static function fromAst(Node $node) : static
+ {
+ $funcCall = $node->getFuncCall();
+
+ if ($funcCall === null) {
+ throw InvalidAstException::unexpectedNodeType('FuncCall', 'unknown');
+ }
+
+ $funcNameNodes = $funcCall->getFuncname();
+
+ if ($funcNameNodes === null || \count($funcNameNodes) === 0) {
+ throw InvalidAstException::missingRequiredField('funcname', 'FuncCall');
+ }
+
+ $funcName = [];
+
+ foreach ($funcNameNodes as $nameNode) {
+ $stringNode = $nameNode->getString();
+
+ if ($stringNode === null) {
+ throw InvalidAstException::invalidFieldValue('funcname', 'FuncCall', 'expected String node');
+ }
+
+ $funcName[] = $stringNode->getSval();
+ }
+
+ if ($funcName === []) {
+ throw InvalidAstException::invalidFieldValue('funcname', 'FuncCall', 'cannot be empty');
+ }
+
+ $args = [];
+ $argsNodes = $funcCall->getArgs();
+
+ if ($argsNodes !== null) {
+ foreach ($argsNodes as $argNode) {
+ $args[] = ExpressionFactory::fromAst($argNode);
+ }
+ }
+
+ $star = $funcCall->getAggStar();
+ $distinct = $funcCall->getAggDistinct();
+
+ $orderBy = [];
+ $orderByNodes = $funcCall->getAggOrder();
+
+ if ($orderByNodes !== null) {
+ foreach ($orderByNodes as $orderByNode) {
+ $orderBy[] = OrderBy::fromAst($orderByNode);
+ }
+ }
+
+ $filter = null;
+ $filterNode = $funcCall->getAggFilter();
+
+ if ($filterNode !== null) {
+ $filter = ExpressionFactory::fromAst($filterNode);
+ }
+
+ return new self($funcName, $args, $star, $distinct, $orderBy, $filter);
+ }
+
+ public function as(string $alias) : AliasedExpression
+ {
+ return new AliasedExpression($this, $alias);
+ }
+
+ /**
+ * @return list
+ */
+ public function getArgs() : array
+ {
+ return $this->args;
+ }
+
+ public function getFilter() : ?Expression
+ {
+ return $this->filter;
+ }
+
+ /**
+ * @return non-empty-list
+ */
+ public function getFuncName() : array
+ {
+ return $this->funcName;
+ }
+
+ /**
+ * @return list
+ */
+ public function getOrderBy() : array
+ {
+ return $this->orderBy;
+ }
+
+ public function isDistinct() : bool
+ {
+ return $this->distinct;
+ }
+
+ public function isStar() : bool
+ {
+ return $this->star;
+ }
+
+ public function toAst() : Node
+ {
+ $funcCall = new FuncCall();
+ $funcNameNodes = [];
+
+ foreach ($this->funcName as $namePart) {
+ $stringNode = new PBString();
+ $stringNode->setSval($namePart);
+
+ $nameNode = new Node();
+ $nameNode->setString($stringNode);
+
+ $funcNameNodes[] = $nameNode;
+ }
+
+ $funcCall->setFuncname($funcNameNodes);
+
+ $argNodes = [];
+
+ foreach ($this->args as $arg) {
+ $argNodes[] = $arg->toAst();
+ }
+
+ $funcCall->setArgs($argNodes);
+
+ if ($this->star) {
+ $funcCall->setAggStar(true);
+ }
+
+ if ($this->distinct) {
+ $funcCall->setAggDistinct(true);
+ }
+
+ $orderByNodes = [];
+
+ foreach ($this->orderBy as $orderByClause) {
+ $orderByNodes[] = $orderByClause->toAst();
+ }
+
+ if ($orderByNodes !== []) {
+ $funcCall->setAggOrder($orderByNodes);
+ }
+
+ if ($this->filter !== null) {
+ $funcCall->setAggFilter($this->filter->toAst());
+ }
+
+ $node = new Node();
+ $node->setFuncCall($funcCall);
+
+ return $node;
+ }
+
+ public function withDistinct(bool $distinct = true) : self
+ {
+ return new self($this->funcName, $this->args, $this->star, $distinct, $this->orderBy, $this->filter);
+ }
+
+ public function withFilter(Expression $filter) : self
+ {
+ return new self($this->funcName, $this->args, $this->star, $this->distinct, $this->orderBy, $filter);
+ }
+
+ public function withOrderBy(OrderBy ...$orderBy) : self
+ {
+ return new self($this->funcName, $this->args, $this->star, $this->distinct, \array_values($orderBy), $this->filter);
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/AliasedExpression.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/AliasedExpression.php
new file mode 100644
index 000000000..c1638b92a
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/AliasedExpression.php
@@ -0,0 +1,90 @@
+alias === '') {
+ throw InvalidExpressionException::invalidValue('Alias', 'cannot be empty');
+ }
+ }
+
+ public static function create(Expression $expression, string $alias) : self
+ {
+ return new self($expression, $alias);
+ }
+
+ public static function fromAst(Node $node) : static
+ {
+ $resTarget = $node->getResTarget();
+
+ if ($resTarget === null) {
+ throw InvalidAstException::unexpectedNodeType('ResTarget', 'unknown');
+ }
+
+ $valNode = $resTarget->getVal();
+
+ if ($valNode === null) {
+ throw InvalidAstException::missingRequiredField('val', 'ResTarget');
+ }
+
+ $expression = ExpressionFactory::fromAst($valNode);
+
+ $aliasName = $resTarget->getName();
+
+ if ($aliasName === null || $aliasName === '') {
+ throw InvalidAstException::missingRequiredField('name', 'ResTarget');
+ }
+
+ return new self($expression, $aliasName);
+ }
+
+ public function as(string $alias) : self
+ {
+ return new self($this->expression, $alias);
+ }
+
+ public function getAlias() : string
+ {
+ return $this->alias;
+ }
+
+ public function getExpression() : Expression
+ {
+ return $this->expression;
+ }
+
+ public function toAst() : Node
+ {
+ $resTarget = new ResTarget();
+ $resTarget->setName($this->alias);
+ $resTarget->setVal($this->expression->toAst());
+
+ $node = new Node();
+ $node->setResTarget($resTarget);
+
+ return $node;
+ }
+
+ public function withAlias(string $alias) : self
+ {
+ return new self($this->expression, $alias);
+ }
+
+ public function withExpression(Expression $expression) : self
+ {
+ return new self($expression, $this->alias);
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/ArrayExpression.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/ArrayExpression.php
new file mode 100644
index 000000000..55fba76db
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/ArrayExpression.php
@@ -0,0 +1,79 @@
+ $elements
+ */
+ public function __construct(
+ private array $elements,
+ ) {
+ }
+
+ public static function fromAst(Node $node) : static
+ {
+ $arrayExpr = $node->getAArrayExpr();
+
+ if ($arrayExpr === null) {
+ throw InvalidAstException::unexpectedNodeType('A_ArrayExpr', 'unknown');
+ }
+
+ $elements = $arrayExpr->getElements();
+
+ $expressions = [];
+
+ if ($elements !== null) {
+ foreach ($elements as $elementNode) {
+ $expressions[] = self::expressionFromNode($elementNode);
+ }
+ }
+
+ return new self($expressions);
+ }
+
+ public function as(string $alias) : AliasedExpression
+ {
+ return new AliasedExpression($this, $alias);
+ }
+
+ /**
+ * @return array
+ */
+ public function elements() : array
+ {
+ return $this->elements;
+ }
+
+ public function toAst() : Node
+ {
+ $elementNodes = [];
+
+ foreach ($this->elements as $element) {
+ $elementNodes[] = $element->toAst();
+ }
+
+ $arrayExpr = new A_ArrayExpr();
+ $arrayExpr->setElements($elementNodes);
+ $arrayExpr->setLocation(-1);
+
+ $node = new Node();
+ $node->setAArrayExpr($arrayExpr);
+
+ return $node;
+ }
+
+ private static function expressionFromNode(Node $node) : Expression
+ {
+ return ExpressionFactory::fromAst($node);
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/BinaryExpression.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/BinaryExpression.php
new file mode 100644
index 000000000..c7afaed2a
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/BinaryExpression.php
@@ -0,0 +1,104 @@
+getAExpr();
+
+ if ($aExpr === null) {
+ throw InvalidAstException::unexpectedNodeType('A_Expr', 'unknown');
+ }
+
+ if ($aExpr->getKind() !== A_Expr_Kind::AEXPR_OP) {
+ throw InvalidAstException::invalidFieldValue('kind', 'A_Expr', 'must be AEXPR_OP for binary expression');
+ }
+
+ $lexpr = $aExpr->getLexpr();
+ $rexpr = $aExpr->getRexpr();
+
+ if ($lexpr === null) {
+ throw InvalidAstException::missingRequiredField('lexpr', 'A_Expr');
+ }
+
+ if ($rexpr === null) {
+ throw InvalidAstException::missingRequiredField('rexpr', 'A_Expr');
+ }
+
+ $name = $aExpr->getName();
+
+ if ($name === null || \count($name) === 0) {
+ throw InvalidAstException::missingRequiredField('name', 'A_Expr');
+ }
+
+ $operatorNode = $name[\count($name) - 1];
+ $operatorString = $operatorNode->getString();
+
+ if ($operatorString === null) {
+ throw InvalidAstException::invalidFieldValue('name', 'A_Expr', 'operator must be a String node');
+ }
+
+ return new self(
+ ExpressionFactory::fromAst($lexpr),
+ $operatorString->getSval(),
+ ExpressionFactory::fromAst($rexpr)
+ );
+ }
+
+ public function as(string $alias) : AliasedExpression
+ {
+ return new AliasedExpression($this, $alias);
+ }
+
+ public function left() : Expression
+ {
+ return $this->left;
+ }
+
+ public function operator() : string
+ {
+ return $this->operator;
+ }
+
+ public function right() : Expression
+ {
+ return $this->right;
+ }
+
+ public function toAst() : Node
+ {
+ $operatorNode = new Node();
+ $operatorString = new PBString();
+ $operatorString->setSval($this->operator);
+ $operatorNode->setString($operatorString);
+
+ $aExpr = new A_Expr();
+ $aExpr->setKind(A_Expr_Kind::AEXPR_OP);
+ $aExpr->setName([$operatorNode]);
+ $aExpr->setLexpr($this->left->toAst());
+ $aExpr->setRexpr($this->right->toAst());
+ $aExpr->setLocation(-1);
+
+ $node = new Node();
+ $node->setAExpr($aExpr);
+
+ return $node;
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/CaseExpression.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/CaseExpression.php
new file mode 100644
index 000000000..9c0b6bec8
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/CaseExpression.php
@@ -0,0 +1,124 @@
+ $whenClauses WHEN clauses
+ * @param null|Expression $elseResult ELSE clause result
+ */
+ public function __construct(
+ private ?Expression $arg,
+ private array $whenClauses,
+ private ?Expression $elseResult = null,
+ ) {
+ if ($this->whenClauses === []) {
+ throw InvalidExpressionException::emptyArray('WHEN clauses');
+ }
+ }
+
+ public static function fromAst(Node $node) : static
+ {
+ $caseExpr = $node->getCaseExpr();
+
+ if ($caseExpr === null) {
+ throw InvalidAstException::unexpectedNodeType('CaseExpr', 'unknown');
+ }
+
+ $argNode = $caseExpr->getArg();
+ $arg = $argNode !== null ? ExpressionFactory::fromAst($argNode) : null;
+
+ $argsNodes = $caseExpr->getArgs();
+
+ if ($argsNodes === null || \count($argsNodes) === 0) {
+ throw InvalidAstException::missingRequiredField('args', 'CaseExpr');
+ }
+
+ $whenClauses = [];
+
+ foreach ($argsNodes as $whenNode) {
+ $whenClauses[] = WhenClause::fromAst($whenNode);
+ }
+
+ if ($whenClauses === []) {
+ throw InvalidAstException::invalidFieldValue('args', 'CaseExpr', 'cannot be empty');
+ }
+
+ $defResultNode = $caseExpr->getDefresult();
+ $elseResult = $defResultNode !== null ? ExpressionFactory::fromAst($defResultNode) : null;
+
+ return new self($arg, $whenClauses, $elseResult);
+ }
+
+ public function as(string $alias) : AliasedExpression
+ {
+ return new AliasedExpression($this, $alias);
+ }
+
+ public function getArg() : ?Expression
+ {
+ return $this->arg;
+ }
+
+ public function getElseResult() : ?Expression
+ {
+ return $this->elseResult;
+ }
+
+ /**
+ * @return non-empty-list
+ */
+ public function getWhenClauses() : array
+ {
+ return $this->whenClauses;
+ }
+
+ public function toAst() : Node
+ {
+ $caseExpr = new CaseExpr();
+
+ if ($this->arg !== null) {
+ $caseExpr->setArg($this->arg->toAst());
+ }
+
+ $whenNodes = [];
+
+ foreach ($this->whenClauses as $whenClause) {
+ $whenNodes[] = $whenClause->toAst();
+ }
+
+ $caseExpr->setArgs($whenNodes);
+
+ if ($this->elseResult !== null) {
+ $caseExpr->setDefresult($this->elseResult->toAst());
+ }
+
+ $node = new Node();
+ $node->setCaseExpr($caseExpr);
+
+ return $node;
+ }
+
+ public function withElse(Expression $elseResult) : self
+ {
+ return new self($this->arg, $this->whenClauses, $elseResult);
+ }
+
+ public function withWhen(WhenClause ...$whenClauses) : self
+ {
+ $clauses = \array_values($whenClauses);
+
+ if ($clauses === []) {
+ throw InvalidExpressionException::emptyArray('WHEN clauses');
+ }
+
+ return new self($this->arg, $clauses, $this->elseResult);
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/Coalesce.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/Coalesce.php
new file mode 100644
index 000000000..9e00a285f
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/Coalesce.php
@@ -0,0 +1,81 @@
+ $expressions
+ */
+ public function __construct(
+ private array $expressions,
+ ) {
+ if (\count($this->expressions) < 2) {
+ throw new \InvalidArgumentException('COALESCE requires at least 2 expressions');
+ }
+ }
+
+ public static function fromAst(Node $node) : static
+ {
+ $coalesceExpr = $node->getCoalesceExpr();
+
+ if ($coalesceExpr === null) {
+ throw InvalidAstException::unexpectedNodeType('CoalesceExpr', 'unknown');
+ }
+
+ $args = $coalesceExpr->getArgs();
+
+ if ($args === null || \count($args) < 2) {
+ throw InvalidAstException::invalidFieldValue('args', 'CoalesceExpr', 'must have at least 2 arguments');
+ }
+
+ $expressions = [];
+
+ foreach ($args as $argNode) {
+ $expressions[] = ExpressionFactory::fromAst($argNode);
+ }
+
+ return new self($expressions);
+ }
+
+ public function as(string $alias) : AliasedExpression
+ {
+ return new AliasedExpression($this, $alias);
+ }
+
+ /**
+ * @return array
+ */
+ public function expressions() : array
+ {
+ return $this->expressions;
+ }
+
+ public function toAst() : Node
+ {
+ $args = [];
+
+ foreach ($this->expressions as $expression) {
+ $args[] = $expression->toAst();
+ }
+
+ $coalesceExpr = new CoalesceExpr();
+ $coalesceExpr->setArgs($args);
+ $coalesceExpr->setCoalescetype(0);
+ $coalesceExpr->setCoalescecollid(0);
+ $coalesceExpr->setLocation(-1);
+
+ $node = new Node();
+ $node->setCoalesceExpr($coalesceExpr);
+
+ return $node;
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/Column.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/Column.php
new file mode 100644
index 000000000..abf520864
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/Column.php
@@ -0,0 +1,151 @@
+ $parts
+ */
+ private function __construct(
+ private array $parts,
+ ) {
+ if ($parts === []) {
+ throw InvalidExpressionException::emptyArray('Column parts');
+ }
+
+ foreach ($parts as $part) {
+ if ($part === '') {
+ throw InvalidExpressionException::invalidValue('Column part', $part);
+ }
+ }
+ }
+
+ public static function fromAst(Node $node) : static
+ {
+ $columnRef = $node->getColumnRef();
+
+ if ($columnRef === null) {
+ throw InvalidAstException::unexpectedNodeType('ColumnRef', 'unknown');
+ }
+
+ $fields = $columnRef->getFields();
+
+ if ($fields === null || \count($fields) === 0) {
+ throw InvalidAstException::missingRequiredField('fields', 'ColumnRef');
+ }
+
+ $parts = [];
+
+ foreach ($fields as $field) {
+ $stringNode = $field->getString();
+
+ if ($stringNode === null) {
+ throw InvalidAstException::invalidFieldValue('fields', 'ColumnRef', 'Expected String node');
+ }
+
+ $parts[] = $stringNode->getSval();
+ }
+
+ return new self($parts);
+ }
+
+ /**
+ * @param list $parts
+ */
+ public static function fromParts(array $parts) : self
+ {
+ return new self($parts);
+ }
+
+ /**
+ * Create a column reference from a simple column name.
+ */
+ public static function name(string $name) : self
+ {
+ return new self([$name]);
+ }
+
+ /**
+ * Create a column reference from schema, table, and column name.
+ */
+ public static function schemaTableColumn(string $schema, string $table, string $column) : self
+ {
+ return new self([$schema, $table, $column]);
+ }
+
+ /**
+ * Create a column reference from table and column name.
+ */
+ public static function tableColumn(string $table, string $column) : self
+ {
+ return new self([$table, $column]);
+ }
+
+ public function as(string $alias) : AliasedExpression
+ {
+ return AliasedExpression::create($this, $alias);
+ }
+
+ public function columnName() : string
+ {
+ return $this->parts[\count($this->parts) - 1];
+ }
+
+ /**
+ * @return list
+ */
+ public function parts() : array
+ {
+ return $this->parts;
+ }
+
+ public function schemaName() : ?string
+ {
+ if (\count($this->parts) < 3) {
+ return null;
+ }
+
+ return $this->parts[0];
+ }
+
+ public function tableName() : ?string
+ {
+ if (\count($this->parts) < 2) {
+ return null;
+ }
+
+ return $this->parts[\count($this->parts) - 2];
+ }
+
+ public function toAst() : Node
+ {
+ $columnRef = new ColumnRef();
+ $fields = [];
+
+ foreach ($this->parts as $part) {
+ $stringNode = new PBString();
+ $stringNode->setSval($part);
+
+ $node = new Node();
+ $node->setString($stringNode);
+
+ $fields[] = $node;
+ }
+
+ $columnRef->setFields($fields);
+
+ $node = new Node();
+ $node->setColumnRef($columnRef);
+
+ return $node;
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/Expression.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/Expression.php
new file mode 100644
index 000000000..b269e811d
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/Expression.php
@@ -0,0 +1,18 @@
+getAStar() !== null) {
+ return Star::fromAst($node);
+ }
+
+ if ($node->getColumnRef() !== null) {
+ $columnRef = $node->getColumnRef();
+ $fields = $columnRef->getFields();
+
+ if ($fields !== null && \count($fields) > 0) {
+ $lastField = $fields[\count($fields) - 1];
+
+ if ($lastField->getAStar() !== null) {
+ return Star::fromAst($node);
+ }
+ }
+
+ return Column::fromAst($node);
+ }
+
+ if ($node->getAConst() !== null) {
+ return Literal::fromAst($node);
+ }
+
+ if ($node->getFuncCall() !== null) {
+ $funcCall = $node->getFuncCall();
+
+ if ($funcCall->getOver() !== null) {
+ return WindowFunction::fromAst($node);
+ }
+
+ if ($funcCall->getAggStar() || $funcCall->getAggDistinct() || $funcCall->getAggOrder() !== null || $funcCall->getAggFilter() !== null) {
+ return AggregateCall::fromAst($node);
+ }
+
+ return FunctionCall::fromAst($node);
+ }
+
+ if ($node->getTypeCast() !== null) {
+ return TypeCast::fromAst($node);
+ }
+
+ if ($node->getAExpr() !== null) {
+ $aExpr = $node->getAExpr();
+ $kind = $aExpr->getKind();
+
+ if ($kind === A_Expr_Kind::AEXPR_NULLIF) {
+ return NullIf::fromAst($node);
+ }
+
+ return BinaryExpression::fromAst($node);
+ }
+
+ if ($node->getCoalesceExpr() !== null) {
+ return Coalesce::fromAst($node);
+ }
+
+ if ($node->getResTarget() !== null) {
+ $resTarget = $node->getResTarget();
+ $aliasName = $resTarget->getName();
+
+ // If there's an alias, return an AliasedExpression
+ if ($aliasName !== null && $aliasName !== '') {
+ return AliasedExpression::fromAst($node);
+ }
+
+ // Otherwise, unwrap and return the inner expression
+ $valNode = $resTarget->getVal();
+
+ if ($valNode !== null) {
+ return self::fromAst($valNode);
+ }
+ }
+
+ if ($node->getParamRef() !== null) {
+ return Parameter::fromAst($node);
+ }
+
+ if ($node->getCaseExpr() !== null) {
+ return CaseExpression::fromAst($node);
+ }
+
+ if ($node->getSubLink() !== null) {
+ return Subquery::fromAst($node);
+ }
+
+ if ($node->getMinMaxExpr() !== null) {
+ $minMaxExpr = $node->getMinMaxExpr();
+
+ if ($minMaxExpr->getOp() === MinMaxOp::IS_GREATEST) {
+ return Greatest::fromAst($node);
+ }
+
+ return Least::fromAst($node);
+ }
+
+ if ($node->getRowExpr() !== null) {
+ return RowExpression::fromAst($node);
+ }
+
+ if ($node->getAArrayExpr() !== null) {
+ return ArrayExpression::fromAst($node);
+ }
+
+ throw UnsupportedNodeException::forNodeType('Unknown expression node type');
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/FunctionCall.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/FunctionCall.php
new file mode 100644
index 000000000..a780c4045
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/FunctionCall.php
@@ -0,0 +1,126 @@
+ $funcName Function name parts (e.g., ['pg_catalog', 'count'] or ['my_func'])
+ * @param list $args Function arguments
+ */
+ public function __construct(
+ private array $funcName,
+ private array $args = [],
+ ) {
+ if ($this->funcName === []) {
+ throw InvalidExpressionException::emptyArray('Function name');
+ }
+ }
+
+ public static function fromAst(Node $node) : static
+ {
+ $funcCall = $node->getFuncCall();
+
+ if ($funcCall === null) {
+ throw InvalidAstException::unexpectedNodeType('FuncCall', 'unknown');
+ }
+
+ $funcNameNodes = $funcCall->getFuncname();
+
+ if ($funcNameNodes === null || \count($funcNameNodes) === 0) {
+ throw InvalidAstException::missingRequiredField('funcname', 'FuncCall');
+ }
+
+ $funcName = [];
+
+ foreach ($funcNameNodes as $nameNode) {
+ $stringNode = $nameNode->getString();
+
+ if ($stringNode === null) {
+ throw InvalidAstException::invalidFieldValue('funcname', 'FuncCall', 'expected String node');
+ }
+
+ $funcName[] = $stringNode->getSval();
+ }
+
+ if ($funcName === []) {
+ throw InvalidAstException::invalidFieldValue('funcname', 'FuncCall', 'cannot be empty');
+ }
+
+ $args = [];
+ $argsNodes = $funcCall->getArgs();
+
+ if ($argsNodes !== null) {
+ foreach ($argsNodes as $argNode) {
+ $args[] = ExpressionFactory::fromAst($argNode);
+ }
+ }
+
+ return new self($funcName, $args);
+ }
+
+ public function as(string $alias) : AliasedExpression
+ {
+ return new AliasedExpression($this, $alias);
+ }
+
+ /**
+ * @return list
+ */
+ public function getArgs() : array
+ {
+ return $this->args;
+ }
+
+ /**
+ * @return non-empty-list
+ */
+ public function getFuncName() : array
+ {
+ return $this->funcName;
+ }
+
+ public function toAst() : Node
+ {
+ $funcCall = new FuncCall();
+ $funcNameNodes = [];
+
+ foreach ($this->funcName as $namePart) {
+ $stringNode = new PBString();
+ $stringNode->setSval($namePart);
+
+ $nameNode = new Node();
+ $nameNode->setString($stringNode);
+
+ $funcNameNodes[] = $nameNode;
+ }
+
+ $funcCall->setFuncname($funcNameNodes);
+
+ $argNodes = [];
+
+ foreach ($this->args as $arg) {
+ $argNodes[] = $arg->toAst();
+ }
+
+ $funcCall->setArgs($argNodes);
+
+ $node = new Node();
+ $node->setFuncCall($funcCall);
+
+ return $node;
+ }
+
+ public function withArgs(Expression ...$args) : self
+ {
+ return new self($this->funcName, \array_values($args));
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/Greatest.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/Greatest.php
new file mode 100644
index 000000000..bbed38708
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/Greatest.php
@@ -0,0 +1,92 @@
+ $expressions
+ */
+ public function __construct(
+ private array $expressions,
+ ) {
+ if (\count($this->expressions) < 2) {
+ throw new \InvalidArgumentException('GREATEST requires at least 2 expressions');
+ }
+ }
+
+ public static function fromAst(Node $node) : static
+ {
+ $minMaxExpr = $node->getMinMaxExpr();
+
+ if ($minMaxExpr === null) {
+ throw InvalidAstException::unexpectedNodeType('MinMaxExpr', 'unknown');
+ }
+
+ if ($minMaxExpr->getOp() !== MinMaxOp::IS_GREATEST) {
+ throw InvalidAstException::invalidFieldValue('op', 'MinMaxExpr', 'must be IS_GREATEST');
+ }
+
+ $args = $minMaxExpr->getArgs();
+
+ if ($args === null || \count($args) < 2) {
+ throw InvalidAstException::invalidFieldValue('args', 'MinMaxExpr', 'must have at least 2 arguments');
+ }
+
+ $expressions = [];
+
+ foreach ($args as $argNode) {
+ $expressions[] = self::expressionFromNode($argNode);
+ }
+
+ return new self($expressions);
+ }
+
+ public function as(string $alias) : AliasedExpression
+ {
+ return new AliasedExpression($this, $alias);
+ }
+
+ /**
+ * @return array
+ */
+ public function expressions() : array
+ {
+ return $this->expressions;
+ }
+
+ public function toAst() : Node
+ {
+ $args = [];
+
+ foreach ($this->expressions as $expression) {
+ $args[] = $expression->toAst();
+ }
+
+ $minMaxExpr = new MinMaxExpr();
+ $minMaxExpr->setOp(MinMaxOp::IS_GREATEST);
+ $minMaxExpr->setArgs($args);
+ $minMaxExpr->setMinmaxtype(0);
+ $minMaxExpr->setMinmaxcollid(0);
+ $minMaxExpr->setInputcollid(0);
+ $minMaxExpr->setLocation(-1);
+
+ $node = new Node();
+ $node->setMinMaxExpr($minMaxExpr);
+
+ return $node;
+ }
+
+ private static function expressionFromNode(Node $node) : Expression
+ {
+ return ExpressionFactory::fromAst($node);
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/Least.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/Least.php
new file mode 100644
index 000000000..ef92723ae
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/Least.php
@@ -0,0 +1,92 @@
+ $expressions
+ */
+ public function __construct(
+ private array $expressions,
+ ) {
+ if (\count($this->expressions) < 2) {
+ throw new \InvalidArgumentException('LEAST requires at least 2 expressions');
+ }
+ }
+
+ public static function fromAst(Node $node) : static
+ {
+ $minMaxExpr = $node->getMinMaxExpr();
+
+ if ($minMaxExpr === null) {
+ throw InvalidAstException::unexpectedNodeType('MinMaxExpr', 'unknown');
+ }
+
+ if ($minMaxExpr->getOp() !== MinMaxOp::IS_LEAST) {
+ throw InvalidAstException::invalidFieldValue('op', 'MinMaxExpr', 'must be IS_LEAST');
+ }
+
+ $args = $minMaxExpr->getArgs();
+
+ if ($args === null || \count($args) < 2) {
+ throw InvalidAstException::invalidFieldValue('args', 'MinMaxExpr', 'must have at least 2 arguments');
+ }
+
+ $expressions = [];
+
+ foreach ($args as $argNode) {
+ $expressions[] = self::expressionFromNode($argNode);
+ }
+
+ return new self($expressions);
+ }
+
+ public function as(string $alias) : AliasedExpression
+ {
+ return new AliasedExpression($this, $alias);
+ }
+
+ /**
+ * @return array
+ */
+ public function expressions() : array
+ {
+ return $this->expressions;
+ }
+
+ public function toAst() : Node
+ {
+ $args = [];
+
+ foreach ($this->expressions as $expression) {
+ $args[] = $expression->toAst();
+ }
+
+ $minMaxExpr = new MinMaxExpr();
+ $minMaxExpr->setOp(MinMaxOp::IS_LEAST);
+ $minMaxExpr->setArgs($args);
+ $minMaxExpr->setMinmaxtype(0);
+ $minMaxExpr->setMinmaxcollid(0);
+ $minMaxExpr->setInputcollid(0);
+ $minMaxExpr->setLocation(-1);
+
+ $node = new Node();
+ $node->setMinMaxExpr($minMaxExpr);
+
+ return $node;
+ }
+
+ private static function expressionFromNode(Node $node) : Expression
+ {
+ return ExpressionFactory::fromAst($node);
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/Literal.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/Literal.php
new file mode 100644
index 000000000..66f3ba0d9
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/Literal.php
@@ -0,0 +1,157 @@
+getAConst();
+
+ if ($aConst === null) {
+ throw InvalidAstException::unexpectedNodeType('A_Const', 'unknown');
+ }
+
+ if ($aConst->getIsnull()) {
+ return new self(null);
+ }
+
+ if ($aConst->hasIval()) {
+ $ival = $aConst->getIval();
+ \assert($ival instanceof Integer);
+
+ return new self($ival->getIval());
+ }
+
+ if ($aConst->hasFval()) {
+ $fval = $aConst->getFval();
+ \assert($fval instanceof PBFloat);
+ $floatStr = $fval->getFval();
+
+ return new self((float) $floatStr);
+ }
+
+ if ($aConst->hasSval()) {
+ $sval = $aConst->getSval();
+ \assert($sval instanceof PBString);
+
+ return new self($sval->getSval());
+ }
+
+ if ($aConst->hasBoolval()) {
+ $boolval = $aConst->getBoolval();
+ \assert($boolval instanceof Boolean);
+
+ return new self($boolval->getBoolval());
+ }
+
+ throw InvalidAstException::missingRequiredField('value', 'A_Const');
+ }
+
+ public static function int(int $value) : self
+ {
+ return new self($value);
+ }
+
+ public static function null() : self
+ {
+ return new self(null);
+ }
+
+ public static function string(string $value) : self
+ {
+ return new self($value);
+ }
+
+ public function as(string $alias) : AliasedExpression
+ {
+ return AliasedExpression::create($this, $alias);
+ }
+
+ public function isBool() : bool
+ {
+ return \is_bool($this->value);
+ }
+
+ public function isFloat() : bool
+ {
+ return \is_float($this->value);
+ }
+
+ public function isInt() : bool
+ {
+ return \is_int($this->value);
+ }
+
+ public function isNull() : bool
+ {
+ return $this->value === null;
+ }
+
+ public function isString() : bool
+ {
+ return \is_string($this->value);
+ }
+
+ public function toAst() : Node
+ {
+ $aConst = new A_Const();
+
+ if ($this->value === null) {
+ $aConst->setIsnull(true);
+ } elseif (\is_int($this->value)) {
+ $integer = new Integer();
+ $integer->setIval($this->value);
+
+ /** @phpstan-ignore argument.type (protobuf PHPDoc says int but actually expects Integer) */
+ $aConst->setIval($integer);
+ } elseif (\is_float($this->value)) {
+ $float = new PBFloat();
+ $float->setFval((string) $this->value);
+ $aConst->setFval($float);
+ } elseif (\is_string($this->value)) {
+ $string = new PBString();
+ $string->setSval($this->value);
+ $aConst->setSval($string);
+ } elseif (\is_bool($this->value)) {
+ $boolean = new Boolean();
+ $boolean->setBoolval($this->value);
+
+ /** @phpstan-ignore argument.type (protobuf PHPDoc says bool but actually expects Boolean) */
+ $aConst->setBoolval($boolean);
+ }
+
+ $node = new Node();
+ $node->setAConst($aConst);
+
+ return $node;
+ }
+
+ public function value() : string|int|float|bool|null
+ {
+ return $this->value;
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/NullIf.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/NullIf.php
new file mode 100644
index 000000000..d3ff046bf
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/NullIf.php
@@ -0,0 +1,76 @@
+getAExpr();
+
+ if ($aExpr === null) {
+ throw InvalidAstException::unexpectedNodeType('A_Expr', 'unknown');
+ }
+
+ if ($aExpr->getKind() !== A_Expr_Kind::AEXPR_NULLIF) {
+ throw InvalidAstException::invalidFieldValue('kind', 'A_Expr', 'Expected AEXPR_NULLIF for NullIf expression');
+ }
+
+ $lexpr = $aExpr->getLexpr();
+ $rexpr = $aExpr->getRexpr();
+
+ if ($lexpr === null || $rexpr === null) {
+ throw InvalidAstException::missingRequiredField('lexpr/rexpr', 'A_Expr');
+ }
+
+ return new self(
+ ExpressionFactory::fromAst($lexpr),
+ ExpressionFactory::fromAst($rexpr)
+ );
+ }
+
+ public function as(string $alias) : AliasedExpression
+ {
+ return new AliasedExpression($this, $alias);
+ }
+
+ public function first() : Expression
+ {
+ return $this->first;
+ }
+
+ public function second() : Expression
+ {
+ return $this->second;
+ }
+
+ public function toAst() : Node
+ {
+ $nameString = new PBString();
+ $nameString->setSval('=');
+ $nameNode = new Node(['string' => $nameString]);
+
+ $aExpr = new A_Expr([
+ 'kind' => A_Expr_Kind::AEXPR_NULLIF,
+ 'name' => [$nameNode],
+ 'lexpr' => $this->first->toAst(),
+ 'rexpr' => $this->second->toAst(),
+ ]);
+
+ return new Node(['a_expr' => $aExpr]);
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/Parameter.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/Parameter.php
new file mode 100644
index 000000000..2d756fd32
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/Parameter.php
@@ -0,0 +1,68 @@
+getParamRef();
+
+ if ($paramRef === null) {
+ throw InvalidAstException::unexpectedNodeType('ParamRef', 'unknown');
+ }
+
+ $number = $paramRef->getNumber();
+
+ if ($number < 1) {
+ throw InvalidAstException::invalidFieldValue('number', 'ParamRef', 'Must be >= 1');
+ }
+
+ return new self($number);
+ }
+
+ /**
+ * Create a parameter reference with the given position number.
+ */
+ public static function positional(int $number) : self
+ {
+ return new self($number);
+ }
+
+ public function as(string $alias) : AliasedExpression
+ {
+ return AliasedExpression::create($this, $alias);
+ }
+
+ public function number() : int
+ {
+ return $this->number;
+ }
+
+ public function toAst() : Node
+ {
+ $paramRef = new ParamRef();
+ $paramRef->setNumber($this->number);
+
+ $node = new Node();
+ $node->setParamRef($paramRef);
+
+ return $node;
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/RawExpression.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/RawExpression.php
new file mode 100644
index 000000000..ec54a1ad6
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/RawExpression.php
@@ -0,0 +1,81 @@
+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/RowExpression.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/RowExpression.php
new file mode 100644
index 000000000..4e07fcfb8
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/RowExpression.php
@@ -0,0 +1,98 @@
+ $args
+ * @param bool $explicitRow Whether to use ROW keyword (true) or just parentheses (false)
+ */
+ public function __construct(
+ private array $args,
+ private bool $explicitRow = false,
+ ) {
+ if (\count($this->args) === 0) {
+ throw new \InvalidArgumentException('RowExpression requires at least 1 expression');
+ }
+ }
+
+ public static function fromAst(Node $node) : static
+ {
+ $rowExpr = $node->getRowExpr();
+
+ if ($rowExpr === null) {
+ throw InvalidAstException::unexpectedNodeType('RowExpr', 'unknown');
+ }
+
+ $args = $rowExpr->getArgs();
+
+ if ($args === null || \count($args) === 0) {
+ throw InvalidAstException::invalidFieldValue('args', 'RowExpr', 'must have at least 1 argument');
+ }
+
+ $expressions = [];
+
+ foreach ($args as $argNode) {
+ $expressions[] = self::expressionFromNode($argNode);
+ }
+
+ $rowFormat = $rowExpr->getRowFormat();
+ $explicitRow = $rowFormat === CoercionForm::COERCE_EXPLICIT_CALL;
+
+ return new self($expressions, $explicitRow);
+ }
+
+ /**
+ * @return array
+ */
+ public function args() : array
+ {
+ return $this->args;
+ }
+
+ public function as(string $alias) : AliasedExpression
+ {
+ return new AliasedExpression($this, $alias);
+ }
+
+ public function isExplicitRow() : bool
+ {
+ return $this->explicitRow;
+ }
+
+ public function toAst() : Node
+ {
+ $argNodes = [];
+
+ foreach ($this->args as $arg) {
+ $argNodes[] = $arg->toAst();
+ }
+
+ $rowExpr = new RowExpr();
+ $rowExpr->setArgs($argNodes);
+ $rowExpr->setRowFormat(
+ $this->explicitRow ? CoercionForm::COERCE_EXPLICIT_CALL : CoercionForm::COERCE_IMPLICIT_CAST
+ );
+ $rowExpr->setRowTypeid(0);
+ $rowExpr->setLocation(-1);
+
+ $node = new Node();
+ $node->setRowExpr($rowExpr);
+
+ return $node;
+ }
+
+ private static function expressionFromNode(Node $node) : Expression
+ {
+ return ExpressionFactory::fromAst($node);
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/Star.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/Star.php
new file mode 100644
index 000000000..b47e96e30
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/Star.php
@@ -0,0 +1,121 @@
+getAStar();
+
+ if ($aStar !== null) {
+ return new self();
+ }
+
+ $columnRef = $node->getColumnRef();
+
+ if ($columnRef !== null) {
+ $fields = $columnRef->getFields();
+
+ if ($fields === null || \count($fields) === 0) {
+ throw InvalidAstException::missingRequiredField('fields', 'ColumnRef');
+ }
+
+ $lastField = $fields[\count($fields) - 1];
+ $aStar = $lastField->getAStar();
+
+ if ($aStar === null) {
+ throw InvalidAstException::unexpectedNodeType('A_Star', 'unknown');
+ }
+
+ if (\count($fields) === 1) {
+ return new self();
+ }
+
+ if (\count($fields) === 2) {
+ $tableField = $fields[0];
+ $tableString = $tableField->getString();
+
+ if ($tableString === null) {
+ throw InvalidAstException::invalidFieldValue('fields[0]', 'ColumnRef', 'Expected String node');
+ }
+
+ return new self($tableString->getSval());
+ }
+
+ throw InvalidAstException::invalidFieldValue('fields', 'ColumnRef', 'Star can only have table prefix');
+ }
+
+ throw InvalidAstException::unexpectedNodeType('A_Star or ColumnRef', 'unknown');
+ }
+
+ /**
+ * Create a qualified star: SELECT table.*.
+ */
+ public static function fromTable(string $table) : self
+ {
+ return new self($table);
+ }
+
+ public function as(string $alias) : AliasedExpression
+ {
+ return AliasedExpression::create($this, $alias);
+ }
+
+ public function isQualified() : bool
+ {
+ return $this->table !== null;
+ }
+
+ public function table() : ?string
+ {
+ return $this->table;
+ }
+
+ public function toAst() : Node
+ {
+ $columnRef = new ColumnRef();
+ $fields = [];
+
+ if ($this->table !== null) {
+ $tableString = new PBString();
+ $tableString->setSval($this->table);
+ $tableNode = new Node();
+ $tableNode->setString($tableString);
+ $fields[] = $tableNode;
+ }
+
+ $aStar = new A_Star();
+ $starNode = new Node();
+ $starNode->setAStar($aStar);
+ $fields[] = $starNode;
+
+ $columnRef->setFields($fields);
+
+ $node = new Node();
+ $node->setColumnRef($columnRef);
+
+ return $node;
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/Subquery.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/Subquery.php
new file mode 100644
index 000000000..6069c6a1c
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/Subquery.php
@@ -0,0 +1,63 @@
+getSubLink();
+
+ if ($subLink === null) {
+ throw InvalidAstException::unexpectedNodeType('SubLink', 'unknown');
+ }
+
+ if ($subLink->getSubLinkType() !== SubLinkType::EXPR_SUBLINK) {
+ throw InvalidAstException::invalidFieldValue(
+ 'subLinkType',
+ 'SubLink',
+ \sprintf('expected EXPR_SUBLINK (%d), got %d', SubLinkType::EXPR_SUBLINK, $subLink->getSubLinkType())
+ );
+ }
+
+ $subselectNode = $subLink->getSubselect();
+
+ if ($subselectNode === null) {
+ throw InvalidAstException::missingRequiredField('subselect', 'SubLink');
+ }
+
+ return new self($subselectNode);
+ }
+
+ public function as(string $alias) : AliasedExpression
+ {
+ return new AliasedExpression($this, $alias);
+ }
+
+ public function getSelectStatement() : Node
+ {
+ return $this->selectStatement;
+ }
+
+ public function toAst() : Node
+ {
+ $subLink = new SubLink();
+ $subLink->setSubLinkType(SubLinkType::EXPR_SUBLINK);
+ $subLink->setSubselect($this->selectStatement);
+
+ $node = new Node();
+ $node->setSubLink($subLink);
+
+ return $node;
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/TypeCast.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/TypeCast.php
new file mode 100644
index 000000000..9f8f1f2dd
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/TypeCast.php
@@ -0,0 +1,135 @@
+ $typeName Type name parts (e.g., ['pg_catalog', 'int4'] or ['varchar'])
+ */
+ public function __construct(
+ private Expression $expression,
+ private array $typeName,
+ ) {
+ if ($this->typeName === []) {
+ throw InvalidExpressionException::emptyArray('Type name');
+ }
+ }
+
+ public static function fromAst(Node $node) : static
+ {
+ $typeCast = $node->getTypeCast();
+
+ if ($typeCast === null) {
+ throw InvalidAstException::unexpectedNodeType('TypeCast', 'unknown');
+ }
+
+ $argNode = $typeCast->getArg();
+
+ if ($argNode === null) {
+ throw InvalidAstException::missingRequiredField('arg', 'TypeCast');
+ }
+
+ $expression = ExpressionFactory::fromAst($argNode);
+
+ $typeNameNode = $typeCast->getTypeName();
+
+ if ($typeNameNode === null) {
+ throw InvalidAstException::missingRequiredField('typeName', 'TypeCast');
+ }
+
+ $namesNodes = $typeNameNode->getNames();
+
+ if ($namesNodes === null || \count($namesNodes) === 0) {
+ throw InvalidAstException::missingRequiredField('names', 'TypeName');
+ }
+
+ $typeName = [];
+
+ foreach ($namesNodes as $nameNode) {
+ $stringNode = $nameNode->getString();
+
+ if ($stringNode === null) {
+ throw InvalidAstException::invalidFieldValue('names', 'TypeName', 'expected String node');
+ }
+
+ $typeName[] = $stringNode->getSval();
+ }
+
+ if ($typeName === []) {
+ throw InvalidAstException::invalidFieldValue('names', 'TypeName', 'cannot be empty');
+ }
+
+ return new self($expression, $typeName);
+ }
+
+ public function as(string $alias) : AliasedExpression
+ {
+ return new AliasedExpression($this, $alias);
+ }
+
+ public function getExpression() : Expression
+ {
+ return $this->expression;
+ }
+
+ /**
+ * @return non-empty-list
+ */
+ public function getTypeName() : array
+ {
+ return $this->typeName;
+ }
+
+ public function toAst() : Node
+ {
+ $typeName = new TypeName();
+ $namesNodes = [];
+
+ foreach ($this->typeName as $namePart) {
+ $stringNode = new PBString();
+ $stringNode->setSval($namePart);
+
+ $nameNode = new Node();
+ $nameNode->setString($stringNode);
+
+ $namesNodes[] = $nameNode;
+ }
+
+ $typeName->setNames($namesNodes);
+
+ $typeCast = new AstTypeCast();
+ $typeCast->setArg($this->expression->toAst());
+ $typeCast->setTypeName($typeName);
+
+ $node = new Node();
+ $node->setTypeCast($typeCast);
+
+ return $node;
+ }
+
+ public function withExpression(Expression $expression) : self
+ {
+ return new self($expression, $this->typeName);
+ }
+
+ public function withTypeName(string ...$typeName) : self
+ {
+ $typeNameList = \array_values($typeName);
+
+ if ($typeNameList === []) {
+ throw InvalidExpressionException::emptyArray('Type name');
+ }
+
+ return new self($this->expression, $typeNameList);
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/WhenClause.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/WhenClause.php
new file mode 100644
index 000000000..76a3d668b
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/WhenClause.php
@@ -0,0 +1,65 @@
+getCaseWhen();
+
+ if ($caseWhen === null) {
+ throw InvalidAstException::unexpectedNodeType('CaseWhen', 'unknown');
+ }
+
+ $exprNode = $caseWhen->getExpr();
+
+ if ($exprNode === null) {
+ throw InvalidAstException::missingRequiredField('expr', 'CaseWhen');
+ }
+
+ $resultNode = $caseWhen->getResult();
+
+ if ($resultNode === null) {
+ throw InvalidAstException::missingRequiredField('result', 'CaseWhen');
+ }
+
+ $condition = ExpressionFactory::fromAst($exprNode);
+ $result = ExpressionFactory::fromAst($resultNode);
+
+ return new self($condition, $result);
+ }
+
+ public function getCondition() : Expression
+ {
+ return $this->condition;
+ }
+
+ public function getResult() : Expression
+ {
+ return $this->result;
+ }
+
+ public function toAst() : Node
+ {
+ $caseWhen = new CaseWhen();
+ $caseWhen->setExpr($this->condition->toAst());
+ $caseWhen->setResult($this->result->toAst());
+
+ $node = new Node();
+ $node->setCaseWhen($caseWhen);
+
+ return $node;
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/WindowFunction.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/WindowFunction.php
new file mode 100644
index 000000000..1184dd051
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Expression/WindowFunction.php
@@ -0,0 +1,206 @@
+ $funcName Function name parts (e.g., ['row_number'] or ['rank'])
+ * @param list $args Function arguments
+ * @param list $partitionBy PARTITION BY expressions
+ * @param list $orderBy ORDER BY clauses
+ */
+ public function __construct(
+ private array $funcName,
+ private array $args = [],
+ private array $partitionBy = [],
+ private array $orderBy = [],
+ ) {
+ if ($this->funcName === []) {
+ throw InvalidExpressionException::emptyArray('Function name');
+ }
+ }
+
+ public static function fromAst(Node $node) : static
+ {
+ $funcCall = $node->getFuncCall();
+
+ if ($funcCall === null) {
+ throw InvalidAstException::unexpectedNodeType('FuncCall', 'unknown');
+ }
+
+ $overNode = $funcCall->getOver();
+
+ if ($overNode === null) {
+ throw InvalidAstException::missingRequiredField('over', 'FuncCall');
+ }
+
+ $funcNameNodes = $funcCall->getFuncname();
+
+ if ($funcNameNodes === null || \count($funcNameNodes) === 0) {
+ throw InvalidAstException::missingRequiredField('funcname', 'FuncCall');
+ }
+
+ $funcName = [];
+
+ foreach ($funcNameNodes as $nameNode) {
+ $stringNode = $nameNode->getString();
+
+ if ($stringNode === null) {
+ throw InvalidAstException::invalidFieldValue('funcname', 'FuncCall', 'expected String node');
+ }
+
+ $funcName[] = $stringNode->getSval();
+ }
+
+ if ($funcName === []) {
+ throw InvalidAstException::invalidFieldValue('funcname', 'FuncCall', 'cannot be empty');
+ }
+
+ $args = [];
+ $argsNodes = $funcCall->getArgs();
+
+ if ($argsNodes !== null) {
+ foreach ($argsNodes as $argNode) {
+ $args[] = ExpressionFactory::fromAst($argNode);
+ }
+ }
+
+ $partitionBy = [];
+ $partitionNodes = $overNode->getPartitionClause();
+
+ if ($partitionNodes !== null) {
+ foreach ($partitionNodes as $partitionNode) {
+ $partitionBy[] = ExpressionFactory::fromAst($partitionNode);
+ }
+ }
+
+ $orderBy = [];
+ $orderNodes = $overNode->getOrderClause();
+
+ if ($orderNodes !== null) {
+ foreach ($orderNodes as $orderNode) {
+ $orderBy[] = OrderBy::fromAst($orderNode);
+ }
+ }
+
+ return new self($funcName, $args, $partitionBy, $orderBy);
+ }
+
+ public function as(string $alias) : AliasedExpression
+ {
+ return new AliasedExpression($this, $alias);
+ }
+
+ /**
+ * @return list
+ */
+ public function getArgs() : array
+ {
+ return $this->args;
+ }
+
+ /**
+ * @return non-empty-list
+ */
+ public function getFuncName() : array
+ {
+ return $this->funcName;
+ }
+
+ /**
+ * @return list
+ */
+ public function getOrderBy() : array
+ {
+ return $this->orderBy;
+ }
+
+ /**
+ * @return list
+ */
+ public function getPartitionBy() : array
+ {
+ return $this->partitionBy;
+ }
+
+ public function toAst() : Node
+ {
+ $funcCall = new FuncCall();
+ $funcNameNodes = [];
+
+ foreach ($this->funcName as $namePart) {
+ $stringNode = new PBString();
+ $stringNode->setSval($namePart);
+
+ $nameNode = new Node();
+ $nameNode->setString($stringNode);
+
+ $funcNameNodes[] = $nameNode;
+ }
+
+ $funcCall->setFuncname($funcNameNodes);
+
+ $argNodes = [];
+
+ foreach ($this->args as $arg) {
+ $argNodes[] = $arg->toAst();
+ }
+
+ $funcCall->setArgs($argNodes);
+
+ $windowDef = new WindowDef();
+
+ $partitionNodes = [];
+
+ foreach ($this->partitionBy as $partition) {
+ $partitionNodes[] = $partition->toAst();
+ }
+
+ if ($partitionNodes !== []) {
+ $windowDef->setPartitionClause($partitionNodes);
+ }
+
+ $orderNodes = [];
+
+ foreach ($this->orderBy as $order) {
+ if ($order instanceof OrderByItem) {
+ $orderNodes[] = new Node(['sort_by' => $order->toAst()]);
+ } else {
+ $orderNodes[] = $order->toAst();
+ }
+ }
+
+ if ($orderNodes !== []) {
+ $windowDef->setOrderClause($orderNodes);
+ }
+
+ $funcCall->setOver($windowDef);
+
+ $node = new Node();
+ $node->setFuncCall($funcCall);
+
+ return $node;
+ }
+
+ public function withArgs(Expression ...$args) : self
+ {
+ return new self($this->funcName, \array_values($args), $this->partitionBy, $this->orderBy);
+ }
+
+ public function withOrderBy(OrderBy ...$orderBy) : self
+ {
+ return new self($this->funcName, $this->args, $this->partitionBy, \array_values($orderBy));
+ }
+
+ public function withPartitionBy(Expression ...$partitionBy) : self
+ {
+ return new self($this->funcName, $this->args, \array_values($partitionBy), $this->orderBy);
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Factory/AlterFactory.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Factory/AlterFactory.php
new file mode 100644
index 000000000..fe22ee439
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Factory/AlterFactory.php
@@ -0,0 +1,93 @@
+sequence($name, $schema);
+ }
+
+ public function table(string $table, ?string $schema = null) : AlterTableFinalStep
+ {
+ if ($schema !== null) {
+ return AlterTableBuilder::create($table, $schema);
+ }
+
+ $identifier = QualifiedIdentifier::parse($table);
+
+ return AlterTableBuilder::create($identifier->name(), $identifier->schema());
+ }
+
+ public function trigger(string $name) : AlterTriggerOnStep
+ {
+ return AlterTriggerBuilder::create($name);
+ }
+
+ public function view(string $name, ?string $schema = null) : AlterViewActionStep
+ {
+ return AlterViewBuilder::create($name, $schema);
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Factory/CopyFactory.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Factory/CopyFactory.php
new file mode 100644
index 000000000..12ab68180
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Factory/CopyFactory.php
@@ -0,0 +1,26 @@
+table($table);
+ }
+
+ public function to(string $table) : CopyToDestinationStep
+ {
+ return CopyToBuilder::create()->table($table);
+ }
+
+ public function toQuery(SelectFinalStep $query) : CopyToDestinationStep
+ {
+ return CopyToBuilder::create()->query($query);
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Factory/CreateFactory.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Factory/CreateFactory.php
new file mode 100644
index 000000000..84c6d16e0
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Factory/CreateFactory.php
@@ -0,0 +1,134 @@
+name(), $identifier->schema());
+ }
+
+ public function procedure(string $name) : CreateProcedureArgsStep
+ {
+ return CreateProcedureBuilder::create($name);
+ }
+
+ public function rangeType(string $name) : CreateRangeTypeSubtypeStep
+ {
+ return CreateRangeTypeBuilder::create($name);
+ }
+
+ public function role(string $role) : CreateRoleOptionsStep
+ {
+ return CreateRoleBuilder::create($role);
+ }
+
+ public function rule(string $name) : CreateRuleEventStep
+ {
+ return CreateRuleBuilder::create($name);
+ }
+
+ public function schema(string $name) : CreateSchemaOptionsStep
+ {
+ return CreateSchemaBuilder::create($name);
+ }
+
+ public function sequence(string $name, ?string $schema = null) : CreateSequenceOptionsStep
+ {
+ return CreateSequenceBuilder::create()->sequence($name, $schema);
+ }
+
+ public function table(string $table, ?string $schema = null) : CreateTableColumnsStep
+ {
+ if ($schema !== null) {
+ return CreateTableBuilder::create($table, $schema);
+ }
+
+ $identifier = QualifiedIdentifier::parse($table);
+
+ return CreateTableBuilder::create($identifier->name(), $identifier->schema());
+ }
+
+ public function tableAs(string $table, SelectFinalStep $query, ?string $schema = null) : CreateTableAsFinalStep
+ {
+ if ($schema !== null) {
+ return CreateTableAsBuilder::create($table, $query, $schema);
+ }
+
+ $identifier = QualifiedIdentifier::parse($table);
+
+ return CreateTableAsBuilder::create($identifier->name(), $query, $identifier->schema());
+ }
+
+ public function trigger(string $name) : CreateTriggerTimingStep
+ {
+ return CreateTriggerBuilder::create($name);
+ }
+
+ public function view(string $name, ?string $schema = null) : CreateViewOptionsStep
+ {
+ if ($schema !== null) {
+ return CreateViewBuilder::create($name, $schema);
+ }
+
+ $identifier = QualifiedIdentifier::parse($name);
+
+ return CreateViewBuilder::create($identifier->name(), $identifier->schema());
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Factory/DropFactory.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Factory/DropFactory.php
new file mode 100644
index 000000000..4cd1a6d99
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Factory/DropFactory.php
@@ -0,0 +1,98 @@
+sequence(...$sequences);
+ }
+
+ public function table(string ...$tables) : DropTableFinalStep
+ {
+ return DropTableBuilder::create(...$tables);
+ }
+
+ public function trigger(string $name) : DropTriggerOnStep
+ {
+ return DropTriggerBuilder::create($name);
+ }
+
+ public function type(string ...$types) : DropTypeFinalStep
+ {
+ return DropTypeBuilder::create(...$types);
+ }
+
+ public function view(string ...$views) : DropViewFinalStep
+ {
+ return DropViewBuilder::create(...$views);
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Insert/InsertBuilder.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Insert/InsertBuilder.php
new file mode 100644
index 000000000..cd276303d
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Insert/InsertBuilder.php
@@ -0,0 +1,522 @@
+ $columns
+ * @param list> $valuesList
+ * @param list $returning
+ */
+ private function __construct(
+ private ?WithClause $with = null,
+ private ?string $table = null,
+ private ?string $schema = null,
+ private ?string $alias = null,
+ private array $columns = [],
+ private array $valuesList = [],
+ private ?SelectFinalStep $selectQuery = null,
+ private bool $defaultValues = false,
+ private ?OnConflictClause $onConflict = null,
+ private array $returning = [],
+ private bool $returningAll = false,
+ ) {
+ }
+
+ public static function create() : InsertIntoStep
+ {
+ return new self();
+ }
+
+ public static function fromAst(Node $node) : static
+ {
+ $insertStmt = $node->getInsertStmt();
+
+ if ($insertStmt === null) {
+ throw InvalidAstException::unexpectedNodeType('InsertStmt', 'unknown');
+ }
+
+ $relation = $insertStmt->getRelation();
+
+ if ($relation === null) {
+ throw InvalidAstException::missingRequiredField('relation', 'InsertStmt');
+ }
+
+ $table = $relation->getRelname();
+
+ if ($table === '') {
+ throw InvalidAstException::missingRequiredField('relname', 'RangeVar');
+ }
+
+ $schema = $relation->getSchemaname();
+
+ if ($schema === '') {
+ $schema = null;
+ }
+
+ $alias = $relation->getAlias();
+
+ if ($alias !== null) {
+ $aliasName = $alias->getAliasname();
+
+ if ($aliasName === '') {
+ $aliasName = null;
+ }
+ } else {
+ $aliasName = null;
+ }
+
+ $columns = [];
+ $colsNodes = $insertStmt->getCols();
+
+ if ($colsNodes !== null) {
+ foreach ($colsNodes as $colNode) {
+ $resTarget = $colNode->getResTarget();
+
+ if ($resTarget !== null) {
+ $name = $resTarget->getName();
+
+ if ($name !== '') {
+ $columns[] = $name;
+ }
+ }
+ }
+ }
+
+ $valuesList = [];
+ $selectQuery = null;
+ $defaultValues = false;
+ $selectStmtNode = $insertStmt->getSelectStmt();
+
+ if ($selectStmtNode !== null) {
+ $selectStmt = $selectStmtNode->getSelectStmt();
+
+ if ($selectStmt !== null) {
+ $valuesListsNodes = $selectStmt->getValuesLists();
+
+ if ($valuesListsNodes !== null && \count($valuesListsNodes) > 0) {
+ foreach ($valuesListsNodes as $listNode) {
+ $list = $listNode->getList();
+
+ if ($list !== null) {
+ $rowValues = [];
+ $elements = $list->getItems();
+
+ if ($elements !== null) {
+ foreach ($elements as $element) {
+ $rowValues[] = ExpressionFactory::fromAst($element);
+ }
+ }
+
+ $valuesList[] = $rowValues;
+ }
+ }
+ } else {
+ $targetList = $selectStmt->getTargetList();
+
+ if ($targetList === null || \count($targetList) === 0) {
+ $defaultValues = true;
+ } else {
+ $selectQuery = new class($selectStmt) implements SelectFinalStep {
+ use AstToSql;
+
+ public function __construct(private readonly SelectStmt $stmt)
+ {
+ }
+
+ public static function fromAst(Node $node) : static
+ {
+ $selectStmt = $node->getSelectStmt();
+
+ if ($selectStmt === null) {
+ throw InvalidAstException::unexpectedNodeType('SelectStmt', 'unknown');
+ }
+
+ return new self($selectStmt);
+ }
+
+ public function toAst() : SelectStmt
+ {
+ return $this->stmt;
+ }
+ };
+ }
+ }
+ }
+ }
+
+ $onConflict = null;
+ $onConflictNode = $insertStmt->getOnConflictClause();
+
+ if ($onConflictNode !== null) {
+ $conflictNode = new Node();
+ $conflictNode->setOnConflictClause($onConflictNode);
+ $onConflict = OnConflictClause::fromAst($conflictNode);
+ }
+
+ $returning = [];
+ $returningAll = false;
+ $returningListNodes = $insertStmt->getReturningList();
+
+ if ($returningListNodes !== null) {
+ foreach ($returningListNodes as $retNode) {
+ $resTarget = $retNode->getResTarget();
+
+ if ($resTarget !== null) {
+ $valNode = $resTarget->getVal();
+
+ if ($valNode !== null) {
+ $expr = ExpressionFactory::fromAst($valNode);
+
+ if ($expr instanceof Star && !$expr->isQualified()) {
+ $returningAll = true;
+ $returning = [];
+
+ break;
+ }
+
+ $returning[] = $expr;
+ }
+ }
+ }
+ }
+
+ $with = null;
+ $withClauseNode = $insertStmt->getWithClause();
+
+ if ($withClauseNode !== null) {
+ $withNode = new Node();
+ $withNode->setWithClause($withClauseNode);
+ $with = WithClause::fromAst($withNode);
+ }
+
+ return new self(
+ $with,
+ $table,
+ $schema,
+ $aliasName,
+ $columns,
+ $valuesList,
+ $selectQuery,
+ $defaultValues,
+ $onConflict,
+ $returning,
+ $returningAll,
+ );
+ }
+
+ public static function with(WithClause $with) : InsertIntoStep
+ {
+ return new self(with: $with);
+ }
+
+ public function columns(string ...$columns) : InsertValuesStep
+ {
+ return new self(
+ $this->with,
+ $this->table,
+ $this->schema,
+ $this->alias,
+ \array_values([...$columns]),
+ $this->valuesList,
+ $this->selectQuery,
+ $this->defaultValues,
+ $this->onConflict,
+ $this->returning,
+ $this->returningAll,
+ );
+ }
+
+ public function defaultValues() : InsertOnConflictStep
+ {
+ return new self(
+ $this->with,
+ $this->table,
+ $this->schema,
+ $this->alias,
+ $this->columns,
+ [],
+ null,
+ true,
+ $this->onConflict,
+ $this->returning,
+ $this->returningAll,
+ );
+ }
+
+ public function into(string $table, ?string $alias = null) : InsertColumnsStep
+ {
+ $identifier = QualifiedIdentifier::parse($table);
+
+ return new self(
+ $this->with,
+ $identifier->name(),
+ $identifier->schema(),
+ $alias,
+ $this->columns,
+ $this->valuesList,
+ $this->selectQuery,
+ $this->defaultValues,
+ $this->onConflict,
+ $this->returning,
+ $this->returningAll,
+ );
+ }
+
+ public function onConflict(OnConflictClause $clause) : InsertReturningStep
+ {
+ return new self(
+ $this->with,
+ $this->table,
+ $this->schema,
+ $this->alias,
+ $this->columns,
+ $this->valuesList,
+ $this->selectQuery,
+ $this->defaultValues,
+ $clause,
+ $this->returning,
+ $this->returningAll,
+ );
+ }
+
+ public function onConflictDoNothing(?ConflictTarget $target = null) : InsertReturningStep
+ {
+ return $this->onConflict(OnConflictClause::doNothing($target));
+ }
+
+ public function onConflictDoUpdate(ConflictTarget $target, array $updates) : InsertDoUpdateStep
+ {
+ return new self(
+ $this->with,
+ $this->table,
+ $this->schema,
+ $this->alias,
+ $this->columns,
+ $this->valuesList,
+ $this->selectQuery,
+ $this->defaultValues,
+ OnConflictClause::doUpdate($target, $updates),
+ $this->returning,
+ $this->returningAll,
+ );
+ }
+
+ public function returning(Expression ...$expressions) : InsertFinalStep
+ {
+ return new self(
+ $this->with,
+ $this->table,
+ $this->schema,
+ $this->alias,
+ $this->columns,
+ $this->valuesList,
+ $this->selectQuery,
+ $this->defaultValues,
+ $this->onConflict,
+ \array_values([...$expressions]),
+ false,
+ );
+ }
+
+ public function returningAll() : InsertFinalStep
+ {
+ return new self(
+ $this->with,
+ $this->table,
+ $this->schema,
+ $this->alias,
+ $this->columns,
+ $this->valuesList,
+ $this->selectQuery,
+ $this->defaultValues,
+ $this->onConflict,
+ [],
+ true,
+ );
+ }
+
+ public function select(SelectFinalStep $select) : InsertOnConflictStep
+ {
+ return new self(
+ $this->with,
+ $this->table,
+ $this->schema,
+ $this->alias,
+ $this->columns,
+ [],
+ $select,
+ false,
+ $this->onConflict,
+ $this->returning,
+ $this->returningAll,
+ );
+ }
+
+ public function toAst() : InsertStmt
+ {
+ $insertStmt = new InsertStmt();
+
+ $rangeVar = new RangeVar([
+ 'relname' => $this->table ?? '',
+ 'inh' => true,
+ ]);
+
+ if ($this->schema !== null) {
+ $rangeVar->setSchemaname($this->schema);
+ }
+
+ if ($this->alias !== null) {
+ $alias = new Alias();
+ $alias->setAliasname($this->alias);
+ $rangeVar->setAlias($alias);
+ }
+
+ $insertStmt->setRelation($rangeVar);
+
+ if ($this->columns !== []) {
+ $colsNodes = [];
+
+ foreach ($this->columns as $column) {
+ $resTarget = new ResTarget();
+ $resTarget->setName($column);
+
+ $colNode = new Node();
+ $colNode->setResTarget($resTarget);
+
+ $colsNodes[] = $colNode;
+ }
+
+ $insertStmt->setCols($colsNodes);
+ }
+
+ if ($this->selectQuery !== null) {
+ $selectNode = new Node();
+ $selectNode->setSelectStmt($this->selectQuery->toAst());
+ $insertStmt->setSelectStmt($selectNode);
+ } elseif ($this->defaultValues) {
+ // DEFAULT VALUES: do not set selectStmt at all
+ } elseif ($this->valuesList !== []) {
+ $selectStmt = new SelectStmt();
+ $valuesListsNodes = [];
+
+ foreach ($this->valuesList as $values) {
+ $items = [];
+
+ foreach ($values as $expr) {
+ $items[] = $expr->toAst();
+ }
+
+ $list = new PBList();
+ $list->setItems($items);
+
+ $listNode = new Node();
+ $listNode->setList($list);
+
+ $valuesListsNodes[] = $listNode;
+ }
+
+ $selectStmt->setValuesLists($valuesListsNodes);
+
+ $selectNode = new Node();
+ $selectNode->setSelectStmt($selectStmt);
+ $insertStmt->setSelectStmt($selectNode);
+ }
+
+ if ($this->onConflict !== null) {
+ $onConflictNode = $this->onConflict->toAst();
+ $onConflictClause = $onConflictNode->getOnConflictClause();
+
+ if ($onConflictClause !== null) {
+ $insertStmt->setOnConflictClause($onConflictClause);
+ }
+ }
+
+ if ($this->returningAll) {
+ $resTarget = new ResTarget();
+ $resTarget->setVal(Star::all()->toAst());
+
+ $retNode = new Node();
+ $retNode->setResTarget($resTarget);
+
+ $insertStmt->setReturningList([$retNode]);
+ } elseif ($this->returning !== []) {
+ $returningNodes = [];
+
+ foreach ($this->returning as $expr) {
+ $resTarget = new ResTarget();
+ $resTarget->setVal($expr->toAst());
+
+ $retNode = new Node();
+ $retNode->setResTarget($resTarget);
+
+ $returningNodes[] = $retNode;
+ }
+
+ $insertStmt->setReturningList($returningNodes);
+ }
+
+ if ($this->with !== null) {
+ $withNode = $this->with->toAst();
+ $withClause = $withNode->getWithClause();
+
+ if ($withClause !== null) {
+ $insertStmt->setWithClause($withClause);
+ }
+ }
+
+ return $insertStmt;
+ }
+
+ public function values(Expression ...$values) : InsertValuesStep
+ {
+ return new self(
+ $this->with,
+ $this->table,
+ $this->schema,
+ $this->alias,
+ $this->columns,
+ [...$this->valuesList, \array_values([...$values])],
+ $this->selectQuery,
+ $this->defaultValues,
+ $this->onConflict,
+ $this->returning,
+ $this->returningAll,
+ );
+ }
+
+ public function where(Condition $condition) : InsertReturningStep
+ {
+ if ($this->onConflict === null) {
+ return $this;
+ }
+
+ return new self(
+ $this->with,
+ $this->table,
+ $this->schema,
+ $this->alias,
+ $this->columns,
+ $this->valuesList,
+ $this->selectQuery,
+ $this->defaultValues,
+ $this->onConflict->where($condition),
+ $this->returning,
+ $this->returningAll,
+ );
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Insert/InsertColumnsStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Insert/InsertColumnsStep.php
new file mode 100644
index 000000000..3f9661fba
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Insert/InsertColumnsStep.php
@@ -0,0 +1,10 @@
+ $updates
+ */
+ public function onConflictDoUpdate(ConflictTarget $target, array $updates) : InsertDoUpdateStep;
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Insert/InsertReturningStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Insert/InsertReturningStep.php
new file mode 100644
index 000000000..7934703dd
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Insert/InsertReturningStep.php
@@ -0,0 +1,14 @@
+ $whenClauses
+ */
+ private function __construct(
+ private ?WithClause $with = null,
+ private ?string $table = null,
+ private ?string $schema = null,
+ private ?string $tableAlias = null,
+ private ?string $sourceTable = null,
+ private ?SelectFinalStep $sourceSelect = null,
+ private ?string $sourceAlias = null,
+ private ?Condition $joinCondition = null,
+ private array $whenClauses = [],
+ ) {
+ }
+
+ public static function create() : MergeIntoStep
+ {
+ return new self();
+ }
+
+ public static function with(WithClause $with) : MergeIntoStep
+ {
+ return new self(with: $with);
+ }
+
+ public function addWhenClause(MergeWhenClauseData $clause) : MergeWhenStep
+ {
+ return new self(
+ $this->with,
+ $this->table,
+ $this->schema,
+ $this->tableAlias,
+ $this->sourceTable,
+ $this->sourceSelect,
+ $this->sourceAlias,
+ $this->joinCondition,
+ [...$this->whenClauses, $clause],
+ );
+ }
+
+ public function into(string $table, ?string $alias = null) : MergeUsingStep
+ {
+ $identifier = QualifiedIdentifier::parse($table);
+
+ return new self(
+ $this->with,
+ $identifier->name(),
+ $identifier->schema(),
+ $alias,
+ $this->sourceTable,
+ $this->sourceSelect,
+ $this->sourceAlias,
+ $this->joinCondition,
+ $this->whenClauses,
+ );
+ }
+
+ public function on(Condition $condition) : MergeWhenStep
+ {
+ return new self(
+ $this->with,
+ $this->table,
+ $this->schema,
+ $this->tableAlias,
+ $this->sourceTable,
+ $this->sourceSelect,
+ $this->sourceAlias,
+ $condition,
+ $this->whenClauses,
+ );
+ }
+
+ public function toAst() : MergeStmt
+ {
+ if ($this->table === null || $this->table === '') {
+ throw InvalidExpressionException::invalidValue('table', 'null or empty');
+ }
+
+ if ($this->sourceTable === null && $this->sourceSelect === null) {
+ throw InvalidExpressionException::invalidValue('source', 'null');
+ }
+
+ if ($this->sourceAlias === null || $this->sourceAlias === '') {
+ throw InvalidExpressionException::invalidValue('sourceAlias', 'null or empty');
+ }
+
+ if ($this->joinCondition === null) {
+ throw InvalidExpressionException::invalidValue('joinCondition', 'null');
+ }
+
+ if ($this->whenClauses === []) {
+ throw InvalidExpressionException::emptyArray('whenClauses');
+ }
+
+ $mergeStmt = new MergeStmt();
+
+ $rangeVar = new RangeVar([
+ 'relname' => $this->table,
+ 'inh' => true,
+ ]);
+
+ if ($this->schema !== null) {
+ $rangeVar->setSchemaname($this->schema);
+ }
+
+ if ($this->tableAlias !== null) {
+ $alias = new Alias();
+ $alias->setAliasname($this->tableAlias);
+ $rangeVar->setAlias($alias);
+ }
+
+ $mergeStmt->setRelation($rangeVar);
+
+ $sourceNode = new Node();
+
+ if ($this->sourceSelect !== null) {
+ $rangeSubselect = new RangeSubselect();
+ $selectNode = new Node();
+ $selectNode->setSelectStmt($this->sourceSelect->toAst());
+ $rangeSubselect->setSubquery($selectNode);
+ $alias = new Alias();
+ $alias->setAliasname($this->sourceAlias);
+ $rangeSubselect->setAlias($alias);
+ $sourceNode->setRangeSubselect($rangeSubselect);
+ } else {
+ $sourceRangeVar = new RangeVar([
+ 'relname' => $this->sourceTable ?? '',
+ 'inh' => true,
+ ]);
+ $alias = new Alias();
+ $alias->setAliasname($this->sourceAlias);
+ $sourceRangeVar->setAlias($alias);
+ $sourceNode->setRangeVar($sourceRangeVar);
+ }
+
+ $mergeStmt->setSourceRelation($sourceNode);
+
+ $mergeStmt->setJoinCondition($this->joinCondition->toAst());
+
+ $whenClauseNodes = [];
+
+ foreach ($this->whenClauses as $clause) {
+ $whenClauseNodes[] = $this->buildWhenClauseNode($clause);
+ }
+
+ $mergeStmt->setMergeWhenClauses($whenClauseNodes);
+
+ if ($this->with !== null) {
+ $withNode = $this->with->toAst();
+ $withClause = $withNode->getWithClause();
+
+ if ($withClause !== null) {
+ $mergeStmt->setWithClause($withClause);
+ }
+ }
+
+ return $mergeStmt;
+ }
+
+ public function using(string|SelectFinalStep $source, string $alias) : MergeOnStep
+ {
+ if ($source instanceof SelectFinalStep) {
+ return new self(
+ $this->with,
+ $this->table,
+ $this->schema,
+ $this->tableAlias,
+ null,
+ $source,
+ $alias,
+ $this->joinCondition,
+ $this->whenClauses,
+ );
+ }
+
+ return new self(
+ $this->with,
+ $this->table,
+ $this->schema,
+ $this->tableAlias,
+ $source,
+ null,
+ $alias,
+ $this->joinCondition,
+ $this->whenClauses,
+ );
+ }
+
+ public function whenMatched() : MergeWhenMatched
+ {
+ return MergeWhenMatched::create($this, MergeMatchKind::MATCHED);
+ }
+
+ public function whenMatchedAnd(Condition $condition) : MergeWhenMatched
+ {
+ return MergeWhenMatched::create($this, MergeMatchKind::MATCHED, $condition);
+ }
+
+ public function whenNotMatched() : MergeWhenNotMatched
+ {
+ return MergeWhenNotMatched::create($this);
+ }
+
+ public function whenNotMatchedAnd(Condition $condition) : MergeWhenNotMatched
+ {
+ return MergeWhenNotMatched::create($this, $condition);
+ }
+
+ public function whenNotMatchedBySource() : MergeWhenMatched
+ {
+ return MergeWhenMatched::create($this, MergeMatchKind::NOT_MATCHED_BY_SOURCE);
+ }
+
+ public function whenNotMatchedBySourceAnd(Condition $condition) : MergeWhenMatched
+ {
+ return MergeWhenMatched::create($this, MergeMatchKind::NOT_MATCHED_BY_SOURCE, $condition);
+ }
+
+ private function buildWhenClauseNode(MergeWhenClauseData $clause) : Node
+ {
+ $whenClause = new MergeWhenClause();
+
+ $whenClause->setMatchKind($clause->matchKind->value);
+ $whenClause->setCommandType($clause->actionType->value);
+
+ if ($clause->condition !== null) {
+ $whenClause->setCondition($clause->condition->toAst());
+ }
+
+ if ($clause->actionType === MergeActionType::UPDATE && $clause->assignments !== []) {
+ $targetList = [];
+
+ foreach ($clause->assignments as $column => $value) {
+ $resTarget = new ResTarget([
+ 'name' => $column,
+ 'val' => $value->toAst(),
+ ]);
+
+ $node = new Node();
+ $node->setResTarget($resTarget);
+
+ $targetList[] = $node;
+ }
+
+ $whenClause->setTargetList($targetList);
+ }
+
+ if ($clause->actionType === MergeActionType::INSERT) {
+ if ($clause->insertColumns !== []) {
+ $targetList = [];
+
+ foreach ($clause->insertColumns as $column) {
+ $resTarget = new ResTarget();
+ $resTarget->setName($column);
+
+ $node = new Node();
+ $node->setResTarget($resTarget);
+
+ $targetList[] = $node;
+ }
+
+ $whenClause->setTargetList($targetList);
+ }
+
+ if ($clause->insertValues !== []) {
+ $valueNodes = [];
+
+ foreach ($clause->insertValues as $value) {
+ $valueNodes[] = $value->toAst();
+ }
+
+ $whenClause->setValues($valueNodes);
+ }
+ }
+
+ $node = new Node();
+ $node->setMergeWhenClause($whenClause);
+
+ return $node;
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Merge/MergeFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Merge/MergeFinalStep.php
new file mode 100644
index 000000000..9a7415995
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Merge/MergeFinalStep.php
@@ -0,0 +1,20 @@
+ $assignments UPDATE SET assignments
+ * @param list $insertColumns INSERT column names
+ * @param list $insertValues INSERT values
+ */
+ public function __construct(
+ public MergeMatchKind $matchKind,
+ public MergeActionType $actionType,
+ public ?Condition $condition = null,
+ public array $assignments = [],
+ public array $insertColumns = [],
+ public array $insertValues = [],
+ ) {
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Merge/MergeWhenMatched.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Merge/MergeWhenMatched.php
new file mode 100644
index 000000000..e480e2d75
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Merge/MergeWhenMatched.php
@@ -0,0 +1,67 @@
+builder->addWhenClause(
+ new MergeWhenClauseData(
+ $this->matchKind,
+ MergeActionType::DELETE,
+ $this->condition,
+ )
+ );
+ }
+
+ public function thenDoNothing() : MergeWhenStep
+ {
+ return $this->builder->addWhenClause(
+ new MergeWhenClauseData(
+ $this->matchKind,
+ MergeActionType::DO_NOTHING,
+ $this->condition,
+ )
+ );
+ }
+
+ /**
+ * @param array $assignments Column => value pairs for SET clause
+ */
+ public function thenUpdate(array $assignments) : MergeWhenStep
+ {
+ return $this->builder->addWhenClause(
+ new MergeWhenClauseData(
+ $this->matchKind,
+ MergeActionType::UPDATE,
+ $this->condition,
+ $assignments,
+ )
+ );
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Merge/MergeWhenNotMatched.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Merge/MergeWhenNotMatched.php
new file mode 100644
index 000000000..92f02ab2e
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Merge/MergeWhenNotMatched.php
@@ -0,0 +1,79 @@
+builder->addWhenClause(
+ new MergeWhenClauseData(
+ MergeMatchKind::NOT_MATCHED_BY_TARGET,
+ MergeActionType::DO_NOTHING,
+ $this->condition,
+ )
+ );
+ }
+
+ /**
+ * Insert specific columns with values.
+ *
+ * @param list $columns Column names
+ * @param list $values Values to insert
+ */
+ public function thenInsert(array $columns, array $values) : MergeWhenStep
+ {
+ return $this->builder->addWhenClause(
+ new MergeWhenClauseData(
+ MergeMatchKind::NOT_MATCHED_BY_TARGET,
+ MergeActionType::INSERT,
+ $this->condition,
+ [],
+ $columns,
+ $values,
+ )
+ );
+ }
+
+ /**
+ * Insert with column => value pairs.
+ *
+ * @param array $columnValuePairs
+ */
+ public function thenInsertValues(array $columnValuePairs) : MergeWhenStep
+ {
+ $columns = \array_keys($columnValuePairs);
+ $values = \array_values($columnValuePairs);
+
+ return $this->builder->addWhenClause(
+ new MergeWhenClauseData(
+ MergeMatchKind::NOT_MATCHED_BY_TARGET,
+ MergeActionType::INSERT,
+ $this->condition,
+ [],
+ $columns,
+ $values,
+ )
+ );
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Merge/MergeWhenStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Merge/MergeWhenStep.php
new file mode 100644
index 000000000..43d0a95c7
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Merge/MergeWhenStep.php
@@ -0,0 +1,22 @@
+ $parts
+ */
+ private function __construct(
+ private array $parts,
+ ) {
+ }
+
+ /**
+ * Create from explicit parts without parsing.
+ *
+ * @param non-empty-list $parts
+ */
+ public static function fromParts(array $parts) : self
+ {
+ return new self($parts);
+ }
+
+ /**
+ * Parse a qualified identifier string, respecting double-quoted parts.
+ */
+ public static function parse(string $identifier) : self
+ {
+ if ($identifier === '') {
+ return new self(['']);
+ }
+
+ $parts = self::splitRespectingQuotes($identifier);
+
+ return new self($parts);
+ }
+
+ /**
+ * For three-part identifiers (schema.table.column), get the column part (last).
+ * For two-part identifiers (table.column), get the column part (last).
+ * For single-part identifiers, get the only part.
+ */
+ public function column() : string
+ {
+ return $this->parts[\count($this->parts) - 1];
+ }
+
+ /**
+ * Get the number of parts.
+ */
+ public function count() : int
+ {
+ return \count($this->parts);
+ }
+
+ /**
+ * Check if this identifier has a schema part.
+ *
+ * @phpstan-assert-if-true !null $this->schema()
+ */
+ public function hasSchema() : bool
+ {
+ return \count($this->parts) >= 2;
+ }
+
+ /**
+ * Get the last part (typically the name/column).
+ */
+ public function name() : string
+ {
+ return $this->parts[\count($this->parts) - 1];
+ }
+
+ /**
+ * Get all parts of the identifier.
+ *
+ * @return non-empty-list
+ */
+ public function parts() : array
+ {
+ return $this->parts;
+ }
+
+ /**
+ * Get the schema part for a two-part identifier (schema.name).
+ * Returns null if there's only one part.
+ */
+ public function schema() : ?string
+ {
+ if (\count($this->parts) < 2) {
+ return null;
+ }
+
+ return $this->parts[0];
+ }
+
+ /**
+ * For three-part identifiers (schema.table.column), get the table part.
+ * For two-part identifiers (table.column), get the first part.
+ * Returns null for single-part identifiers.
+ */
+ public function table() : ?string
+ {
+ if (\count($this->parts) === 3) {
+ return $this->parts[1];
+ }
+
+ if (\count($this->parts) === 2) {
+ return $this->parts[0];
+ }
+
+ return null;
+ }
+
+ /**
+ * Split a qualified identifier by dots, but respect double-quoted parts.
+ *
+ * @return non-empty-list
+ */
+ private static function splitRespectingQuotes(string $identifier) : array
+ {
+ if (\str_starts_with($identifier, '"') && \str_ends_with($identifier, '"')) {
+ $inner = \substr($identifier, 1, -1);
+
+ if (\str_contains($inner, '"')) {
+ } else {
+ return [$inner];
+ }
+ }
+
+ $parts = [];
+ $current = '';
+ $inQuotes = false;
+ $length = \strlen($identifier);
+
+ for ($i = 0; $i < $length; $i++) {
+ $char = $identifier[$i];
+
+ if ($char === '"') {
+ $inQuotes = !$inQuotes;
+ } elseif ($char === '.' && !$inQuotes) {
+ $parts[] = $current;
+ $current = '';
+ } else {
+ $current .= $char;
+ }
+ }
+
+ $parts[] = $current;
+
+ return $parts;
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterSequence/AlterSequenceBuilder.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterSequence/AlterSequenceBuilder.php
new file mode 100644
index 000000000..d8269af87
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterSequence/AlterSequenceBuilder.php
@@ -0,0 +1,297 @@
+ $options
+ */
+ private function __construct(
+ private ?string $name = null,
+ private ?string $schema = null,
+ private bool $ifExists = false,
+ private array $options = [],
+ ) {
+ }
+
+ public static function create() : AlterSequenceNameStep
+ {
+ return new self();
+ }
+
+ public static function ifExists() : AlterSequenceNameStep
+ {
+ return new self(ifExists: true);
+ }
+
+ public function asType(string $dataType) : AlterSequenceOptionsStep
+ {
+ $typeMap = [
+ 'smallint' => 'int2',
+ 'integer' => 'int4',
+ 'bigint' => 'int8',
+ 'int2' => 'int2',
+ 'int4' => 'int4',
+ 'int8' => 'int8',
+ ];
+
+ $pgType = $typeMap[\strtolower($dataType)] ?? $dataType;
+
+ $typeName = new TypeName();
+ $names = [];
+
+ $catalogStr = new PBString();
+ $catalogStr->setSval('pg_catalog');
+ $catalogNode = new Node();
+ $catalogNode->setString($catalogStr);
+ $names[] = $catalogNode;
+
+ $typeStr = new PBString();
+ $typeStr->setSval($pgType);
+ $typeNode = new Node();
+ $typeNode->setString($typeStr);
+ $names[] = $typeNode;
+
+ $typeName->setNames($names);
+ $typeName->setTypemod(-1);
+
+ $argNode = new Node();
+ $argNode->setTypeName($typeName);
+
+ return $this->withOption('as', $argNode);
+ }
+
+ public function cache(int $cache) : AlterSequenceOptionsStep
+ {
+ return $this->withIntegerOption('cache', $cache);
+ }
+
+ public function cycle() : AlterSequenceOptionsStep
+ {
+ return $this->withBooleanOption('cycle', true);
+ }
+
+ public function incrementBy(int $increment) : AlterSequenceOptionsStep
+ {
+ return $this->withIntegerOption('increment', $increment);
+ }
+
+ public function maxValue(int $maxValue) : AlterSequenceOptionsStep
+ {
+ return $this->withIntegerOption('maxvalue', $maxValue);
+ }
+
+ public function minValue(int $minValue) : AlterSequenceOptionsStep
+ {
+ return $this->withIntegerOption('minvalue', $minValue);
+ }
+
+ public function noCycle() : AlterSequenceOptionsStep
+ {
+ return $this->withBooleanOption('cycle', false);
+ }
+
+ public function noMaxValue() : AlterSequenceOptionsStep
+ {
+ return $this->withOption('maxvalue', null);
+ }
+
+ public function noMinValue() : AlterSequenceOptionsStep
+ {
+ return $this->withOption('minvalue', null);
+ }
+
+ public function ownedBy(string $table, string $column) : AlterSequenceOptionsStep
+ {
+ $list = new PBList();
+ $items = [];
+
+ $identifier = QualifiedIdentifier::parse($table);
+
+ foreach ($identifier->parts() as $part) {
+ $str = new PBString();
+ $str->setSval($part);
+ $strNode = new Node();
+ $strNode->setString($str);
+ $items[] = $strNode;
+ }
+
+ $colStr = new PBString();
+ $colStr->setSval($column);
+ $colNode = new Node();
+ $colNode->setString($colStr);
+ $items[] = $colNode;
+
+ $list->setItems($items);
+
+ $argNode = new Node();
+ $argNode->setList($list);
+
+ return $this->withOption('owned_by', $argNode);
+ }
+
+ public function ownedByNone() : AlterSequenceOptionsStep
+ {
+ $list = new PBList();
+ $items = [];
+
+ $str = new PBString();
+ $str->setSval('none');
+ $strNode = new Node();
+ $strNode->setString($str);
+ $items[] = $strNode;
+
+ $list->setItems($items);
+
+ $argNode = new Node();
+ $argNode->setList($list);
+
+ return $this->withOption('owned_by', $argNode);
+ }
+
+ public function ownerTo(string $owner) : AlterSequenceOwnerFinalStep
+ {
+ return AlterSequenceOwnerBuilder::create($this->name ?? '', $this->schema, $owner, $this->ifExists);
+ }
+
+ public function renameTo(string $newName) : RenameSequenceFinalStep
+ {
+ return RenameSequenceBuilder::create($this->name ?? '', $this->schema, $newName, $this->ifExists);
+ }
+
+ public function restart() : AlterSequenceOptionsStep
+ {
+ return $this->withOption('restart', null);
+ }
+
+ public function restartWith(int $restart) : AlterSequenceOptionsStep
+ {
+ return $this->withIntegerOption('restart', $restart);
+ }
+
+ public function sequence(string $name, ?string $schema = null) : AlterSequenceOptionsStep
+ {
+ return new self(
+ $name,
+ $schema,
+ $this->ifExists,
+ $this->options,
+ );
+ }
+
+ public function setLogged() : AlterSequenceLoggingFinalStep
+ {
+ return AlterSequenceLoggingBuilder::createLogged($this->name ?? '', $this->schema, $this->ifExists);
+ }
+
+ public function setSchema(string $schema) : AlterSequenceSchemaFinalStep
+ {
+ return AlterSequenceSchemaBuilder::create($this->name ?? '', $this->schema, $schema, $this->ifExists);
+ }
+
+ public function setUnlogged() : AlterSequenceLoggingFinalStep
+ {
+ return AlterSequenceLoggingBuilder::createUnlogged($this->name ?? '', $this->schema, $this->ifExists);
+ }
+
+ public function startWith(int $start) : AlterSequenceOptionsStep
+ {
+ return $this->withIntegerOption('start', $start);
+ }
+
+ public function toAst() : AlterSeqStmt
+ {
+ $stmt = new AlterSeqStmt();
+
+ $rangeVar = new RangeVar();
+ $rangeVar->setRelname($this->name ?? '');
+ $rangeVar->setInh(true);
+ $rangeVar->setRelpersistence('p');
+
+ if ($this->schema !== null) {
+ $rangeVar->setSchemaname($this->schema);
+ }
+
+ $stmt->setSequence($rangeVar);
+
+ if ($this->ifExists) {
+ $stmt->setMissingOk(true);
+ }
+
+ if ($this->options !== []) {
+ $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;
+ }
+
+ $stmt->setOptions($optionNodes);
+ }
+
+ return $stmt;
+ }
+
+ public function withIfExists() : self
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ true,
+ $this->options,
+ );
+ }
+
+ private function withBooleanOption(string $name, bool $value) : self
+ {
+ $boolean = new Boolean();
+ $boolean->setBoolval($value);
+
+ $argNode = new Node();
+ /** @phpstan-ignore argument.type (protobuf PHPDoc says bool but actually expects Boolean) */
+ $argNode->setBoolean($boolean);
+
+ return $this->withOption($name, $argNode);
+ }
+
+ private function withIntegerOption(string $name, int $value) : self
+ {
+ $integer = new Integer();
+ $integer->setIval($value);
+
+ $argNode = new Node();
+ /** @phpstan-ignore argument.type (protobuf PHPDoc says int but actually expects Integer) */
+ $argNode->setInteger($integer);
+
+ return $this->withOption($name, $argNode);
+ }
+
+ private function withOption(string $name, ?Node $arg) : self
+ {
+ $newOptions = $this->options;
+ $newOptions[] = ['name' => $name, 'arg' => $arg];
+
+ return new self(
+ $this->name,
+ $this->schema,
+ $this->ifExists,
+ $newOptions,
+ );
+ }
+}
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
new file mode 100644
index 000000000..e1f9cc427
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterSequence/AlterSequenceFinalStep.php
@@ -0,0 +1,14 @@
+setObjtype(ObjectType::OBJECT_SEQUENCE);
+
+ $rangeVar = new RangeVar();
+ $rangeVar->setRelname($this->sequence);
+ $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/AlterSequence/AlterSequenceLoggingFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterSequence/AlterSequenceLoggingFinalStep.php
new file mode 100644
index 000000000..281786ef4
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterSequence/AlterSequenceLoggingFinalStep.php
@@ -0,0 +1,14 @@
+setObjtype(ObjectType::OBJECT_SEQUENCE);
+
+ $rangeVar = new RangeVar();
+ $rangeVar->setRelname($this->sequence);
+ $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(AlterTableType::AT_ChangeOwner);
+ $cmd->setBehavior(DropBehavior::DROP_RESTRICT);
+
+ $roleSpec = new RoleSpec();
+ $roleSpec->setRoletype(RoleSpecType::ROLESPEC_CSTRING);
+ $roleSpec->setRolename($this->owner);
+
+ $cmd->setNewowner($roleSpec);
+
+ $cmdNode = new Node();
+ $cmdNode->setAlterTableCmd($cmd);
+
+ $stmt->setCmds([$cmdNode]);
+
+ return $stmt;
+ }
+}
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
new file mode 100644
index 000000000..1c0bd46fb
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterSequence/AlterSequenceOwnerFinalStep.php
@@ -0,0 +1,14 @@
+setObjectType(ObjectType::OBJECT_SEQUENCE);
+
+ $rangeVar = new RangeVar();
+ $rangeVar->setRelname($this->sequence);
+ $rangeVar->setInh(true);
+ $rangeVar->setRelpersistence('p');
+
+ if ($this->schema !== null) {
+ $rangeVar->setSchemaname($this->schema);
+ }
+
+ $stmt->setRelation($rangeVar);
+ $stmt->setNewschema($this->newSchema);
+
+ if ($this->ifExists) {
+ $stmt->setMissingOk(true);
+ }
+
+ return $stmt;
+ }
+}
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
new file mode 100644
index 000000000..e7bef5153
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterSequence/AlterSequenceSchemaFinalStep.php
@@ -0,0 +1,14 @@
+setRenameType(ObjectType::OBJECT_SEQUENCE);
+
+ $rangeVar = new RangeVar();
+ $rangeVar->setRelname($this->sequence);
+ $rangeVar->setInh(true);
+ $rangeVar->setRelpersistence('p');
+
+ if ($this->schema !== null) {
+ $rangeVar->setSchemaname($this->schema);
+ }
+
+ $stmt->setRelation($rangeVar);
+ $stmt->setNewname($this->newName);
+ $stmt->setBehavior(DropBehavior::DROP_RESTRICT);
+
+ if ($this->ifExists) {
+ $stmt->setMissingOk(true);
+ }
+
+ return $stmt;
+ }
+}
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
new file mode 100644
index 000000000..16aea2d88
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterSequence/RenameSequenceFinalStep.php
@@ -0,0 +1,14 @@
+ $commands
+ */
+ private function __construct(
+ private string $table,
+ private ?string $schema,
+ private array $commands = [],
+ private bool $ifExists = false,
+ ) {
+ }
+
+ public static function create(string $table, ?string $schema = null) : AlterTableFinalStep
+ {
+ return new self($table, $schema);
+ }
+
+ public function addColumn(ColumnDefinition $column) : AlterTableFinalStep
+ {
+ $cmd = new AlterTableCmd();
+ $cmd->setSubtype(AlterTableType::AT_AddColumn);
+
+ $node = new Node();
+ $node->setColumnDef($column->toAst());
+ $cmd->setDef($node);
+
+ return new self(
+ $this->table,
+ $this->schema,
+ [...$this->commands, $cmd],
+ $this->ifExists,
+ );
+ }
+
+ public function addConstraint(TableConstraint $constraint) : AlterTableFinalStep
+ {
+ $cmd = new AlterTableCmd();
+ $cmd->setSubtype(AlterTableType::AT_AddConstraint);
+
+ $node = new Node();
+ $node->setConstraint($constraint->toAst());
+ $cmd->setDef($node);
+
+ return new self(
+ $this->table,
+ $this->schema,
+ [...$this->commands, $cmd],
+ $this->ifExists,
+ );
+ }
+
+ public function alterColumnDropDefault(string $column) : AlterTableFinalStep
+ {
+ $cmd = new AlterTableCmd();
+ $cmd->setSubtype(AlterTableType::AT_ColumnDefault);
+ $cmd->setName($column);
+
+ return new self(
+ $this->table,
+ $this->schema,
+ [...$this->commands, $cmd],
+ $this->ifExists,
+ );
+ }
+
+ public function alterColumnDropNotNull(string $column) : AlterTableFinalStep
+ {
+ $cmd = new AlterTableCmd();
+ $cmd->setSubtype(AlterTableType::AT_DropNotNull);
+ $cmd->setName($column);
+
+ return new self(
+ $this->table,
+ $this->schema,
+ [...$this->commands, $cmd],
+ $this->ifExists,
+ );
+ }
+
+ public function alterColumnSetDefault(string $column, string $defaultExpression) : AlterTableFinalStep
+ {
+ $cmd = new AlterTableCmd();
+ $cmd->setSubtype(AlterTableType::AT_ColumnDefault);
+ $cmd->setName($column);
+
+ $cmd->setDef($this->parseExpression($defaultExpression));
+
+ return new self(
+ $this->table,
+ $this->schema,
+ [...$this->commands, $cmd],
+ $this->ifExists,
+ );
+ }
+
+ public function alterColumnSetNotNull(string $column) : AlterTableFinalStep
+ {
+ $cmd = new AlterTableCmd();
+ $cmd->setSubtype(AlterTableType::AT_SetNotNull);
+ $cmd->setName($column);
+
+ return new self(
+ $this->table,
+ $this->schema,
+ [...$this->commands, $cmd],
+ $this->ifExists,
+ );
+ }
+
+ public function alterColumnType(string $column, DataType $type) : AlterTableFinalStep
+ {
+ $cmd = new AlterTableCmd();
+ $cmd->setSubtype(AlterTableType::AT_AlterColumnType);
+ $cmd->setName($column);
+
+ $columnDef = new ColumnDef();
+ $columnDef->setTypeName($type->toAst());
+
+ $node = new Node();
+ $node->setColumnDef($columnDef);
+ $cmd->setDef($node);
+
+ return new self(
+ $this->table,
+ $this->schema,
+ [...$this->commands, $cmd],
+ $this->ifExists,
+ );
+ }
+
+ public function disableTrigger(string $trigger) : AlterTableFinalStep
+ {
+ $cmd = new AlterTableCmd();
+ $cmd->setSubtype(AlterTableType::AT_DisableTrig);
+ $cmd->setName($trigger);
+
+ return new self(
+ $this->table,
+ $this->schema,
+ [...$this->commands, $cmd],
+ $this->ifExists,
+ );
+ }
+
+ public function disableTriggerAll() : AlterTableFinalStep
+ {
+ $cmd = new AlterTableCmd();
+ $cmd->setSubtype(AlterTableType::AT_DisableTrigAll);
+
+ return new self(
+ $this->table,
+ $this->schema,
+ [...$this->commands, $cmd],
+ $this->ifExists,
+ );
+ }
+
+ public function disableTriggerUser() : AlterTableFinalStep
+ {
+ $cmd = new AlterTableCmd();
+ $cmd->setSubtype(AlterTableType::AT_DisableTrigUser);
+
+ return new self(
+ $this->table,
+ $this->schema,
+ [...$this->commands, $cmd],
+ $this->ifExists,
+ );
+ }
+
+ public function dropColumn(string $column, bool $cascade = false) : AlterTableFinalStep
+ {
+ $cmd = new AlterTableCmd();
+ $cmd->setSubtype(AlterTableType::AT_DropColumn);
+ $cmd->setName($column);
+
+ if ($cascade) {
+ $cmd->setBehavior(DropBehavior::DROP_CASCADE);
+ }
+
+ return new self(
+ $this->table,
+ $this->schema,
+ [...$this->commands, $cmd],
+ $this->ifExists,
+ );
+ }
+
+ public function dropColumnIfExists(string $column, bool $cascade = false) : AlterTableFinalStep
+ {
+ $cmd = new AlterTableCmd();
+ $cmd->setSubtype(AlterTableType::AT_DropColumn);
+ $cmd->setName($column);
+ $cmd->setMissingOk(true);
+
+ if ($cascade) {
+ $cmd->setBehavior(DropBehavior::DROP_CASCADE);
+ }
+
+ return new self(
+ $this->table,
+ $this->schema,
+ [...$this->commands, $cmd],
+ $this->ifExists,
+ );
+ }
+
+ public function dropConstraint(string $constraintName, bool $cascade = false) : AlterTableFinalStep
+ {
+ $cmd = new AlterTableCmd();
+ $cmd->setSubtype(AlterTableType::AT_DropConstraint);
+ $cmd->setName($constraintName);
+
+ if ($cascade) {
+ $cmd->setBehavior(DropBehavior::DROP_CASCADE);
+ }
+
+ return new self(
+ $this->table,
+ $this->schema,
+ [...$this->commands, $cmd],
+ $this->ifExists,
+ );
+ }
+
+ public function dropConstraintIfExists(string $constraintName, bool $cascade = false) : AlterTableFinalStep
+ {
+ $cmd = new AlterTableCmd();
+ $cmd->setSubtype(AlterTableType::AT_DropConstraint);
+ $cmd->setName($constraintName);
+ $cmd->setMissingOk(true);
+
+ if ($cascade) {
+ $cmd->setBehavior(DropBehavior::DROP_CASCADE);
+ }
+
+ return new self(
+ $this->table,
+ $this->schema,
+ [...$this->commands, $cmd],
+ $this->ifExists,
+ );
+ }
+
+ public function enableTrigger(string $trigger) : AlterTableFinalStep
+ {
+ $cmd = new AlterTableCmd();
+ $cmd->setSubtype(AlterTableType::AT_EnableTrig);
+ $cmd->setName($trigger);
+
+ return new self(
+ $this->table,
+ $this->schema,
+ [...$this->commands, $cmd],
+ $this->ifExists,
+ );
+ }
+
+ public function enableTriggerAll() : AlterTableFinalStep
+ {
+ $cmd = new AlterTableCmd();
+ $cmd->setSubtype(AlterTableType::AT_EnableTrigAll);
+
+ return new self(
+ $this->table,
+ $this->schema,
+ [...$this->commands, $cmd],
+ $this->ifExists,
+ );
+ }
+
+ public function enableTriggerAlways(string $trigger) : AlterTableFinalStep
+ {
+ $cmd = new AlterTableCmd();
+ $cmd->setSubtype(AlterTableType::AT_EnableAlwaysTrig);
+ $cmd->setName($trigger);
+
+ return new self(
+ $this->table,
+ $this->schema,
+ [...$this->commands, $cmd],
+ $this->ifExists,
+ );
+ }
+
+ public function enableTriggerReplica(string $trigger) : AlterTableFinalStep
+ {
+ $cmd = new AlterTableCmd();
+ $cmd->setSubtype(AlterTableType::AT_EnableReplicaTrig);
+ $cmd->setName($trigger);
+
+ return new self(
+ $this->table,
+ $this->schema,
+ [...$this->commands, $cmd],
+ $this->ifExists,
+ );
+ }
+
+ public function enableTriggerUser() : AlterTableFinalStep
+ {
+ $cmd = new AlterTableCmd();
+ $cmd->setSubtype(AlterTableType::AT_EnableTrigUser);
+
+ return new self(
+ $this->table,
+ $this->schema,
+ [...$this->commands, $cmd],
+ $this->ifExists,
+ );
+ }
+
+ public function ifExists() : AlterTableFinalStep
+ {
+ return new self(
+ $this->table,
+ $this->schema,
+ $this->commands,
+ true,
+ );
+ }
+
+ public function renameColumn(string $oldName, string $newName) : RenameTableBuilder
+ {
+ return RenameTableBuilder::renameColumn($this->table, $this->schema, $oldName, $newName, $this->ifExists);
+ }
+
+ public function renameConstraint(string $oldName, string $newName) : RenameTableBuilder
+ {
+ return RenameTableBuilder::renameConstraint($this->table, $this->schema, $oldName, $newName, $this->ifExists);
+ }
+
+ public function renameTo(string $newName) : RenameTableBuilder
+ {
+ return RenameTableBuilder::renameTo($this->table, $this->schema, $newName, $this->ifExists);
+ }
+
+ public function setSchema(string $schema) : AlterTableSchemaBuilder
+ {
+ return AlterTableSchemaBuilder::create($this->table, $this->schema, $schema, $this->ifExists);
+ }
+
+ public function toAst() : AlterTableStmt
+ {
+ $stmt = new AlterTableStmt();
+
+ $rangeVar = new RangeVar();
+ $rangeVar->setRelname($this->table);
+ $rangeVar->setRelpersistence('p');
+ $rangeVar->setInh(true);
+
+ if ($this->schema !== null) {
+ $rangeVar->setSchemaname($this->schema);
+ }
+
+ $stmt->setRelation($rangeVar);
+ $stmt->setObjtype(ObjectType::OBJECT_TABLE);
+
+ if ($this->ifExists) {
+ $stmt->setMissingOk(true);
+ }
+
+ if ($this->commands !== []) {
+ $cmdNodes = [];
+
+ foreach ($this->commands as $cmd) {
+ $node = new Node();
+ $node->setAlterTableCmd($cmd);
+ $cmdNodes[] = $node;
+ }
+
+ $stmt->setCmds($cmdNodes);
+ }
+
+ 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
new file mode 100644
index 000000000..c7abb61a2
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterTable/AlterTableFinalStep.php
@@ -0,0 +1,64 @@
+setObjectType(ObjectType::OBJECT_TABLE);
+
+ $rangeVar = new RangeVar();
+ $rangeVar->setRelname($this->table);
+ $rangeVar->setRelpersistence('p');
+ $rangeVar->setInh(true);
+
+ if ($this->schema !== null) {
+ $rangeVar->setSchemaname($this->schema);
+ }
+
+ $stmt->setRelation($rangeVar);
+ $stmt->setNewschema($this->newSchema);
+
+ if ($this->ifExists) {
+ $stmt->setMissingOk(true);
+ }
+
+ return $stmt;
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterTable/RenameTableBuilder.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterTable/RenameTableBuilder.php
new file mode 100644
index 000000000..e2750931c
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/AlterTable/RenameTableBuilder.php
@@ -0,0 +1,89 @@
+setRenameType($this->renameType);
+
+ $rangeVar = new RangeVar();
+ $rangeVar->setRelname($this->table);
+ $rangeVar->setRelpersistence('p');
+ $rangeVar->setInh(true);
+
+ if ($this->schema !== null) {
+ $rangeVar->setSchemaname($this->schema);
+ }
+
+ $stmt->setRelation($rangeVar);
+
+ if ($this->renameType === ObjectType::OBJECT_COLUMN || $this->renameType === ObjectType::OBJECT_TABCONSTRAINT) {
+ $stmt->setRelationType(ObjectType::OBJECT_TABLE);
+
+ if ($this->subname !== null) {
+ $stmt->setSubname($this->subname);
+ }
+ }
+
+ $stmt->setNewname($this->newname);
+
+ if ($this->ifExists) {
+ $stmt->setMissingOk(true);
+ }
+
+ return $stmt;
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/ColumnDefinition.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/ColumnDefinition.php
new file mode 100644
index 000000000..dd1153142
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/ColumnDefinition.php
@@ -0,0 +1,345 @@
+ $constraints
+ */
+ private function __construct(
+ private string $name,
+ private DataType $type,
+ private bool $notNull = false,
+ private ?Node $defaultValue = null,
+ private ?string $identity = null,
+ private ?Node $generatedExpression = null,
+ private array $constraints = [],
+ ) {
+ }
+
+ public static function create(string $name, DataType $type) : self
+ {
+ return new self($name, $type);
+ }
+
+ public function check(string $expression) : self
+ {
+ $constraint = new Constraint();
+ $constraint->setContype(ConstrType::CONSTR_CHECK);
+ $constraint->setRawExpr($this->parseExpression($expression));
+
+ return new self(
+ $this->name,
+ $this->type,
+ $this->notNull,
+ $this->defaultValue,
+ $this->identity,
+ $this->generatedExpression,
+ [...$this->constraints, $constraint],
+ );
+ }
+
+ public function default(bool|float|int|string|null $value) : self
+ {
+ return new self(
+ $this->name,
+ $this->type,
+ $this->notNull,
+ $this->createLiteralNode($value),
+ $this->identity,
+ $this->generatedExpression,
+ $this->constraints,
+ );
+ }
+
+ public function defaultRaw(string $expression) : self
+ {
+ return new self(
+ $this->name,
+ $this->type,
+ $this->notNull,
+ $this->parseExpression($expression),
+ $this->identity,
+ $this->generatedExpression,
+ $this->constraints,
+ );
+ }
+
+ public function generatedAs(string $expression) : self
+ {
+ return new self(
+ $this->name,
+ $this->type,
+ $this->notNull,
+ $this->defaultValue,
+ $this->identity,
+ $this->parseExpression($expression),
+ $this->constraints,
+ );
+ }
+
+ public function identity(string $type = 'ALWAYS') : self
+ {
+ $identityChar = \strtoupper($type) === 'ALWAYS' ? 'a' : 'd';
+
+ return new self(
+ $this->name,
+ $this->type,
+ $this->notNull,
+ $this->defaultValue,
+ $identityChar,
+ $this->generatedExpression,
+ $this->constraints,
+ );
+ }
+
+ public function notNull() : self
+ {
+ return new self(
+ $this->name,
+ $this->type,
+ true,
+ $this->defaultValue,
+ $this->identity,
+ $this->generatedExpression,
+ $this->constraints,
+ );
+ }
+
+ public function nullable() : self
+ {
+ return new self(
+ $this->name,
+ $this->type,
+ false,
+ $this->defaultValue,
+ $this->identity,
+ $this->generatedExpression,
+ $this->constraints,
+ );
+ }
+
+ public function primaryKey() : self
+ {
+ $constraint = new Constraint();
+ $constraint->setContype(ConstrType::CONSTR_PRIMARY);
+
+ return new self(
+ $this->name,
+ $this->type,
+ $this->notNull,
+ $this->defaultValue,
+ $this->identity,
+ $this->generatedExpression,
+ [...$this->constraints, $constraint],
+ );
+ }
+
+ public function references(string $table, ?string $column = null, ?string $schema = null) : self
+ {
+ $constraint = new Constraint();
+ $constraint->setContype(ConstrType::CONSTR_FOREIGN);
+
+ $rangeVar = new RangeVar();
+ $rangeVar->setRelname($table);
+
+ if ($schema !== null) {
+ $rangeVar->setSchemaname($schema);
+ }
+
+ $constraint->setPktable($rangeVar);
+
+ if ($column !== null) {
+ $constraint->setPkAttrs([$this->createStringNode($column)]);
+ }
+
+ return new self(
+ $this->name,
+ $this->type,
+ $this->notNull,
+ $this->defaultValue,
+ $this->identity,
+ $this->generatedExpression,
+ [...$this->constraints, $constraint],
+ );
+ }
+
+ public function toAst() : ColumnDef
+ {
+ $columnDef = new ColumnDef();
+ $columnDef->setColname($this->name);
+ $columnDef->setTypeName($this->type->toAst());
+ $columnDef->setIsLocal(true);
+
+ if ($this->identity !== null) {
+ $columnDef->setIdentity($this->identity);
+ }
+
+ $allConstraints = [];
+
+ if ($this->notNull) {
+ $notNullConstraint = new Constraint();
+ $notNullConstraint->setContype(ConstrType::CONSTR_NOTNULL);
+ $allConstraints[] = $notNullConstraint;
+ }
+
+ if ($this->defaultValue !== null) {
+ $defaultConstraint = new Constraint();
+ $defaultConstraint->setContype(ConstrType::CONSTR_DEFAULT);
+ $defaultConstraint->setRawExpr($this->defaultValue);
+ $allConstraints[] = $defaultConstraint;
+ }
+
+ foreach ($this->constraints as $constraint) {
+ $allConstraints[] = $constraint;
+ }
+
+ if ($this->generatedExpression !== null) {
+ $columnDef->setGenerated('s');
+
+ $generatedConstraint = new Constraint();
+ $generatedConstraint->setContype(ConstrType::CONSTR_GENERATED);
+ $generatedConstraint->setGeneratedWhen('a');
+ $generatedConstraint->setRawExpr($this->generatedExpression);
+
+ $allConstraints[] = $generatedConstraint;
+ }
+
+ if ($allConstraints !== []) {
+ $constraintNodes = [];
+
+ foreach ($allConstraints as $constraint) {
+ $node = new Node();
+ $node->setConstraint($constraint);
+ $constraintNodes[] = $node;
+ }
+
+ $columnDef->setConstraints($constraintNodes);
+ }
+
+ return $columnDef;
+ }
+
+ public function unique() : self
+ {
+ $constraint = new Constraint();
+ $constraint->setContype(ConstrType::CONSTR_UNIQUE);
+
+ return new self(
+ $this->name,
+ $this->type,
+ $this->notNull,
+ $this->defaultValue,
+ $this->identity,
+ $this->generatedExpression,
+ [...$this->constraints, $constraint],
+ );
+ }
+
+ 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');
+ }
+
+ $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;
+ }
+
+ private function createStringNode(string $value) : Node
+ {
+ $str = new PBString();
+ $str->setSval($value);
+
+ $node = new Node();
+ $node->setString($str);
+
+ 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/Constraint/CheckConstraint.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Constraint/CheckConstraint.php
new file mode 100644
index 000000000..3eb09717d
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Constraint/CheckConstraint.php
@@ -0,0 +1,92 @@
+expression, $name, $this->noInherit);
+ }
+
+ public function noInherit() : self
+ {
+ return new self($this->expression, $this->name, true);
+ }
+
+ public function toAst() : Constraint
+ {
+ $constraint = new Constraint();
+ $constraint->setContype(ConstrType::CONSTR_CHECK);
+
+ if ($this->name !== null) {
+ $constraint->setConname($this->name);
+ }
+
+ if ($this->noInherit) {
+ $constraint->setIsNoInherit(true);
+ }
+
+ $constraint->setRawExpr($this->parseExpression($this->expression));
+
+ 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
new file mode 100644
index 000000000..f5286f81d
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Constraint/ExcludeConstraint.php
@@ -0,0 +1,147 @@
+ $elements
+ */
+ private function __construct(
+ private string $accessMethod,
+ private array $elements = [],
+ private ?string $name = null,
+ private ?string $whereClause = null,
+ ) {
+ }
+
+ public static function create(string $accessMethod = 'gist') : self
+ {
+ return new self($accessMethod);
+ }
+
+ public function element(string $element, string $operator) : self
+ {
+ return new self(
+ $this->accessMethod,
+ [...$this->elements, ['element' => $element, 'operator' => $operator]],
+ $this->name,
+ $this->whereClause,
+ );
+ }
+
+ public function name(string $name) : self
+ {
+ return new self(
+ $this->accessMethod,
+ $this->elements,
+ $name,
+ $this->whereClause,
+ );
+ }
+
+ public function toAst() : Constraint
+ {
+ $constraint = new Constraint();
+ $constraint->setContype(ConstrType::CONSTR_EXCLUSION);
+ $constraint->setAccessMethod($this->accessMethod);
+
+ if ($this->name !== null) {
+ $constraint->setConname($this->name);
+ }
+
+ if ($this->elements !== []) {
+ $exclusions = [];
+
+ foreach ($this->elements as $element) {
+ $exclusions[] = $this->parseExpression($element['element']);
+ $exclusions[] = $this->createOperatorNode($element['operator']);
+ }
+
+ $constraint->setExclusions($exclusions);
+ }
+
+ if ($this->whereClause !== null) {
+ $constraint->setWhereClause($this->parseExpression($this->whereClause));
+ }
+
+ return $constraint;
+ }
+
+ public function where(string $whereClause) : self
+ {
+ return new self(
+ $this->accessMethod,
+ $this->elements,
+ $this->name,
+ $whereClause,
+ );
+ }
+
+ private function createOperatorNode(string $operator) : Node
+ {
+ $operatorList = new PBList();
+ $operatorItems = [];
+
+ $str = new PBString();
+ $str->setSval($operator);
+
+ $node = new Node();
+ $node->setString($str);
+ $operatorItems[] = $node;
+
+ $operatorList->setItems($operatorItems);
+
+ $resultNode = new Node();
+ $resultNode->setList($operatorList);
+
+ 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
new file mode 100644
index 000000000..7b11e8c57
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Constraint/ForeignKeyConstraint.php
@@ -0,0 +1,179 @@
+ $columns
+ * @param list $referenceColumns
+ */
+ private function __construct(
+ private array $columns,
+ private string $referenceTable,
+ private array $referenceColumns,
+ private ?string $referenceSchema = null,
+ private ?string $name = null,
+ private ?ReferentialAction $onUpdate = null,
+ private ?ReferentialAction $onDelete = null,
+ private bool $deferrable = false,
+ private bool $initiallyDeferred = false,
+ ) {
+ }
+
+ /**
+ * @param list $columns
+ * @param list $referenceColumns
+ */
+ public static function create(array $columns, string $referenceTable, array $referenceColumns = []) : self
+ {
+ return new self($columns, $referenceTable, $referenceColumns);
+ }
+
+ public function deferrable(bool $initiallyDeferred = false) : self
+ {
+ return new self(
+ $this->columns,
+ $this->referenceTable,
+ $this->referenceColumns,
+ $this->referenceSchema,
+ $this->name,
+ $this->onUpdate,
+ $this->onDelete,
+ true,
+ $initiallyDeferred,
+ );
+ }
+
+ public function name(string $name) : self
+ {
+ return new self(
+ $this->columns,
+ $this->referenceTable,
+ $this->referenceColumns,
+ $this->referenceSchema,
+ $name,
+ $this->onUpdate,
+ $this->onDelete,
+ $this->deferrable,
+ $this->initiallyDeferred,
+ );
+ }
+
+ public function onDelete(ReferentialAction $action) : self
+ {
+ return new self(
+ $this->columns,
+ $this->referenceTable,
+ $this->referenceColumns,
+ $this->referenceSchema,
+ $this->name,
+ $this->onUpdate,
+ $action,
+ $this->deferrable,
+ $this->initiallyDeferred,
+ );
+ }
+
+ public function onUpdate(ReferentialAction $action) : self
+ {
+ return new self(
+ $this->columns,
+ $this->referenceTable,
+ $this->referenceColumns,
+ $this->referenceSchema,
+ $this->name,
+ $action,
+ $this->onDelete,
+ $this->deferrable,
+ $this->initiallyDeferred,
+ );
+ }
+
+ public function schema(string $schema) : self
+ {
+ return new self(
+ $this->columns,
+ $this->referenceTable,
+ $this->referenceColumns,
+ $schema,
+ $this->name,
+ $this->onUpdate,
+ $this->onDelete,
+ $this->deferrable,
+ $this->initiallyDeferred,
+ );
+ }
+
+ public function toAst() : Constraint
+ {
+ $constraint = new Constraint();
+ $constraint->setContype(ConstrType::CONSTR_FOREIGN);
+
+ if ($this->name !== null) {
+ $constraint->setConname($this->name);
+ }
+
+ $fkAttrs = [];
+
+ foreach ($this->columns as $column) {
+ $fkAttrs[] = $this->createStringNode($column);
+ }
+
+ $constraint->setFkAttrs($fkAttrs);
+
+ $rangeVar = new RangeVar();
+ $rangeVar->setRelname($this->referenceTable);
+ $rangeVar->setInh(true);
+
+ if ($this->referenceSchema !== null) {
+ $rangeVar->setSchemaname($this->referenceSchema);
+ }
+
+ $constraint->setPktable($rangeVar);
+
+ if ($this->referenceColumns !== []) {
+ $pkAttrs = [];
+
+ foreach ($this->referenceColumns as $column) {
+ $pkAttrs[] = $this->createStringNode($column);
+ }
+
+ $constraint->setPkAttrs($pkAttrs);
+ }
+
+ if ($this->onUpdate !== null) {
+ $constraint->setFkUpdAction($this->onUpdate->value);
+ }
+
+ if ($this->onDelete !== null) {
+ $constraint->setFkDelAction($this->onDelete->value);
+ }
+
+ if ($this->deferrable) {
+ $constraint->setDeferrable(true);
+
+ if ($this->initiallyDeferred) {
+ $constraint->setInitdeferred(true);
+ }
+ }
+
+ return $constraint;
+ }
+
+ private function createStringNode(string $value) : Node
+ {
+ $str = new PBString();
+ $str->setSval($value);
+
+ $node = new Node();
+ $node->setString($str);
+
+ return $node;
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Constraint/PrimaryKeyConstraint.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Constraint/PrimaryKeyConstraint.php
new file mode 100644
index 000000000..bb86d4a43
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Constraint/PrimaryKeyConstraint.php
@@ -0,0 +1,60 @@
+ $columns
+ */
+ private function __construct(
+ private array $columns,
+ private ?string $name = null,
+ ) {
+ }
+
+ public static function create(string ...$columns) : self
+ {
+ return new self(\array_values($columns));
+ }
+
+ public function name(string $name) : self
+ {
+ return new self($this->columns, $name);
+ }
+
+ public function toAst() : Constraint
+ {
+ $constraint = new Constraint();
+ $constraint->setContype(ConstrType::CONSTR_PRIMARY);
+
+ if ($this->name !== null) {
+ $constraint->setConname($this->name);
+ }
+
+ $keys = [];
+
+ foreach ($this->columns as $column) {
+ $keys[] = $this->createStringNode($column);
+ }
+
+ $constraint->setKeys($keys);
+
+ return $constraint;
+ }
+
+ private function createStringNode(string $value) : Node
+ {
+ $str = new PBString();
+ $str->setSval($value);
+
+ $node = new Node();
+ $node->setString($str);
+
+ return $node;
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Constraint/TableConstraint.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Constraint/TableConstraint.php
new file mode 100644
index 000000000..2505f205a
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Constraint/TableConstraint.php
@@ -0,0 +1,12 @@
+ $columns
+ */
+ private function __construct(
+ private array $columns,
+ private ?string $name = null,
+ private bool $nullsNotDistinct = false,
+ ) {
+ }
+
+ public static function create(string ...$columns) : self
+ {
+ return new self(\array_values($columns));
+ }
+
+ public function name(string $name) : self
+ {
+ return new self($this->columns, $name, $this->nullsNotDistinct);
+ }
+
+ public function nullsNotDistinct() : self
+ {
+ return new self($this->columns, $this->name, true);
+ }
+
+ public function toAst() : Constraint
+ {
+ $constraint = new Constraint();
+ $constraint->setContype(ConstrType::CONSTR_UNIQUE);
+
+ if ($this->name !== null) {
+ $constraint->setConname($this->name);
+ }
+
+ if ($this->nullsNotDistinct) {
+ $constraint->setNullsNotDistinct(true);
+ }
+
+ $keys = [];
+
+ foreach ($this->columns as $column) {
+ $keys[] = $this->createStringNode($column);
+ }
+
+ $constraint->setKeys($keys);
+
+ return $constraint;
+ }
+
+ private function createStringNode(string $value) : Node
+ {
+ $str = new PBString();
+ $str->setSval($value);
+
+ $node = new Node();
+ $node->setString($str);
+
+ return $node;
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/CreateSequence/CreateSequenceBuilder.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/CreateSequence/CreateSequenceBuilder.php
new file mode 100644
index 000000000..ead77ebc2
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/CreateSequence/CreateSequenceBuilder.php
@@ -0,0 +1,311 @@
+ $options
+ */
+ private function __construct(
+ private ?string $name = null,
+ private ?string $schema = null,
+ private bool $ifNotExists = false,
+ private bool $temporary = false,
+ private bool $unlogged = false,
+ private array $options = [],
+ ) {
+ }
+
+ public static function create() : CreateSequenceNameStep
+ {
+ return new self();
+ }
+
+ public static function createIfNotExists() : CreateSequenceNameStep
+ {
+ return new self(ifNotExists: true);
+ }
+
+ public static function createTemporary() : CreateSequenceNameStep
+ {
+ return new self(temporary: true);
+ }
+
+ public static function createUnlogged() : CreateSequenceNameStep
+ {
+ return new self(unlogged: true);
+ }
+
+ public function asType(string $dataType) : CreateSequenceOptionsStep
+ {
+ $typeMap = [
+ 'smallint' => 'int2',
+ 'integer' => 'int4',
+ 'bigint' => 'int8',
+ 'int2' => 'int2',
+ 'int4' => 'int4',
+ 'int8' => 'int8',
+ ];
+
+ $pgType = $typeMap[\strtolower($dataType)] ?? $dataType;
+
+ $typeName = new TypeName();
+ $names = [];
+
+ $catalogStr = new PBString();
+ $catalogStr->setSval('pg_catalog');
+ $catalogNode = new Node();
+ $catalogNode->setString($catalogStr);
+ $names[] = $catalogNode;
+
+ $typeStr = new PBString();
+ $typeStr->setSval($pgType);
+ $typeNode = new Node();
+ $typeNode->setString($typeStr);
+ $names[] = $typeNode;
+
+ $typeName->setNames($names);
+ $typeName->setTypemod(-1);
+
+ $argNode = new Node();
+ $argNode->setTypeName($typeName);
+
+ return $this->withOption('as', $argNode);
+ }
+
+ public function cache(int $cache) : CreateSequenceOptionsStep
+ {
+ return $this->withIntegerOption('cache', $cache);
+ }
+
+ public function cycle() : CreateSequenceOptionsStep
+ {
+ return $this->withBooleanOption('cycle', true);
+ }
+
+ public function ifNotExists() : self
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ true,
+ $this->temporary,
+ $this->unlogged,
+ $this->options,
+ );
+ }
+
+ public function incrementBy(int $increment) : CreateSequenceOptionsStep
+ {
+ return $this->withIntegerOption('increment', $increment);
+ }
+
+ public function maxValue(int $maxValue) : CreateSequenceOptionsStep
+ {
+ return $this->withIntegerOption('maxvalue', $maxValue);
+ }
+
+ public function minValue(int $minValue) : CreateSequenceOptionsStep
+ {
+ return $this->withIntegerOption('minvalue', $minValue);
+ }
+
+ public function noCycle() : CreateSequenceOptionsStep
+ {
+ return $this->withBooleanOption('cycle', false);
+ }
+
+ public function noMaxValue() : CreateSequenceOptionsStep
+ {
+ return $this->withOption('maxvalue', null);
+ }
+
+ public function noMinValue() : CreateSequenceOptionsStep
+ {
+ return $this->withOption('minvalue', null);
+ }
+
+ public function ownedBy(string $table, string $column) : CreateSequenceOptionsStep
+ {
+ $list = new PBList();
+ $items = [];
+
+ $identifier = QualifiedIdentifier::parse($table);
+
+ foreach ($identifier->parts() as $part) {
+ $str = new PBString();
+ $str->setSval($part);
+ $strNode = new Node();
+ $strNode->setString($str);
+ $items[] = $strNode;
+ }
+
+ $colStr = new PBString();
+ $colStr->setSval($column);
+ $colNode = new Node();
+ $colNode->setString($colStr);
+ $items[] = $colNode;
+
+ $list->setItems($items);
+
+ $argNode = new Node();
+ $argNode->setList($list);
+
+ return $this->withOption('owned_by', $argNode);
+ }
+
+ public function ownedByNone() : CreateSequenceOptionsStep
+ {
+ $list = new PBList();
+ $items = [];
+
+ $str = new PBString();
+ $str->setSval('none');
+ $strNode = new Node();
+ $strNode->setString($str);
+ $items[] = $strNode;
+
+ $list->setItems($items);
+
+ $argNode = new Node();
+ $argNode->setList($list);
+
+ return $this->withOption('owned_by', $argNode);
+ }
+
+ public function sequence(string $name, ?string $schema = null) : CreateSequenceOptionsStep
+ {
+ return new self(
+ $name,
+ $schema,
+ $this->ifNotExists,
+ $this->temporary,
+ $this->unlogged,
+ $this->options,
+ );
+ }
+
+ public function startWith(int $start) : CreateSequenceOptionsStep
+ {
+ return $this->withIntegerOption('start', $start);
+ }
+
+ public function temporary() : self
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ $this->ifNotExists,
+ true,
+ false,
+ $this->options,
+ );
+ }
+
+ public function toAst() : CreateSeqStmt
+ {
+ $stmt = new CreateSeqStmt();
+
+ $rangeVar = new RangeVar();
+ $rangeVar->setRelname($this->name ?? '');
+ $rangeVar->setInh(true);
+
+ if ($this->schema !== null) {
+ $rangeVar->setSchemaname($this->schema);
+ }
+
+ if ($this->temporary) {
+ $rangeVar->setRelpersistence('t');
+ } elseif ($this->unlogged) {
+ $rangeVar->setRelpersistence('u');
+ } else {
+ $rangeVar->setRelpersistence('p');
+ }
+
+ $stmt->setSequence($rangeVar);
+
+ if ($this->ifNotExists) {
+ $stmt->setIfNotExists(true);
+ }
+
+ if ($this->options !== []) {
+ $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;
+ }
+
+ $stmt->setOptions($optionNodes);
+ }
+
+ return $stmt;
+ }
+
+ public function unlogged() : self
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ $this->ifNotExists,
+ false,
+ true,
+ $this->options,
+ );
+ }
+
+ private function withBooleanOption(string $name, bool $value) : self
+ {
+ $boolean = new Boolean();
+ $boolean->setBoolval($value);
+
+ $argNode = new Node();
+ /** @phpstan-ignore argument.type (protobuf PHPDoc says bool but actually expects Boolean) */
+ $argNode->setBoolean($boolean);
+
+ return $this->withOption($name, $argNode);
+ }
+
+ private function withIntegerOption(string $name, int $value) : self
+ {
+ $integer = new Integer();
+ $integer->setIval($value);
+
+ $argNode = new Node();
+ /** @phpstan-ignore argument.type (protobuf PHPDoc says int but actually expects Integer) */
+ $argNode->setInteger($integer);
+
+ return $this->withOption($name, $argNode);
+ }
+
+ private function withOption(string $name, ?Node $arg) : self
+ {
+ $newOptions = $this->options;
+ $newOptions[] = ['name' => $name, 'arg' => $arg];
+
+ return new self(
+ $this->name,
+ $this->schema,
+ $this->ifNotExists,
+ $this->temporary,
+ $this->unlogged,
+ $newOptions,
+ );
+ }
+}
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
new file mode 100644
index 000000000..27714c470
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/CreateSequence/CreateSequenceFinalStep.php
@@ -0,0 +1,14 @@
+ $columns
+ * @param list $constraints
+ * @param list $inherits
+ * @param list $partitionColumns
+ */
+ private function __construct(
+ private string $table,
+ private ?string $schema = null,
+ private array $columns = [],
+ private array $constraints = [],
+ private bool $ifNotExists = false,
+ private bool $temporary = false,
+ private bool $unlogged = false,
+ private array $inherits = [],
+ private ?int $partitionStrategy = null,
+ private array $partitionColumns = [],
+ private ?string $tablespace = null,
+ ) {
+ }
+
+ public static function create(string $table, ?string $schema = null) : CreateTableColumnsStep
+ {
+ return new self($table, $schema);
+ }
+
+ public function column(ColumnDefinition $column) : CreateTableColumnsStep
+ {
+ return new self(
+ $this->table,
+ $this->schema,
+ [...$this->columns, $column],
+ $this->constraints,
+ $this->ifNotExists,
+ $this->temporary,
+ $this->unlogged,
+ $this->inherits,
+ $this->partitionStrategy,
+ $this->partitionColumns,
+ $this->tablespace,
+ );
+ }
+
+ public function constraint(TableConstraint $constraint) : CreateTableFinalStep
+ {
+ return new self(
+ $this->table,
+ $this->schema,
+ $this->columns,
+ [...$this->constraints, $constraint],
+ $this->ifNotExists,
+ $this->temporary,
+ $this->unlogged,
+ $this->inherits,
+ $this->partitionStrategy,
+ $this->partitionColumns,
+ $this->tablespace,
+ );
+ }
+
+ public function ifNotExists() : CreateTableFinalStep
+ {
+ return new self(
+ $this->table,
+ $this->schema,
+ $this->columns,
+ $this->constraints,
+ true,
+ $this->temporary,
+ $this->unlogged,
+ $this->inherits,
+ $this->partitionStrategy,
+ $this->partitionColumns,
+ $this->tablespace,
+ );
+ }
+
+ public function inherits(string ...$tables) : CreateTableFinalStep
+ {
+ return new self(
+ $this->table,
+ $this->schema,
+ $this->columns,
+ $this->constraints,
+ $this->ifNotExists,
+ $this->temporary,
+ $this->unlogged,
+ \array_values([...$this->inherits, ...$tables]),
+ $this->partitionStrategy,
+ $this->partitionColumns,
+ $this->tablespace,
+ );
+ }
+
+ public function partitionByHash(string ...$columns) : CreateTableFinalStep
+ {
+ return new self(
+ $this->table,
+ $this->schema,
+ $this->columns,
+ $this->constraints,
+ $this->ifNotExists,
+ $this->temporary,
+ $this->unlogged,
+ $this->inherits,
+ PartitionStrategy::PARTITION_STRATEGY_HASH,
+ \array_values($columns),
+ $this->tablespace,
+ );
+ }
+
+ public function partitionByList(string ...$columns) : CreateTableFinalStep
+ {
+ return new self(
+ $this->table,
+ $this->schema,
+ $this->columns,
+ $this->constraints,
+ $this->ifNotExists,
+ $this->temporary,
+ $this->unlogged,
+ $this->inherits,
+ PartitionStrategy::PARTITION_STRATEGY_LIST,
+ \array_values($columns),
+ $this->tablespace,
+ );
+ }
+
+ public function partitionByRange(string ...$columns) : CreateTableFinalStep
+ {
+ return new self(
+ $this->table,
+ $this->schema,
+ $this->columns,
+ $this->constraints,
+ $this->ifNotExists,
+ $this->temporary,
+ $this->unlogged,
+ $this->inherits,
+ PartitionStrategy::PARTITION_STRATEGY_RANGE,
+ \array_values($columns),
+ $this->tablespace,
+ );
+ }
+
+ public function tablespace(string $tablespaceName) : CreateTableFinalStep
+ {
+ return new self(
+ $this->table,
+ $this->schema,
+ $this->columns,
+ $this->constraints,
+ $this->ifNotExists,
+ $this->temporary,
+ $this->unlogged,
+ $this->inherits,
+ $this->partitionStrategy,
+ $this->partitionColumns,
+ $tablespaceName,
+ );
+ }
+
+ public function temporary() : CreateTableFinalStep
+ {
+ return new self(
+ $this->table,
+ $this->schema,
+ $this->columns,
+ $this->constraints,
+ $this->ifNotExists,
+ true,
+ false,
+ $this->inherits,
+ $this->partitionStrategy,
+ $this->partitionColumns,
+ $this->tablespace,
+ );
+ }
+
+ public function toAst() : CreateStmt
+ {
+ $createStmt = new CreateStmt();
+
+ $rangeVar = new RangeVar();
+ $rangeVar->setRelname($this->table);
+ $rangeVar->setInh(true);
+
+ if ($this->schema !== null) {
+ $rangeVar->setSchemaname($this->schema);
+ }
+
+ if ($this->temporary) {
+ $rangeVar->setRelpersistence('t');
+ } elseif ($this->unlogged) {
+ $rangeVar->setRelpersistence('u');
+ } else {
+ $rangeVar->setRelpersistence('p');
+ }
+
+ $createStmt->setRelation($rangeVar);
+
+ if ($this->columns !== [] || $this->constraints !== []) {
+ $tableElts = [];
+
+ foreach ($this->columns as $column) {
+ $node = new Node();
+ $node->setColumnDef($column->toAst());
+ $tableElts[] = $node;
+ }
+
+ foreach ($this->constraints as $constraint) {
+ $node = new Node();
+ $node->setConstraint($constraint->toAst());
+ $tableElts[] = $node;
+ }
+
+ $createStmt->setTableElts($tableElts);
+ }
+
+ if ($this->ifNotExists) {
+ $createStmt->setIfNotExists(true);
+ }
+
+ if ($this->temporary) {
+ $createStmt->setOncommit(OnCommitAction::ONCOMMIT_DROP);
+ }
+
+ if ($this->inherits !== []) {
+ $inhRelations = [];
+
+ foreach ($this->inherits as $parentTable) {
+ $parentRangeVar = new RangeVar();
+ $parentRangeVar->setRelname($parentTable);
+ $parentRangeVar->setInh(true);
+ $parentRangeVar->setRelpersistence('p');
+
+ $node = new Node();
+ $node->setRangeVar($parentRangeVar);
+ $inhRelations[] = $node;
+ }
+
+ $createStmt->setInhRelations($inhRelations);
+ }
+
+ if ($this->partitionStrategy !== null && $this->partitionColumns !== []) {
+ $partitionSpec = new PartitionSpec();
+ $partitionSpec->setStrategy($this->partitionStrategy);
+
+ $partParams = [];
+
+ foreach ($this->partitionColumns as $columnName) {
+ $partitionElem = new PartitionElem();
+ $partitionElem->setName($columnName);
+
+ $node = new Node();
+ $node->setPartitionElem($partitionElem);
+ $partParams[] = $node;
+ }
+
+ $partitionSpec->setPartParams($partParams);
+ $createStmt->setPartspec($partitionSpec);
+ }
+
+ if ($this->tablespace !== null) {
+ $createStmt->setTablespacename($this->tablespace);
+ }
+
+ return $createStmt;
+ }
+
+ public function unlogged() : CreateTableFinalStep
+ {
+ return new self(
+ $this->table,
+ $this->schema,
+ $this->columns,
+ $this->constraints,
+ $this->ifNotExists,
+ false,
+ true,
+ $this->inherits,
+ $this->partitionStrategy,
+ $this->partitionColumns,
+ $this->tablespace,
+ );
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/CreateTable/CreateTableColumnsStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/CreateTable/CreateTableColumnsStep.php
new file mode 100644
index 000000000..f40e8d992
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/CreateTable/CreateTableColumnsStep.php
@@ -0,0 +1,12 @@
+ $columnNames
+ */
+ private function __construct(
+ private string $table,
+ private ?string $schema,
+ private SelectFinalStep $query,
+ private array $columnNames = [],
+ private bool $ifNotExists = false,
+ private bool $withNoData = false,
+ ) {
+ }
+
+ public static function create(string $table, SelectFinalStep $query, ?string $schema = null) : CreateTableAsFinalStep
+ {
+ return new self($table, $schema, $query);
+ }
+
+ public function columnNames(string ...$names) : CreateTableAsFinalStep
+ {
+ return new self(
+ $this->table,
+ $this->schema,
+ $this->query,
+ \array_values($names),
+ $this->ifNotExists,
+ $this->withNoData,
+ );
+ }
+
+ public function ifNotExists() : CreateTableAsFinalStep
+ {
+ return new self(
+ $this->table,
+ $this->schema,
+ $this->query,
+ $this->columnNames,
+ true,
+ $this->withNoData,
+ );
+ }
+
+ public function toAst() : CreateTableAsStmt
+ {
+ $stmt = new CreateTableAsStmt();
+
+ $rangeVar = new RangeVar();
+ $rangeVar->setRelname($this->table);
+ $rangeVar->setRelpersistence('p');
+ $rangeVar->setInh(true);
+
+ if ($this->schema !== null) {
+ $rangeVar->setSchemaname($this->schema);
+ }
+
+ $intoClause = new IntoClause();
+ $intoClause->setRel($rangeVar);
+
+ if ($this->columnNames !== []) {
+ $colNames = [];
+
+ foreach ($this->columnNames as $name) {
+ $colNames[] = $this->createStringNode($name);
+ }
+
+ $intoClause->setColNames($colNames);
+ }
+
+ if ($this->withNoData) {
+ $intoClause->setSkipData(true);
+ }
+
+ $stmt->setInto($intoClause);
+
+ $queryNode = new Node();
+ $queryNode->setSelectStmt($this->query->toAst());
+ $stmt->setQuery($queryNode);
+
+ $stmt->setObjtype(ObjectType::OBJECT_TABLE);
+
+ if ($this->ifNotExists) {
+ $stmt->setIfNotExists(true);
+ }
+
+ return $stmt;
+ }
+
+ public function withNoData() : CreateTableAsFinalStep
+ {
+ return new self(
+ $this->table,
+ $this->schema,
+ $this->query,
+ $this->columnNames,
+ $this->ifNotExists,
+ true,
+ );
+ }
+
+ private function createStringNode(string $value) : Node
+ {
+ $str = new PBString();
+ $str->setSval($value);
+
+ $node = new Node();
+ $node->setString($str);
+
+ return $node;
+ }
+}
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
new file mode 100644
index 000000000..7e0c03984
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/CreateTableAs/CreateTableAsFinalStep.php
@@ -0,0 +1,20 @@
+ $names
+ * @param list $typmods
+ * @param list $arrayBounds
+ */
+ private function __construct(
+ private array $names,
+ private array $typmods = [],
+ private array $arrayBounds = [],
+ ) {
+ }
+
+ public static function array(self $elementType) : self
+ {
+ return new self(
+ $elementType->names,
+ $elementType->typmods,
+ [-1],
+ );
+ }
+
+ public static function bigint() : self
+ {
+ return new self(['pg_catalog', 'int8']);
+ }
+
+ public static function bigserial() : self
+ {
+ return new self(['bigserial']);
+ }
+
+ public static function boolean() : self
+ {
+ return new self(['pg_catalog', 'bool']);
+ }
+
+ public static function bytea() : self
+ {
+ return new self(['pg_catalog', 'bytea']);
+ }
+
+ public static function char(int $length) : self
+ {
+ return new self(['pg_catalog', 'bpchar'], [$length]);
+ }
+
+ public static function cidr() : self
+ {
+ return new self(['pg_catalog', 'cidr']);
+ }
+
+ public static function custom(string $typeName, ?string $schema = null) : self
+ {
+ if ($schema !== null) {
+ return new self([$schema, $typeName]);
+ }
+
+ return new self([$typeName]);
+ }
+
+ public static function date() : self
+ {
+ return new self(['pg_catalog', 'date']);
+ }
+
+ public static function decimal(?int $precision = null, ?int $scale = null) : self
+ {
+ return self::numeric($precision, $scale);
+ }
+
+ public static function doublePrecision() : self
+ {
+ return new self(['pg_catalog', 'float8']);
+ }
+
+ public static function inet() : self
+ {
+ return new self(['pg_catalog', 'inet']);
+ }
+
+ public static function integer() : self
+ {
+ return new self(['pg_catalog', 'int4']);
+ }
+
+ public static function interval() : self
+ {
+ return new self(['pg_catalog', 'interval']);
+ }
+
+ public static function json() : self
+ {
+ return new self(['pg_catalog', 'json']);
+ }
+
+ public static function jsonb() : self
+ {
+ return new self(['pg_catalog', 'jsonb']);
+ }
+
+ public static function macaddr() : self
+ {
+ return new self(['pg_catalog', 'macaddr']);
+ }
+
+ 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);
+ }
+
+ public static function real() : self
+ {
+ return new self(['pg_catalog', 'float4']);
+ }
+
+ public static function serial() : self
+ {
+ return new self(['serial']);
+ }
+
+ public static function smallint() : self
+ {
+ return new self(['pg_catalog', 'int2']);
+ }
+
+ public static function smallserial() : self
+ {
+ return new self(['smallserial']);
+ }
+
+ public static function text() : self
+ {
+ return new self(['pg_catalog', 'text']);
+ }
+
+ public static function time(?int $precision = null) : self
+ {
+ $typmods = [];
+
+ if ($precision !== null) {
+ $typmods[] = $precision;
+ }
+
+ return new self(['pg_catalog', 'time'], $typmods);
+ }
+
+ public static function timestamp(?int $precision = null) : self
+ {
+ $typmods = [];
+
+ if ($precision !== null) {
+ $typmods[] = $precision;
+ }
+
+ return new self(['pg_catalog', 'timestamp'], $typmods);
+ }
+
+ public static function timestamptz(?int $precision = null) : self
+ {
+ $typmods = [];
+
+ if ($precision !== null) {
+ $typmods[] = $precision;
+ }
+
+ return new self(['pg_catalog', 'timestamptz'], $typmods);
+ }
+
+ public static function uuid() : self
+ {
+ return new self(['pg_catalog', 'uuid']);
+ }
+
+ public static function varchar(int $length) : self
+ {
+ return new self(['pg_catalog', 'varchar'], [$length]);
+ }
+
+ public function toAst() : TypeName
+ {
+ $typeName = new TypeName();
+
+ $names = [];
+
+ foreach ($this->names as $name) {
+ $names[] = $this->createStringNode($name);
+ }
+
+ $typeName->setNames($names);
+
+ if ($this->typmods !== []) {
+ $typmods = [];
+
+ foreach ($this->typmods as $typmod) {
+ $typmods[] = $this->createIntegerConstNode($typmod);
+ }
+
+ $typeName->setTypmods($typmods);
+ }
+
+ if ($this->arrayBounds !== []) {
+ $arrayBounds = [];
+
+ foreach ($this->arrayBounds as $bound) {
+ $arrayBounds[] = $this->createIntegerConstNode($bound);
+ }
+
+ $typeName->setArrayBounds($arrayBounds);
+ }
+
+ return $typeName;
+ }
+
+ private function createIntegerConstNode(int $value) : Node
+ {
+ $aConst = new A_Const();
+ $ival = new Integer();
+ $ival->setIval($value);
+ /** @phpstan-ignore argument.type (protobuf PHPDoc says int but actually expects Integer) */
+ $aConst->setIval($ival);
+
+ $node = new Node();
+ $node->setAConst($aConst);
+
+ return $node;
+ }
+
+ private function createStringNode(string $value) : Node
+ {
+ $str = new PBString();
+ $str->setSval($value);
+
+ $node = new Node();
+ $node->setString($str);
+
+ return $node;
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Domain/AlterDomainActionStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Domain/AlterDomainActionStep.php
new file mode 100644
index 000000000..1447c9adf
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Domain/AlterDomainActionStep.php
@@ -0,0 +1,22 @@
+name(), $identifier->schema());
+ }
+
+ public function addConstraint(string $name, string $expression) : AlterDomainFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ 'C',
+ $name,
+ $expression,
+ $this->behavior,
+ $this->missingOk,
+ );
+ }
+
+ public function cascade() : AlterDomainFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ $this->subtype,
+ $this->constraintName,
+ $this->expression,
+ DropBehavior::DROP_CASCADE,
+ $this->missingOk,
+ );
+ }
+
+ public function dropConstraint(string $name) : AlterDomainFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ 'X',
+ $name,
+ null,
+ $this->behavior,
+ $this->missingOk,
+ );
+ }
+
+ public function dropDefault() : AlterDomainFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ 'T',
+ null,
+ null,
+ $this->behavior,
+ $this->missingOk,
+ );
+ }
+
+ public function dropNotNull() : AlterDomainFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ 'N',
+ null,
+ null,
+ $this->behavior,
+ $this->missingOk,
+ );
+ }
+
+ public function ifExists() : AlterDomainFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ $this->subtype,
+ $this->constraintName,
+ $this->expression,
+ $this->behavior,
+ true,
+ );
+ }
+
+ public function restrict() : AlterDomainFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ $this->subtype,
+ $this->constraintName,
+ $this->expression,
+ DropBehavior::DROP_RESTRICT,
+ $this->missingOk,
+ );
+ }
+
+ public function setDefault(string $expression) : AlterDomainFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ 'T',
+ null,
+ $expression,
+ $this->behavior,
+ $this->missingOk,
+ );
+ }
+
+ public function setNotNull() : AlterDomainFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ 'O',
+ null,
+ null,
+ $this->behavior,
+ $this->missingOk,
+ );
+ }
+
+ public function toAst() : AlterDomainStmt
+ {
+ $stmt = new AlterDomainStmt();
+ $stmt->setSubtype($this->subtype);
+
+ $typeNameNodes = [];
+
+ if ($this->schema !== null) {
+ $str = new PBString();
+ $str->setSval($this->schema);
+ $node = new Node();
+ $node->setString($str);
+ $typeNameNodes[] = $node;
+ }
+
+ $str = new PBString();
+ $str->setSval($this->name);
+ $node = new Node();
+ $node->setString($str);
+ $typeNameNodes[] = $node;
+
+ $stmt->setTypeName($typeNameNodes);
+
+ if ($this->constraintName !== null) {
+ $stmt->setName($this->constraintName);
+ }
+
+ if ($this->subtype === 'C' && $this->expression !== null) {
+ $constraint = new Constraint();
+ $constraint->setContype(ConstrType::CONSTR_CHECK);
+ $constraint->setRawExpr($this->parseExpression($this->expression));
+
+ if ($this->constraintName !== null) {
+ $constraint->setConname($this->constraintName);
+ }
+
+ $defNode = new Node();
+ $defNode->setConstraint($constraint);
+ $stmt->setDef($defNode);
+ } elseif ($this->subtype === 'T' && $this->expression !== null) {
+ $stmt->setDef($this->parseExpression($this->expression));
+ }
+
+ $stmt->setBehavior($this->behavior);
+ $stmt->setMissingOk($this->missingOk);
+
+ return $stmt;
+ }
+
+ public function validateConstraint(string $name) : AlterDomainFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ 'V',
+ $name,
+ null,
+ $this->behavior,
+ $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
new file mode 100644
index 000000000..17688e235
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Domain/AlterDomainFinalStep.php
@@ -0,0 +1,20 @@
+ $constraints
+ */
+ private function __construct(
+ private string $name,
+ private ?string $schema = null,
+ private ?DataType $dataType = null,
+ private ?string $collation = null,
+ private array $constraints = [],
+ private ?string $currentConstraintName = null,
+ ) {
+ }
+
+ public static function create(string $name) : CreateDomainTypeStep
+ {
+ $identifier = QualifiedIdentifier::parse($name);
+
+ return new self($identifier->name(), $identifier->schema());
+ }
+
+ public function as(DataType $dataType) : CreateDomainOptionsStep
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ $dataType,
+ $this->collation,
+ $this->constraints,
+ $this->currentConstraintName,
+ );
+ }
+
+ public function check(string $expression) : CreateDomainOptionsStep
+ {
+ $constraint = new Constraint();
+ $constraint->setContype(ConstrType::CONSTR_CHECK);
+ $constraint->setRawExpr($this->parseExpression($expression));
+
+ if ($this->currentConstraintName !== null) {
+ $constraint->setConname($this->currentConstraintName);
+ }
+
+ $newConstraints = $this->constraints;
+ $newConstraints[] = $constraint;
+
+ return new self(
+ $this->name,
+ $this->schema,
+ $this->dataType,
+ $this->collation,
+ $newConstraints,
+ null,
+ );
+ }
+
+ public function collate(string $collation) : CreateDomainOptionsStep
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ $this->dataType,
+ $collation,
+ $this->constraints,
+ $this->currentConstraintName,
+ );
+ }
+
+ public function constraint(string $name) : CreateDomainOptionsStep
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ $this->dataType,
+ $this->collation,
+ $this->constraints,
+ $name,
+ );
+ }
+
+ public function default(string $expression) : CreateDomainOptionsStep
+ {
+ $constraint = new Constraint();
+ $constraint->setContype(ConstrType::CONSTR_DEFAULT);
+ $constraint->setRawExpr($this->parseExpression($expression));
+
+ $newConstraints = $this->constraints;
+ $newConstraints[] = $constraint;
+
+ return new self(
+ $this->name,
+ $this->schema,
+ $this->dataType,
+ $this->collation,
+ $newConstraints,
+ $this->currentConstraintName,
+ );
+ }
+
+ public function notNull() : CreateDomainOptionsStep
+ {
+ $constraint = new Constraint();
+ $constraint->setContype(ConstrType::CONSTR_NOTNULL);
+
+ if ($this->currentConstraintName !== null) {
+ $constraint->setConname($this->currentConstraintName);
+ }
+
+ $newConstraints = $this->constraints;
+ $newConstraints[] = $constraint;
+
+ return new self(
+ $this->name,
+ $this->schema,
+ $this->dataType,
+ $this->collation,
+ $newConstraints,
+ null,
+ );
+ }
+
+ public function null() : CreateDomainOptionsStep
+ {
+ $constraint = new Constraint();
+ $constraint->setContype(ConstrType::CONSTR_NULL);
+
+ $newConstraints = $this->constraints;
+ $newConstraints[] = $constraint;
+
+ return new self(
+ $this->name,
+ $this->schema,
+ $this->dataType,
+ $this->collation,
+ $newConstraints,
+ $this->currentConstraintName,
+ );
+ }
+
+ public function toAst() : CreateDomainStmt
+ {
+ $stmt = new CreateDomainStmt();
+
+ $domainNameNodes = [];
+
+ if ($this->schema !== null) {
+ $str = new PBString();
+ $str->setSval($this->schema);
+ $node = new Node();
+ $node->setString($str);
+ $domainNameNodes[] = $node;
+ }
+
+ $str = new PBString();
+ $str->setSval($this->name);
+ $node = new Node();
+ $node->setString($str);
+ $domainNameNodes[] = $node;
+
+ $stmt->setDomainname($domainNameNodes);
+
+ if ($this->dataType !== null) {
+ $stmt->setTypeName($this->dataType->toAst());
+ }
+
+ if ($this->collation !== null) {
+ $collClause = new CollateClause();
+
+ $collNameNodes = [];
+ $str = new PBString();
+ $str->setSval($this->collation);
+ $node = new Node();
+ $node->setString($str);
+ $collNameNodes[] = $node;
+
+ $collClause->setCollname($collNameNodes);
+ $stmt->setCollClause($collClause);
+ }
+
+ if ($this->constraints !== []) {
+ $constraintNodes = [];
+
+ foreach ($this->constraints as $constraint) {
+ $node = new Node();
+ $node->setConstraint($constraint);
+ $constraintNodes[] = $node;
+ }
+
+ $stmt->setConstraints($constraintNodes);
+ }
+
+ 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
new file mode 100644
index 000000000..409653590
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Domain/CreateDomainFinalStep.php
@@ -0,0 +1,14 @@
+ $names
+ */
+ private function __construct(
+ private array $names,
+ private bool $ifExists = false,
+ private int $behavior = DropBehavior::DROP_RESTRICT,
+ ) {
+ }
+
+ public static function create(string ...$names) : DropDomainFinalStep
+ {
+ return new self(\array_values($names));
+ }
+
+ public function cascade() : DropDomainFinalStep
+ {
+ return new self(
+ $this->names,
+ $this->ifExists,
+ DropBehavior::DROP_CASCADE,
+ );
+ }
+
+ public function ifExists() : DropDomainFinalStep
+ {
+ return new self(
+ $this->names,
+ true,
+ $this->behavior,
+ );
+ }
+
+ public function restrict() : DropDomainFinalStep
+ {
+ return new self(
+ $this->names,
+ $this->ifExists,
+ DropBehavior::DROP_RESTRICT,
+ );
+ }
+
+ public function toAst() : DropStmt
+ {
+ $stmt = new DropStmt();
+ $stmt->setRemoveType(ObjectType::OBJECT_DOMAIN);
+ $stmt->setBehavior($this->behavior);
+ $stmt->setMissingOk($this->ifExists);
+
+ $objects = [];
+
+ foreach ($this->names as $name) {
+ $identifier = QualifiedIdentifier::parse($name);
+ $nameNodes = [];
+
+ foreach ($identifier->parts() as $part) {
+ $str = new PBString();
+ $str->setSval($part);
+ $node = new Node();
+ $node->setString($str);
+ $nameNodes[] = $node;
+ }
+
+ $typeName = new TypeName();
+ $typeName->setNames($nameNodes);
+ $typeName->setTypemod(-1);
+
+ $node = new Node();
+ $node->setTypeName($typeName);
+ $objects[] = $node;
+ }
+
+ $stmt->setObjects($objects);
+
+ return $stmt;
+ }
+}
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
new file mode 100644
index 000000000..2b1a6d6c8
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Domain/DropDomainFinalStep.php
@@ -0,0 +1,20 @@
+ $sequences
+ */
+ private function __construct(
+ private array $sequences = [],
+ private bool $ifExists = false,
+ private int $behavior = DropBehavior::DROP_BEHAVIOR_UNDEFINED,
+ ) {
+ }
+
+ public static function create() : DropSequenceNameStep
+ {
+ return new self();
+ }
+
+ public function cascade() : DropSequenceFinalStep
+ {
+ return new self(
+ $this->sequences,
+ $this->ifExists,
+ DropBehavior::DROP_CASCADE,
+ );
+ }
+
+ public function ifExists() : DropSequenceFinalStep
+ {
+ return new self(
+ $this->sequences,
+ true,
+ $this->behavior,
+ );
+ }
+
+ public function restrict() : DropSequenceFinalStep
+ {
+ return new self(
+ $this->sequences,
+ $this->ifExists,
+ DropBehavior::DROP_RESTRICT,
+ );
+ }
+
+ public function sequence(string ...$names) : DropSequenceFinalStep
+ {
+ return new self(
+ \array_values($names),
+ $this->ifExists,
+ $this->behavior,
+ );
+ }
+
+ public function toAst() : DropStmt
+ {
+ $stmt = new DropStmt();
+ $stmt->setRemoveType(ObjectType::OBJECT_SEQUENCE);
+
+ if ($this->ifExists) {
+ $stmt->setMissingOk(true);
+ }
+
+ if ($this->behavior !== DropBehavior::DROP_BEHAVIOR_UNDEFINED) {
+ $stmt->setBehavior($this->behavior);
+ }
+
+ $objects = [];
+
+ foreach ($this->sequences as $sequence) {
+ $objects[] = $this->createSequenceListNode($sequence);
+ }
+
+ $stmt->setObjects($objects);
+
+ return $stmt;
+ }
+
+ private function createSequenceListNode(string $sequence) : Node
+ {
+ $identifier = QualifiedIdentifier::parse($sequence);
+ $listItems = [];
+
+ foreach ($identifier->parts() as $part) {
+ $str = new PBString();
+ $str->setSval($part);
+
+ $strNode = new Node();
+ $strNode->setString($str);
+ $listItems[] = $strNode;
+ }
+
+ $list = new PBList();
+ $list->setItems($listItems);
+
+ $node = new Node();
+ $node->setList($list);
+
+ return $node;
+ }
+}
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
new file mode 100644
index 000000000..7c0d4b363
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/DropSequence/DropSequenceFinalStep.php
@@ -0,0 +1,20 @@
+ $tables
+ */
+ private function __construct(
+ private array $tables,
+ private bool $ifExists = false,
+ private int $behavior = DropBehavior::DROP_BEHAVIOR_UNDEFINED,
+ ) {
+ }
+
+ public static function create(string ...$tables) : DropTableFinalStep
+ {
+ return new self(\array_values($tables));
+ }
+
+ public function cascade() : DropTableFinalStep
+ {
+ return new self(
+ $this->tables,
+ $this->ifExists,
+ DropBehavior::DROP_CASCADE,
+ );
+ }
+
+ public function ifExists() : DropTableFinalStep
+ {
+ return new self(
+ $this->tables,
+ true,
+ $this->behavior,
+ );
+ }
+
+ public function restrict() : DropTableFinalStep
+ {
+ return new self(
+ $this->tables,
+ $this->ifExists,
+ DropBehavior::DROP_RESTRICT,
+ );
+ }
+
+ public function toAst() : DropStmt
+ {
+ $stmt = new DropStmt();
+ $stmt->setRemoveType(ObjectType::OBJECT_TABLE);
+
+ if ($this->ifExists) {
+ $stmt->setMissingOk(true);
+ }
+
+ if ($this->behavior !== DropBehavior::DROP_BEHAVIOR_UNDEFINED) {
+ $stmt->setBehavior($this->behavior);
+ }
+
+ $objects = [];
+
+ foreach ($this->tables as $table) {
+ $objects[] = $this->createTableListNode($table);
+ }
+
+ $stmt->setObjects($objects);
+
+ return $stmt;
+ }
+
+ private function createTableListNode(string $table) : Node
+ {
+ $identifier = QualifiedIdentifier::parse($table);
+ $listItems = [];
+
+ foreach ($identifier->parts() as $part) {
+ $str = new PBString();
+ $str->setSval($part);
+
+ $strNode = new Node();
+ $strNode->setString($str);
+ $listItems[] = $strNode;
+ }
+
+ $list = new PBList();
+ $list->setItems($listItems);
+
+ $node = new Node();
+ $node->setList($list);
+
+ return $node;
+ }
+}
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
new file mode 100644
index 000000000..18f1b7d6e
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/DropTable/DropTableFinalStep.php
@@ -0,0 +1,20 @@
+name,
+ false,
+ null,
+ 1,
+ ObjectType::OBJECT_FUNCTION,
+ $function,
+ );
+ }
+
+ public function addTable(string $table) : AlterExtensionFinalStep
+ {
+ return new self(
+ $this->name,
+ false,
+ null,
+ 1,
+ ObjectType::OBJECT_TABLE,
+ $table,
+ );
+ }
+
+ public function dropFunction(string $function) : AlterExtensionFinalStep
+ {
+ return new self(
+ $this->name,
+ false,
+ null,
+ -1,
+ ObjectType::OBJECT_FUNCTION,
+ $function,
+ );
+ }
+
+ public function dropTable(string $table) : AlterExtensionFinalStep
+ {
+ return new self(
+ $this->name,
+ false,
+ null,
+ -1,
+ ObjectType::OBJECT_TABLE,
+ $table,
+ );
+ }
+
+ public function toAst() : AlterExtensionStmt|AlterExtensionContentsStmt
+ {
+ if ($this->isUpdate) {
+ $stmt = new AlterExtensionStmt();
+ $stmt->setExtname($this->name);
+
+ if ($this->version !== null) {
+ $defElem = new DefElem();
+ $defElem->setDefname('new_version');
+
+ $str = new PBString();
+ $str->setSval($this->version);
+
+ $argNode = new Node();
+ $argNode->setString($str);
+
+ $defElem->setArg($argNode);
+
+ $node = new Node();
+ $node->setDefElem($defElem);
+
+ $stmt->setOptions([$node]);
+ }
+
+ return $stmt;
+ }
+
+ $stmt = new AlterExtensionContentsStmt();
+ $stmt->setExtname($this->name);
+ $stmt->setAction($this->action ?? 1);
+ $stmt->setObjtype($this->objtype ?? ObjectType::OBJECT_TABLE);
+
+ if ($this->objectName !== null) {
+ $identifier = QualifiedIdentifier::parse($this->objectName);
+
+ if ($this->objtype === ObjectType::OBJECT_FUNCTION) {
+ $objectWithArgs = new ObjectWithArgs();
+
+ $nameNodes = [];
+
+ foreach ($identifier->parts() as $part) {
+ $str = new PBString();
+ $str->setSval($part);
+ $node = new Node();
+ $node->setString($str);
+ $nameNodes[] = $node;
+ }
+
+ $objectWithArgs->setObjname($nameNodes);
+ $objectWithArgs->setArgsUnspecified(true);
+
+ $objectNode = new Node();
+ $objectNode->setObjectWithArgs($objectWithArgs);
+
+ $stmt->setObject($objectNode);
+ } else {
+ $nameNodes = [];
+
+ foreach ($identifier->parts() as $part) {
+ $str = new PBString();
+ $str->setSval($part);
+ $node = new Node();
+ $node->setString($str);
+ $nameNodes[] = $node;
+ }
+
+ $list = new PBList();
+ $list->setItems($nameNodes);
+
+ $objectNode = new Node();
+ $objectNode->setList($list);
+
+ $stmt->setObject($objectNode);
+ }
+ }
+
+ return $stmt;
+ }
+
+ public function update() : AlterExtensionFinalStep
+ {
+ return new self(
+ $this->name,
+ true,
+ null,
+ null,
+ null,
+ null,
+ );
+ }
+
+ public function updateTo(string $version) : AlterExtensionFinalStep
+ {
+ return new self(
+ $this->name,
+ true,
+ $version,
+ null,
+ null,
+ null,
+ );
+ }
+}
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
new file mode 100644
index 000000000..ff86e793f
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Extension/AlterExtensionFinalStep.php
@@ -0,0 +1,14 @@
+ $options
+ */
+ private function __construct(
+ private string $name,
+ private bool $ifNotExists = false,
+ private array $options = [],
+ ) {
+ }
+
+ public static function create(string $name) : CreateExtensionOptionsStep
+ {
+ return new self($name);
+ }
+
+ public function cascade() : CreateExtensionOptionsStep
+ {
+ return $this->withBooleanOption('cascade', true);
+ }
+
+ public function ifNotExists() : CreateExtensionOptionsStep
+ {
+ return new self(
+ $this->name,
+ true,
+ $this->options,
+ );
+ }
+
+ public function schema(string $schema) : CreateExtensionOptionsStep
+ {
+ return $this->withStringOption('schema', $schema);
+ }
+
+ public function toAst() : CreateExtensionStmt
+ {
+ $stmt = new CreateExtensionStmt();
+ $stmt->setExtname($this->name);
+ $stmt->setIfNotExists($this->ifNotExists);
+
+ $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;
+ }
+
+ public function version(string $version) : CreateExtensionOptionsStep
+ {
+ return $this->withStringOption('new_version', $version);
+ }
+
+ private function withBooleanOption(string $name, bool $value) : self
+ {
+ $integer = new Integer();
+ $integer->setIval($value ? 1 : 0);
+
+ $argNode = new Node();
+ /** @phpstan-ignore argument.type (protobuf PHPDoc says int but actually expects Integer) */
+ $argNode->setInteger($integer);
+
+ return $this->withOption($name, $argNode);
+ }
+
+ private function withOption(string $name, ?Node $arg) : self
+ {
+ $newOptions = $this->options;
+ $newOptions[] = ['name' => $name, 'arg' => $arg];
+
+ return new self(
+ $this->name,
+ $this->ifNotExists,
+ $newOptions,
+ );
+ }
+
+ private function withStringOption(string $name, string $value) : self
+ {
+ $str = new PBString();
+ $str->setSval($value);
+
+ $argNode = new Node();
+ $argNode->setString($str);
+
+ return $this->withOption($name, $argNode);
+ }
+}
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
new file mode 100644
index 000000000..3780a64bc
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Extension/CreateExtensionFinalStep.php
@@ -0,0 +1,14 @@
+ $names
+ */
+ private function __construct(
+ private array $names,
+ private bool $ifExists = false,
+ private int $behavior = DropBehavior::DROP_RESTRICT,
+ ) {
+ }
+
+ public static function create(string ...$names) : DropExtensionFinalStep
+ {
+ return new self(\array_values($names));
+ }
+
+ public function cascade() : DropExtensionFinalStep
+ {
+ return new self(
+ $this->names,
+ $this->ifExists,
+ DropBehavior::DROP_CASCADE,
+ );
+ }
+
+ public function ifExists() : DropExtensionFinalStep
+ {
+ return new self(
+ $this->names,
+ true,
+ $this->behavior,
+ );
+ }
+
+ public function restrict() : DropExtensionFinalStep
+ {
+ return new self(
+ $this->names,
+ $this->ifExists,
+ DropBehavior::DROP_RESTRICT,
+ );
+ }
+
+ public function toAst() : DropStmt
+ {
+ $stmt = new DropStmt();
+ $stmt->setRemoveType(ObjectType::OBJECT_EXTENSION);
+ $stmt->setBehavior($this->behavior);
+ $stmt->setMissingOk($this->ifExists);
+
+ $objects = [];
+
+ foreach ($this->names as $name) {
+ $str = new PBString();
+ $str->setSval($name);
+ $node = new Node();
+ $node->setString($str);
+ $objects[] = $node;
+ }
+
+ $stmt->setObjects($objects);
+
+ return $stmt;
+ }
+}
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
new file mode 100644
index 000000000..bddcc6541
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Extension/DropExtensionFinalStep.php
@@ -0,0 +1,20 @@
+ $arguments
+ * @param list $actions
+ */
+ private function __construct(
+ private string $name,
+ private array $arguments = [],
+ private array $actions = [],
+ private ?string $renameTo = null,
+ ) {
+ }
+
+ public static function create(string $name) : AlterFunctionArgsStep
+ {
+ return new self($name);
+ }
+
+ public function arguments(FunctionArgument ...$args) : AlterFunctionFinalStep
+ {
+ return new self(
+ $this->name,
+ \array_values($args),
+ $this->actions,
+ $this->renameTo,
+ );
+ }
+
+ public function cost(int $cost) : AlterFunctionFinalStep
+ {
+ return $this->withIntegerOption('cost', $cost);
+ }
+
+ public function immutable() : AlterFunctionFinalStep
+ {
+ return $this->withStringOption('volatility', 'immutable');
+ }
+
+ public function parallel(ParallelSafety $safety) : AlterFunctionFinalStep
+ {
+ return $this->withStringOption('parallel', $safety->value);
+ }
+
+ public function renameTo(string $newName) : AlterFunctionFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->arguments,
+ $this->actions,
+ $newName,
+ );
+ }
+
+ public function reset(string $parameter) : AlterFunctionFinalStep
+ {
+ $defElem = new DefElem();
+ $defElem->setDefname($parameter);
+
+ $node = new Node();
+ $node->setDefElem($defElem);
+
+ return $this->withAction('reset', $node);
+ }
+
+ public function resetAll() : AlterFunctionFinalStep
+ {
+ return $this->withAction('resetall', null);
+ }
+
+ public function rows(int $rows) : AlterFunctionFinalStep
+ {
+ return $this->withIntegerOption('rows', $rows);
+ }
+
+ public function set(string $parameter, string $value) : AlterFunctionFinalStep
+ {
+ $defElem = new DefElem();
+ $defElem->setDefname($parameter);
+
+ $str = new PBString();
+ $str->setSval($value);
+
+ $aConst = new A_Const();
+ $aConst->setSval($str);
+
+ $argNode = new Node();
+ $argNode->setAConst($aConst);
+
+ $defElem->setArg($argNode);
+
+ $node = new Node();
+ $node->setDefElem($defElem);
+
+ return $this->withAction('set', $node);
+ }
+
+ public function stable() : AlterFunctionFinalStep
+ {
+ return $this->withStringOption('volatility', 'stable');
+ }
+
+ public function toAst() : AlterFunctionStmt|RenameStmt
+ {
+ if ($this->renameTo !== null && $this->actions !== []) {
+ throw InvalidBuilderStateException::mutuallyExclusiveOptions('RENAME TO', 'other alterations');
+ }
+
+ if ($this->renameTo !== null) {
+ return $this->buildRenameAst();
+ }
+
+ return $this->buildAlterAst();
+ }
+
+ public function volatile() : AlterFunctionFinalStep
+ {
+ return $this->withStringOption('volatility', 'volatile');
+ }
+
+ private function buildAlterAst() : AlterFunctionStmt
+ {
+ $stmt = new AlterFunctionStmt();
+ $stmt->setObjtype(ObjectType::OBJECT_FUNCTION);
+
+ $objectWithArgs = new ObjectWithArgs();
+
+ $objnameNodes = [];
+ $str = new PBString();
+ $str->setSval($this->name);
+ $node = new Node();
+ $node->setString($str);
+ $objnameNodes[] = $node;
+ $objectWithArgs->setObjname($objnameNodes);
+
+ if ($this->arguments !== []) {
+ $argNodes = [];
+
+ foreach ($this->arguments as $arg) {
+ $node = new Node();
+ $node->setTypeName($arg->type->toAst());
+ $argNodes[] = $node;
+ }
+
+ $objectWithArgs->setObjargs($argNodes);
+ } else {
+ $objectWithArgs->setArgsUnspecified(true);
+ }
+
+ $stmt->setFunc($objectWithArgs);
+
+ $actionNodes = [];
+
+ foreach ($this->actions as $action) {
+ if ($action['arg'] !== null) {
+ $actionNodes[] = $action['arg'];
+ } else {
+ $defElem = new DefElem();
+ $defElem->setDefname($action['name']);
+
+ $node = new Node();
+ $node->setDefElem($defElem);
+ $actionNodes[] = $node;
+ }
+ }
+
+ if ($actionNodes !== []) {
+ $stmt->setActions($actionNodes);
+ }
+
+ return $stmt;
+ }
+
+ private function buildRenameAst() : RenameStmt
+ {
+ $stmt = new RenameStmt();
+ $stmt->setRenameType(ObjectType::OBJECT_FUNCTION);
+
+ $objectWithArgs = new ObjectWithArgs();
+
+ $objnameNodes = [];
+ $str = new PBString();
+ $str->setSval($this->name);
+ $node = new Node();
+ $node->setString($str);
+ $objnameNodes[] = $node;
+ $objectWithArgs->setObjname($objnameNodes);
+
+ if ($this->arguments !== []) {
+ $argNodes = [];
+
+ foreach ($this->arguments as $arg) {
+ $node = new Node();
+ $node->setTypeName($arg->type->toAst());
+ $argNodes[] = $node;
+ }
+
+ $objectWithArgs->setObjargs($argNodes);
+ } else {
+ $objectWithArgs->setArgsUnspecified(true);
+ }
+
+ $objectNode = new Node();
+ $objectNode->setObjectWithArgs($objectWithArgs);
+ $stmt->setObject($objectNode);
+
+ if ($this->renameTo !== null) {
+ $stmt->setNewname($this->renameTo);
+ }
+
+ return $stmt;
+ }
+
+ private function withAction(string $name, ?Node $arg) : self
+ {
+ $newActions = $this->actions;
+ $newActions[] = ['name' => $name, 'arg' => $arg];
+
+ return new self(
+ $this->name,
+ $this->arguments,
+ $newActions,
+ $this->renameTo,
+ );
+ }
+
+ private function withIntegerOption(string $name, int $value) : self
+ {
+ $integer = new Integer();
+ $integer->setIval($value);
+
+ $aConst = new A_Const();
+ /** @phpstan-ignore argument.type (protobuf PHPDoc says int but actually expects Integer) */
+ $aConst->setIval($integer);
+
+ $defElem = new DefElem();
+ $defElem->setDefname($name);
+
+ $argNode = new Node();
+ $argNode->setAConst($aConst);
+ $defElem->setArg($argNode);
+
+ $node = new Node();
+ $node->setDefElem($defElem);
+
+ return $this->withAction($name, $node);
+ }
+
+ private function withStringOption(string $name, string $value) : self
+ {
+ $str = new PBString();
+ $str->setSval($value);
+
+ $defElem = new DefElem();
+ $defElem->setDefname($name);
+
+ $argNode = new Node();
+ $argNode->setString($str);
+ $defElem->setArg($argNode);
+
+ $node = new Node();
+ $node->setDefElem($defElem);
+
+ return $this->withAction($name, $node);
+ }
+}
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
new file mode 100644
index 000000000..03f381e67
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/AlterFunctionFinalStep.php
@@ -0,0 +1,34 @@
+ $arguments
+ * @param list $actions
+ */
+ private function __construct(
+ private string $name,
+ private array $arguments = [],
+ private array $actions = [],
+ private ?string $renameTo = null,
+ ) {
+ }
+
+ public static function create(string $name) : AlterProcedureArgsStep
+ {
+ return new self($name);
+ }
+
+ public function arguments(FunctionArgument ...$args) : AlterProcedureFinalStep
+ {
+ return new self(
+ $this->name,
+ \array_values($args),
+ $this->actions,
+ $this->renameTo,
+ );
+ }
+
+ public function renameTo(string $newName) : AlterProcedureFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->arguments,
+ $this->actions,
+ $newName,
+ );
+ }
+
+ public function reset(string $parameter) : AlterProcedureFinalStep
+ {
+ $defElem = new DefElem();
+ $defElem->setDefname($parameter);
+
+ $node = new Node();
+ $node->setDefElem($defElem);
+
+ return $this->withAction('reset', $node);
+ }
+
+ public function resetAll() : AlterProcedureFinalStep
+ {
+ return $this->withAction('resetall', null);
+ }
+
+ public function securityDefiner() : AlterProcedureFinalStep
+ {
+ $integer = new Integer();
+ $integer->setIval(1);
+
+ $aConst = new A_Const();
+ /** @phpstan-ignore argument.type (protobuf PHPDoc says int but actually expects Integer) */
+ $aConst->setIval($integer);
+
+ $defElem = new DefElem();
+ $defElem->setDefname('security_definer');
+
+ $argNode = new Node();
+ $argNode->setAConst($aConst);
+ $defElem->setArg($argNode);
+
+ $node = new Node();
+ $node->setDefElem($defElem);
+
+ return $this->withAction('security_definer', $node);
+ }
+
+ public function securityInvoker() : AlterProcedureFinalStep
+ {
+ $integer = new Integer();
+ $integer->setIval(0);
+
+ $aConst = new A_Const();
+ /** @phpstan-ignore argument.type (protobuf PHPDoc says int but actually expects Integer) */
+ $aConst->setIval($integer);
+
+ $defElem = new DefElem();
+ $defElem->setDefname('security_definer');
+
+ $argNode = new Node();
+ $argNode->setAConst($aConst);
+ $defElem->setArg($argNode);
+
+ $node = new Node();
+ $node->setDefElem($defElem);
+
+ return $this->withAction('security_definer', $node);
+ }
+
+ public function set(string $parameter, string $value) : AlterProcedureFinalStep
+ {
+ $defElem = new DefElem();
+ $defElem->setDefname($parameter);
+
+ $str = new PBString();
+ $str->setSval($value);
+
+ $aConst = new A_Const();
+ $aConst->setSval($str);
+
+ $argNode = new Node();
+ $argNode->setAConst($aConst);
+
+ $defElem->setArg($argNode);
+
+ $node = new Node();
+ $node->setDefElem($defElem);
+
+ return $this->withAction('set', $node);
+ }
+
+ public function toAst() : AlterFunctionStmt|RenameStmt
+ {
+ if ($this->renameTo !== null && $this->actions !== []) {
+ throw InvalidBuilderStateException::mutuallyExclusiveOptions('RENAME TO', 'other alterations');
+ }
+
+ if ($this->renameTo !== null) {
+ return $this->buildRenameAst();
+ }
+
+ return $this->buildAlterAst();
+ }
+
+ private function buildAlterAst() : AlterFunctionStmt
+ {
+ $stmt = new AlterFunctionStmt();
+ $stmt->setObjtype(ObjectType::OBJECT_PROCEDURE);
+
+ $objectWithArgs = new ObjectWithArgs();
+
+ $objnameNodes = [];
+ $str = new PBString();
+ $str->setSval($this->name);
+ $node = new Node();
+ $node->setString($str);
+ $objnameNodes[] = $node;
+ $objectWithArgs->setObjname($objnameNodes);
+
+ if ($this->arguments !== []) {
+ $argNodes = [];
+
+ foreach ($this->arguments as $arg) {
+ $node = new Node();
+ $node->setTypeName($arg->type->toAst());
+ $argNodes[] = $node;
+ }
+
+ $objectWithArgs->setObjargs($argNodes);
+ } else {
+ $objectWithArgs->setArgsUnspecified(true);
+ }
+
+ $stmt->setFunc($objectWithArgs);
+
+ $actionNodes = [];
+
+ foreach ($this->actions as $action) {
+ if ($action['arg'] !== null) {
+ $actionNodes[] = $action['arg'];
+ } else {
+ $defElem = new DefElem();
+ $defElem->setDefname($action['name']);
+
+ $node = new Node();
+ $node->setDefElem($defElem);
+ $actionNodes[] = $node;
+ }
+ }
+
+ if ($actionNodes !== []) {
+ $stmt->setActions($actionNodes);
+ }
+
+ return $stmt;
+ }
+
+ private function buildRenameAst() : RenameStmt
+ {
+ $stmt = new RenameStmt();
+ $stmt->setRenameType(ObjectType::OBJECT_PROCEDURE);
+
+ $objectWithArgs = new ObjectWithArgs();
+
+ $objnameNodes = [];
+ $str = new PBString();
+ $str->setSval($this->name);
+ $node = new Node();
+ $node->setString($str);
+ $objnameNodes[] = $node;
+ $objectWithArgs->setObjname($objnameNodes);
+
+ if ($this->arguments !== []) {
+ $argNodes = [];
+
+ foreach ($this->arguments as $arg) {
+ $node = new Node();
+ $node->setTypeName($arg->type->toAst());
+ $argNodes[] = $node;
+ }
+
+ $objectWithArgs->setObjargs($argNodes);
+ } else {
+ $objectWithArgs->setArgsUnspecified(true);
+ }
+
+ $objectNode = new Node();
+ $objectNode->setObjectWithArgs($objectWithArgs);
+ $stmt->setObject($objectNode);
+
+ if ($this->renameTo !== null) {
+ $stmt->setNewname($this->renameTo);
+ }
+
+ return $stmt;
+ }
+
+ private function withAction(string $name, ?Node $arg) : self
+ {
+ $newActions = $this->actions;
+ $newActions[] = ['name' => $name, 'arg' => $arg];
+
+ return new self(
+ $this->name,
+ $this->arguments,
+ $newActions,
+ $this->renameTo,
+ );
+ }
+}
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
new file mode 100644
index 000000000..4c506cc24
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/AlterProcedureFinalStep.php
@@ -0,0 +1,26 @@
+ $arguments
+ */
+ private function __construct(
+ private string $procedure,
+ private array $arguments = [],
+ ) {
+ }
+
+ public static function create(string $procedure) : CallFinalStep
+ {
+ return new self($procedure);
+ }
+
+ public function toAst() : CallStmt
+ {
+ $stmt = new CallStmt();
+
+ $funcCall = new FuncCall();
+
+ $funcnameNodes = [];
+ $str = new PBString();
+ $str->setSval($this->procedure);
+ $node = new Node();
+ $node->setString($str);
+ $funcnameNodes[] = $node;
+ $funcCall->setFuncname($funcnameNodes);
+
+ if ($this->arguments !== []) {
+ $funcCall->setArgs($this->arguments);
+ }
+
+ $stmt->setFunccall($funcCall);
+
+ return $stmt;
+ }
+
+ public function with(mixed ...$args) : CallFinalStep
+ {
+ $argNodes = [];
+
+ foreach ($args as $arg) {
+ if ($arg instanceof Node) {
+ $argNodes[] = $arg;
+ } elseif (\is_int($arg)) {
+ $argNodes[] = $this->createIntegerNode($arg);
+ } elseif (\is_string($arg)) {
+ $argNodes[] = $this->createStringNode($arg);
+ } elseif (\is_bool($arg)) {
+ $argNodes[] = $this->createBoolNode($arg);
+ } elseif (\is_float($arg)) {
+ $argNodes[] = $this->createFloatNode($arg);
+ } elseif ($arg === null) {
+ $argNodes[] = $this->createNullNode();
+ }
+ }
+
+ return new self(
+ $this->procedure,
+ \array_merge($this->arguments, $argNodes),
+ );
+ }
+
+ private function createBoolNode(bool $value) : Node
+ {
+ $boolean = new Boolean();
+ $boolean->setBoolval($value);
+
+ $aConst = new A_Const();
+ /** @phpstan-ignore argument.type (protobuf PHPDoc says bool but actually expects Boolean) */
+ $aConst->setBoolval($boolean);
+
+ $node = new Node();
+ $node->setAConst($aConst);
+
+ return $node;
+ }
+
+ private function createFloatNode(float $value) : Node
+ {
+ $float = new PBFloat();
+ $float->setFval((string) $value);
+
+ $aConst = new A_Const();
+ $aConst->setFval($float);
+
+ $node = new Node();
+ $node->setAConst($aConst);
+
+ return $node;
+ }
+
+ private function createIntegerNode(int $value) : Node
+ {
+ $integer = new Integer();
+ $integer->setIval($value);
+
+ $aConst = new A_Const();
+ /** @phpstan-ignore argument.type (protobuf PHPDoc says int but actually expects Integer) */
+ $aConst->setIval($integer);
+
+ $node = new Node();
+ $node->setAConst($aConst);
+
+ return $node;
+ }
+
+ private function createNullNode() : Node
+ {
+ $aConst = new A_Const();
+ $aConst->setIsnull(true);
+
+ $node = new Node();
+ $node->setAConst($aConst);
+
+ return $node;
+ }
+
+ private function createStringNode(string $value) : Node
+ {
+ $str = new PBString();
+ $str->setSval($value);
+
+ $aConst = new A_Const();
+ $aConst->setSval($str);
+
+ $node = new Node();
+ $node->setAConst($aConst);
+
+ return $node;
+ }
+}
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
new file mode 100644
index 000000000..53c65bda1
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/CallFinalStep.php
@@ -0,0 +1,16 @@
+ $arguments
+ * @param list $options
+ * @param null|array $tableColumns
+ */
+ private function __construct(
+ private string $name,
+ private bool $replace = false,
+ private array $arguments = [],
+ private ?DataType $returnType = null,
+ private bool $setof = false,
+ private ?array $tableColumns = null,
+ private array $options = [],
+ ) {
+ }
+
+ public static function create(string $name) : CreateFunctionArgsStep
+ {
+ return new self($name);
+ }
+
+ public function arguments(FunctionArgument ...$args) : CreateFunctionReturnsStep
+ {
+ return new self(
+ $this->name,
+ $this->replace,
+ \array_values($args),
+ $this->returnType,
+ $this->setof,
+ $this->tableColumns,
+ $this->options,
+ );
+ }
+
+ public function as(string $definition) : CreateFunctionFinalStep
+ {
+ return $this->withListOption('as', $definition);
+ }
+
+ public function calledOnNullInput() : CreateFunctionOptionsStep
+ {
+ return $this->withBooleanOption('strict', false);
+ }
+
+ public function cost(int $cost) : CreateFunctionOptionsStep
+ {
+ return $this->withIntegerOption('cost', $cost);
+ }
+
+ public function immutable() : CreateFunctionOptionsStep
+ {
+ return $this->withStringOption('volatility', 'immutable');
+ }
+
+ public function language(string $language) : CreateFunctionOptionsStep
+ {
+ return $this->withStringOption('language', $language);
+ }
+
+ public function leakproof(bool $value = true) : CreateFunctionOptionsStep
+ {
+ return $this->withBooleanOption('leakproof', $value);
+ }
+
+ public function orReplace() : CreateFunctionArgsStep
+ {
+ return new self(
+ $this->name,
+ true,
+ $this->arguments,
+ $this->returnType,
+ $this->setof,
+ $this->tableColumns,
+ $this->options,
+ );
+ }
+
+ public function parallel(ParallelSafety $safety) : CreateFunctionOptionsStep
+ {
+ return $this->withStringOption('parallel', $safety->value);
+ }
+
+ public function returns(DataType $type) : CreateFunctionOptionsStep
+ {
+ return new self(
+ $this->name,
+ $this->replace,
+ $this->arguments,
+ $type,
+ false,
+ null,
+ $this->options,
+ );
+ }
+
+ public function returnsSetOf(DataType $type) : CreateFunctionOptionsStep
+ {
+ return new self(
+ $this->name,
+ $this->replace,
+ $this->arguments,
+ $type,
+ true,
+ null,
+ $this->options,
+ );
+ }
+
+ /**
+ * @param array $columns
+ */
+ public function returnsTable(array $columns) : CreateFunctionOptionsStep
+ {
+ return new self(
+ $this->name,
+ $this->replace,
+ $this->arguments,
+ null,
+ false,
+ $columns,
+ $this->options,
+ );
+ }
+
+ public function returnsVoid() : CreateFunctionOptionsStep
+ {
+ return new self(
+ $this->name,
+ $this->replace,
+ $this->arguments,
+ DataType::custom('void'),
+ false,
+ null,
+ $this->options,
+ );
+ }
+
+ public function rows(int $rows) : CreateFunctionOptionsStep
+ {
+ return $this->withIntegerOption('rows', $rows);
+ }
+
+ public function securityDefiner() : CreateFunctionOptionsStep
+ {
+ return $this->withBooleanOption('security_definer', true);
+ }
+
+ public function securityInvoker() : CreateFunctionOptionsStep
+ {
+ return $this->withBooleanOption('security_definer', false);
+ }
+
+ public function set(string $parameter, string $value) : CreateFunctionOptionsStep
+ {
+ $defElem = new DefElem();
+ $defElem->setDefname($parameter);
+
+ $str = new PBString();
+ $str->setSval($value);
+
+ $aConst = new A_Const();
+ $aConst->setSval($str);
+
+ $argNode = new Node();
+ $argNode->setAConst($aConst);
+
+ $defElem->setArg($argNode);
+
+ $setNode = new Node();
+ $setNode->setDefElem($defElem);
+
+ $newOptions = $this->options;
+ $newOptions[] = ['name' => 'set', 'arg' => $setNode];
+
+ return new self(
+ $this->name,
+ $this->replace,
+ $this->arguments,
+ $this->returnType,
+ $this->setof,
+ $this->tableColumns,
+ $newOptions,
+ );
+ }
+
+ public function stable() : CreateFunctionOptionsStep
+ {
+ return $this->withStringOption('volatility', 'stable');
+ }
+
+ public function strict() : CreateFunctionOptionsStep
+ {
+ return $this->withBooleanOption('strict', true);
+ }
+
+ public function toAst() : CreateFunctionStmt
+ {
+ $stmt = new CreateFunctionStmt();
+ $stmt->setIsProcedure(false);
+ $stmt->setReplace($this->replace);
+
+ $funcnameNodes = [];
+ $str = new PBString();
+ $str->setSval($this->name);
+ $node = new Node();
+ $node->setString($str);
+ $funcnameNodes[] = $node;
+ $stmt->setFuncname($funcnameNodes);
+
+ if ($this->arguments !== []) {
+ $parameterNodes = [];
+
+ foreach ($this->arguments as $arg) {
+ $param = new FunctionParameter();
+
+ if ($arg->name !== null) {
+ $param->setName($arg->name);
+ }
+
+ $param->setMode($arg->mode->value);
+ $param->setArgType($arg->type->toAst());
+
+ if ($arg->default !== null) {
+ $param->setDefexpr($this->createDefaultExpr($arg->default));
+ }
+
+ $node = new Node();
+ $node->setFunctionParameter($param);
+ $parameterNodes[] = $node;
+ }
+
+ $stmt->setParameters($parameterNodes);
+ }
+
+ if ($this->returnType !== null) {
+ $typeName = $this->returnType->toAst();
+
+ if ($this->setof) {
+ $typeName->setSetof(true);
+ }
+
+ $stmt->setReturnType($typeName);
+ } elseif ($this->tableColumns !== null) {
+ $parameterNodes = [];
+
+ foreach ($this->tableColumns as $columnName => $columnType) {
+ $param = new FunctionParameter();
+ $param->setName($columnName);
+ $param->setMode(FunctionParameterMode::FUNC_PARAM_TABLE);
+ $param->setArgType($columnType->toAst());
+
+ $node = new Node();
+ $node->setFunctionParameter($param);
+ $parameterNodes[] = $node;
+ }
+
+ $currentParams = [];
+
+ foreach ($stmt->getParameters() as $existingParam) {
+ $currentParams[] = $existingParam;
+ }
+
+ $stmt->setParameters(\array_merge($currentParams, $parameterNodes));
+ }
+
+ $optionNodes = [];
+
+ foreach ($this->options as $option) {
+ if ($option['name'] === 'set' && $option['arg'] !== null) {
+ $optionNodes[] = $option['arg'];
+ } else {
+ $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;
+ }
+
+ public function volatile() : CreateFunctionOptionsStep
+ {
+ return $this->withStringOption('volatility', 'volatile');
+ }
+
+ private function createDefaultExpr(string $default) : Node
+ {
+ $str = new PBString();
+ $str->setSval($default);
+
+ $aConst = new A_Const();
+ $aConst->setSval($str);
+
+ $node = new Node();
+ $node->setAConst($aConst);
+
+ return $node;
+ }
+
+ private function withBooleanOption(string $name, bool $value) : self
+ {
+ $integer = new Integer();
+ $integer->setIval($value ? 1 : 0);
+
+ $argNode = new Node();
+ /** @phpstan-ignore argument.type (protobuf PHPDoc says int but actually expects Integer) */
+ $argNode->setInteger($integer);
+
+ return $this->withOption($name, $argNode);
+ }
+
+ private function withIntegerOption(string $name, int $value) : self
+ {
+ $integer = new Integer();
+ $integer->setIval($value);
+
+ $aConst = new A_Const();
+ /** @phpstan-ignore argument.type (protobuf PHPDoc says int but actually expects Integer) */
+ $aConst->setIval($integer);
+
+ $argNode = new Node();
+ $argNode->setAConst($aConst);
+
+ return $this->withOption($name, $argNode);
+ }
+
+ private function withListOption(string $name, string $value) : self
+ {
+ $str = new PBString();
+ $str->setSval($value);
+
+ $itemNode = new Node();
+ $itemNode->setString($str);
+
+ $list = new PBList();
+ $list->setItems([$itemNode]);
+
+ $argNode = new Node();
+ $argNode->setList($list);
+
+ return $this->withOption($name, $argNode);
+ }
+
+ private function withOption(string $name, ?Node $arg) : self
+ {
+ $newOptions = $this->options;
+ $newOptions[] = ['name' => $name, 'arg' => $arg];
+
+ return new self(
+ $this->name,
+ $this->replace,
+ $this->arguments,
+ $this->returnType,
+ $this->setof,
+ $this->tableColumns,
+ $newOptions,
+ );
+ }
+
+ private function withStringOption(string $name, string $value) : self
+ {
+ $str = new PBString();
+ $str->setSval($value);
+
+ $argNode = new Node();
+ $argNode->setString($str);
+
+ return $this->withOption($name, $argNode);
+ }
+}
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
new file mode 100644
index 000000000..15511d24d
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/CreateFunctionFinalStep.php
@@ -0,0 +1,14 @@
+ $columns
+ */
+ public function returnsTable(array $columns) : CreateFunctionOptionsStep;
+
+ public function returnsVoid() : CreateFunctionOptionsStep;
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/CreateProcedureArgsStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/CreateProcedureArgsStep.php
new file mode 100644
index 000000000..f3395b9f2
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/CreateProcedureArgsStep.php
@@ -0,0 +1,12 @@
+ $arguments
+ * @param list $options
+ */
+ private function __construct(
+ private string $name,
+ private bool $replace = false,
+ private array $arguments = [],
+ private array $options = [],
+ ) {
+ }
+
+ public static function create(string $name) : CreateProcedureArgsStep
+ {
+ return new self($name);
+ }
+
+ public function arguments(FunctionArgument ...$args) : CreateProcedureOptionsStep
+ {
+ return new self(
+ $this->name,
+ $this->replace,
+ \array_values($args),
+ $this->options,
+ );
+ }
+
+ public function as(string $definition) : CreateProcedureFinalStep
+ {
+ return $this->withListOption('as', $definition);
+ }
+
+ public function language(string $language) : CreateProcedureOptionsStep
+ {
+ return $this->withStringOption('language', $language);
+ }
+
+ public function orReplace() : CreateProcedureArgsStep
+ {
+ return new self(
+ $this->name,
+ true,
+ $this->arguments,
+ $this->options,
+ );
+ }
+
+ public function securityDefiner() : CreateProcedureOptionsStep
+ {
+ $integer = new Integer();
+ $integer->setIval(1);
+
+ $argNode = new Node();
+ /** @phpstan-ignore argument.type (protobuf PHPDoc says int but actually expects Integer) */
+ $argNode->setInteger($integer);
+
+ return $this->withOption('security_definer', $argNode);
+ }
+
+ public function securityInvoker() : CreateProcedureOptionsStep
+ {
+ $integer = new Integer();
+ $integer->setIval(0);
+
+ $argNode = new Node();
+ /** @phpstan-ignore argument.type (protobuf PHPDoc says int but actually expects Integer) */
+ $argNode->setInteger($integer);
+
+ return $this->withOption('security_definer', $argNode);
+ }
+
+ public function set(string $parameter, string $value) : CreateProcedureOptionsStep
+ {
+ $defElem = new DefElem();
+ $defElem->setDefname($parameter);
+
+ $str = new PBString();
+ $str->setSval($value);
+
+ $aConst = new A_Const();
+ $aConst->setSval($str);
+
+ $argNode = new Node();
+ $argNode->setAConst($aConst);
+
+ $defElem->setArg($argNode);
+
+ $setNode = new Node();
+ $setNode->setDefElem($defElem);
+
+ $newOptions = $this->options;
+ $newOptions[] = ['name' => 'set', 'arg' => $setNode];
+
+ return new self(
+ $this->name,
+ $this->replace,
+ $this->arguments,
+ $newOptions,
+ );
+ }
+
+ public function toAst() : CreateFunctionStmt
+ {
+ $stmt = new CreateFunctionStmt();
+ $stmt->setIsProcedure(true);
+ $stmt->setReplace($this->replace);
+
+ $funcnameNodes = [];
+ $str = new PBString();
+ $str->setSval($this->name);
+ $node = new Node();
+ $node->setString($str);
+ $funcnameNodes[] = $node;
+ $stmt->setFuncname($funcnameNodes);
+
+ if ($this->arguments !== []) {
+ $parameterNodes = [];
+
+ foreach ($this->arguments as $arg) {
+ $param = new FunctionParameter();
+
+ if ($arg->name !== null) {
+ $param->setName($arg->name);
+ }
+
+ $param->setMode($arg->mode->value);
+ $param->setArgType($arg->type->toAst());
+
+ if ($arg->default !== null) {
+ $param->setDefexpr($this->createDefaultExpr($arg->default));
+ }
+
+ $node = new Node();
+ $node->setFunctionParameter($param);
+ $parameterNodes[] = $node;
+ }
+
+ $stmt->setParameters($parameterNodes);
+ }
+
+ $optionNodes = [];
+
+ foreach ($this->options as $option) {
+ if ($option['name'] === 'set' && $option['arg'] !== null) {
+ $optionNodes[] = $option['arg'];
+ } else {
+ $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 createDefaultExpr(string $default) : Node
+ {
+ $str = new PBString();
+ $str->setSval($default);
+
+ $aConst = new A_Const();
+ $aConst->setSval($str);
+
+ $node = new Node();
+ $node->setAConst($aConst);
+
+ return $node;
+ }
+
+ private function withListOption(string $name, string $value) : self
+ {
+ $str = new PBString();
+ $str->setSval($value);
+
+ $itemNode = new Node();
+ $itemNode->setString($str);
+
+ $list = new PBList();
+ $list->setItems([$itemNode]);
+
+ $argNode = new Node();
+ $argNode->setList($list);
+
+ return $this->withOption($name, $argNode);
+ }
+
+ private function withOption(string $name, ?Node $arg) : self
+ {
+ $newOptions = $this->options;
+ $newOptions[] = ['name' => $name, 'arg' => $arg];
+
+ return new self(
+ $this->name,
+ $this->replace,
+ $this->arguments,
+ $newOptions,
+ );
+ }
+
+ private function withStringOption(string $name, string $value) : self
+ {
+ $str = new PBString();
+ $str->setSval($value);
+
+ $argNode = new Node();
+ $argNode->setString($str);
+
+ return $this->withOption($name, $argNode);
+ }
+}
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
new file mode 100644
index 000000000..45d404864
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/CreateProcedureFinalStep.php
@@ -0,0 +1,14 @@
+code,
+ $language,
+ );
+ }
+
+ public function toAst() : DoStmt
+ {
+ $stmt = new DoStmt();
+
+ $args = [];
+
+ $asDefElem = new DefElem();
+ $asDefElem->setDefname('as');
+
+ $codeStr = new PBString();
+ $codeStr->setSval($this->code);
+ $codeNode = new Node();
+ $codeNode->setString($codeStr);
+ $asDefElem->setArg($codeNode);
+
+ $asNode = new Node();
+ $asNode->setDefElem($asDefElem);
+ $args[] = $asNode;
+
+ $langDefElem = new DefElem();
+ $langDefElem->setDefname('language');
+
+ $langStr = new PBString();
+ $langStr->setSval($this->language);
+ $langNode = new Node();
+ $langNode->setString($langStr);
+ $langDefElem->setArg($langNode);
+
+ $langNodeWrapper = new Node();
+ $langNodeWrapper->setDefElem($langDefElem);
+ $args[] = $langNodeWrapper;
+
+ $stmt->setArgs($args);
+
+ return $stmt;
+ }
+}
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
new file mode 100644
index 000000000..218be745b
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/DoFinalStep.php
@@ -0,0 +1,16 @@
+ $arguments
+ */
+ private function __construct(
+ private string $name,
+ private array $arguments = [],
+ private bool $ifExists = false,
+ private int $behavior = DropBehavior::DROP_BEHAVIOR_UNDEFINED,
+ ) {
+ }
+
+ public static function create(string $name) : DropFunctionFinalStep
+ {
+ return new self($name);
+ }
+
+ public function arguments(FunctionArgument ...$args) : DropFunctionFinalStep
+ {
+ return new self(
+ $this->name,
+ \array_values($args),
+ $this->ifExists,
+ $this->behavior,
+ );
+ }
+
+ public function cascade() : DropFunctionFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->arguments,
+ $this->ifExists,
+ DropBehavior::DROP_CASCADE,
+ );
+ }
+
+ public function ifExists() : DropFunctionFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->arguments,
+ true,
+ $this->behavior,
+ );
+ }
+
+ public function restrict() : DropFunctionFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->arguments,
+ $this->ifExists,
+ DropBehavior::DROP_RESTRICT,
+ );
+ }
+
+ public function toAst() : DropStmt
+ {
+ $stmt = new DropStmt();
+ $stmt->setRemoveType(ObjectType::OBJECT_FUNCTION);
+
+ if ($this->ifExists) {
+ $stmt->setMissingOk(true);
+ }
+
+ if ($this->behavior !== DropBehavior::DROP_BEHAVIOR_UNDEFINED) {
+ $stmt->setBehavior($this->behavior);
+ }
+
+ $objectWithArgs = new ObjectWithArgs();
+
+ $objnameNodes = [];
+ $str = new PBString();
+ $str->setSval($this->name);
+ $node = new Node();
+ $node->setString($str);
+ $objnameNodes[] = $node;
+ $objectWithArgs->setObjname($objnameNodes);
+
+ if ($this->arguments !== []) {
+ $argNodes = [];
+
+ foreach ($this->arguments as $arg) {
+ $node = new Node();
+ $node->setTypeName($arg->type->toAst());
+ $argNodes[] = $node;
+ }
+
+ $objectWithArgs->setObjargs($argNodes);
+ } else {
+ $objectWithArgs->setArgsUnspecified(true);
+ }
+
+ $objectNode = new Node();
+ $objectNode->setObjectWithArgs($objectWithArgs);
+
+ $stmt->setObjects([$objectNode]);
+
+ return $stmt;
+ }
+}
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
new file mode 100644
index 000000000..99f2dd753
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/DropFunctionFinalStep.php
@@ -0,0 +1,22 @@
+ $arguments
+ */
+ private function __construct(
+ private string $name,
+ private array $arguments = [],
+ private bool $ifExists = false,
+ private int $behavior = DropBehavior::DROP_BEHAVIOR_UNDEFINED,
+ ) {
+ }
+
+ public static function create(string $name) : DropProcedureFinalStep
+ {
+ return new self($name);
+ }
+
+ public function arguments(FunctionArgument ...$args) : DropProcedureFinalStep
+ {
+ return new self(
+ $this->name,
+ \array_values($args),
+ $this->ifExists,
+ $this->behavior,
+ );
+ }
+
+ public function cascade() : DropProcedureFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->arguments,
+ $this->ifExists,
+ DropBehavior::DROP_CASCADE,
+ );
+ }
+
+ public function ifExists() : DropProcedureFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->arguments,
+ true,
+ $this->behavior,
+ );
+ }
+
+ public function restrict() : DropProcedureFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->arguments,
+ $this->ifExists,
+ DropBehavior::DROP_RESTRICT,
+ );
+ }
+
+ public function toAst() : DropStmt
+ {
+ $stmt = new DropStmt();
+ $stmt->setRemoveType(ObjectType::OBJECT_PROCEDURE);
+
+ if ($this->ifExists) {
+ $stmt->setMissingOk(true);
+ }
+
+ if ($this->behavior !== DropBehavior::DROP_BEHAVIOR_UNDEFINED) {
+ $stmt->setBehavior($this->behavior);
+ }
+
+ $objectWithArgs = new ObjectWithArgs();
+
+ $objnameNodes = [];
+ $str = new PBString();
+ $str->setSval($this->name);
+ $node = new Node();
+ $node->setString($str);
+ $objnameNodes[] = $node;
+ $objectWithArgs->setObjname($objnameNodes);
+
+ if ($this->arguments !== []) {
+ $argNodes = [];
+
+ foreach ($this->arguments as $arg) {
+ $node = new Node();
+ $node->setTypeName($arg->type->toAst());
+ $argNodes[] = $node;
+ }
+
+ $objectWithArgs->setObjargs($argNodes);
+ } else {
+ $objectWithArgs->setArgsUnspecified(true);
+ }
+
+ $objectNode = new Node();
+ $objectNode->setObjectWithArgs($objectWithArgs);
+
+ $stmt->setObjects([$objectNode]);
+
+ return $stmt;
+ }
+}
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
new file mode 100644
index 000000000..bbe709bd9
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/DropProcedureFinalStep.php
@@ -0,0 +1,22 @@
+type,
+ $this->name,
+ $this->mode,
+ $value,
+ );
+ }
+
+ public function in() : self
+ {
+ return new self(
+ $this->type,
+ $this->name,
+ ArgumentMode::IN,
+ $this->default,
+ );
+ }
+
+ public function inout() : self
+ {
+ return new self(
+ $this->type,
+ $this->name,
+ ArgumentMode::INOUT,
+ $this->default,
+ );
+ }
+
+ public function named(string $name) : self
+ {
+ return new self(
+ $this->type,
+ $name,
+ $this->mode,
+ $this->default,
+ );
+ }
+
+ public function out() : self
+ {
+ return new self(
+ $this->type,
+ $this->name,
+ ArgumentMode::OUT,
+ $this->default,
+ );
+ }
+
+ public function variadic() : self
+ {
+ return new self(
+ $this->type,
+ $this->name,
+ ArgumentMode::VARIADIC,
+ $this->default,
+ );
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/FunctionVolatility.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/FunctionVolatility.php
new file mode 100644
index 000000000..65c76624b
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Function/FunctionVolatility.php
@@ -0,0 +1,12 @@
+ $privileges
+ * @param list $objects
+ * @param list $grantees
+ */
+ private function __construct(
+ private array $privileges,
+ private int $targetType = GrantTargetType::ACL_TARGET_OBJECT,
+ private int $objectType = ObjectType::OBJECT_TABLE,
+ private array $objects = [],
+ private array $grantees = [],
+ private bool $grantOption = false,
+ ) {
+ }
+
+ public static function create(TablePrivilege|string ...$privileges) : GrantOnStep
+ {
+ $privs = \array_map(
+ static fn (TablePrivilege|string $p) : string => $p instanceof TablePrivilege ? $p->value : $p,
+ $privileges,
+ );
+
+ return new self(\array_values($privs));
+ }
+
+ public function onAllTablesInSchema(string ...$schemas) : GrantToStep
+ {
+ return new self(
+ $this->privileges,
+ GrantTargetType::ACL_TARGET_ALL_IN_SCHEMA,
+ ObjectType::OBJECT_TABLE,
+ \array_values($schemas),
+ $this->grantees,
+ $this->grantOption,
+ );
+ }
+
+ public function onTable(string ...$tables) : GrantToStep
+ {
+ return new self(
+ $this->privileges,
+ GrantTargetType::ACL_TARGET_OBJECT,
+ ObjectType::OBJECT_TABLE,
+ \array_values($tables),
+ $this->grantees,
+ $this->grantOption,
+ );
+ }
+
+ public function to(string ...$roles) : GrantFinalStep
+ {
+ return new self(
+ $this->privileges,
+ $this->targetType,
+ $this->objectType,
+ $this->objects,
+ \array_values($roles),
+ $this->grantOption,
+ );
+ }
+
+ public function toAst() : GrantStmt
+ {
+ $stmt = new GrantStmt();
+ $stmt->setIsGrant(true);
+ $stmt->setTargtype($this->targetType);
+ $stmt->setObjtype($this->objectType);
+ $stmt->setGrantOption($this->grantOption);
+
+ $privilegeNodes = [];
+
+ foreach ($this->privileges as $privilege) {
+ if (\strtolower($privilege) === 'all') {
+ $privilegeNodes = [];
+
+ break;
+ }
+
+ $accessPriv = new AccessPriv();
+ $accessPriv->setPrivName($privilege);
+
+ $node = new Node();
+ $node->setAccessPriv($accessPriv);
+ $privilegeNodes[] = $node;
+ }
+
+ $stmt->setPrivileges($privilegeNodes);
+
+ $objectNodes = [];
+
+ if ($this->targetType === GrantTargetType::ACL_TARGET_ALL_IN_SCHEMA) {
+ foreach ($this->objects as $schemaName) {
+ $str = new PBString();
+ $str->setSval($schemaName);
+
+ $node = new Node();
+ $node->setString($str);
+ $objectNodes[] = $node;
+ }
+ } else {
+ foreach ($this->objects as $tableName) {
+ $identifier = QualifiedIdentifier::parse($tableName);
+ $rangeVar = new RangeVar();
+
+ $schema = $identifier->schema();
+
+ if ($schema !== null) {
+ $rangeVar->setSchemaname($schema);
+ }
+
+ $rangeVar->setRelname($identifier->name());
+ $rangeVar->setInh(true);
+
+ $node = new Node();
+ $node->setRangeVar($rangeVar);
+ $objectNodes[] = $node;
+ }
+ }
+
+ $stmt->setObjects($objectNodes);
+
+ $granteeNodes = [];
+
+ foreach ($this->grantees as $grantee) {
+ $roleSpec = new RoleSpec();
+
+ if (\strtolower($grantee) === 'public') {
+ $roleSpec->setRoletype(RoleSpecType::ROLESPEC_PUBLIC);
+ } else {
+ $roleSpec->setRoletype(RoleSpecType::ROLESPEC_CSTRING);
+ $roleSpec->setRolename($grantee);
+ }
+
+ $node = new Node();
+ $node->setRoleSpec($roleSpec);
+ $granteeNodes[] = $node;
+ }
+
+ $stmt->setGrantees($granteeNodes);
+
+ return $stmt;
+ }
+
+ public function toPublic() : GrantFinalStep
+ {
+ return $this->to('public');
+ }
+
+ public function withGrantOption() : GrantFinalStep
+ {
+ return new self(
+ $this->privileges,
+ $this->targetType,
+ $this->objectType,
+ $this->objects,
+ $this->grantees,
+ true,
+ );
+ }
+}
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
new file mode 100644
index 000000000..ce7e02496
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Grant/GrantFinalStep.php
@@ -0,0 +1,16 @@
+ $grantedRoles
+ * @param list $granteeRoles
+ */
+ private function __construct(
+ private array $grantedRoles,
+ private array $granteeRoles = [],
+ private bool $adminOption = false,
+ ) {
+ }
+
+ public static function create(string ...$roles) : GrantRoleToStep
+ {
+ return new self(\array_values($roles));
+ }
+
+ public function to(string ...$roles) : GrantRoleFinalStep
+ {
+ return new self(
+ $this->grantedRoles,
+ \array_values($roles),
+ $this->adminOption,
+ );
+ }
+
+ public function toAst() : GrantRoleStmt
+ {
+ $stmt = new GrantRoleStmt();
+ $stmt->setIsGrant(true);
+
+ $grantedRoleNodes = [];
+
+ foreach ($this->grantedRoles as $roleName) {
+ $roleSpec = new RoleSpec();
+ $roleSpec->setRoletype(RoleSpecType::ROLESPEC_CSTRING);
+ $roleSpec->setRolename($roleName);
+
+ $node = new Node();
+ $node->setRoleSpec($roleSpec);
+ $grantedRoleNodes[] = $node;
+ }
+
+ $stmt->setGrantedRoles($grantedRoleNodes);
+
+ $granteeRoleNodes = [];
+
+ foreach ($this->granteeRoles as $roleName) {
+ $roleSpec = new RoleSpec();
+ $roleSpec->setRoletype(RoleSpecType::ROLESPEC_CSTRING);
+ $roleSpec->setRolename($roleName);
+
+ $node = new Node();
+ $node->setRoleSpec($roleSpec);
+ $granteeRoleNodes[] = $node;
+ }
+
+ $stmt->setGranteeRoles($granteeRoleNodes);
+
+ if ($this->adminOption) {
+ $boolean = new Boolean();
+ $boolean->setBoolval(true);
+
+ $argNode = new Node();
+ /** @phpstan-ignore argument.type (protobuf PHPDoc says bool but actually expects Boolean) */
+ $argNode->setBoolean($boolean);
+
+ $defElem = new DefElem();
+ $defElem->setDefname('admin');
+ $defElem->setArg($argNode);
+
+ $node = new Node();
+ $node->setDefElem($defElem);
+ $stmt->setOpt([$node]);
+ }
+
+ return $stmt;
+ }
+
+ public function withAdminOption() : GrantRoleFinalStep
+ {
+ return new self(
+ $this->grantedRoles,
+ $this->granteeRoles,
+ true,
+ );
+ }
+}
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
new file mode 100644
index 000000000..4158d9a44
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Grant/GrantRoleFinalStep.php
@@ -0,0 +1,16 @@
+ $privileges
+ * @param list $objects
+ * @param list $grantees
+ */
+ private function __construct(
+ private array $privileges,
+ private int $targetType = GrantTargetType::ACL_TARGET_OBJECT,
+ private int $objectType = ObjectType::OBJECT_TABLE,
+ private array $objects = [],
+ private array $grantees = [],
+ private int $behavior = DropBehavior::DROP_RESTRICT,
+ ) {
+ }
+
+ public static function create(TablePrivilege|string ...$privileges) : RevokeOnStep
+ {
+ $privs = \array_map(
+ static fn (TablePrivilege|string $p) : string => $p instanceof TablePrivilege ? $p->value : $p,
+ $privileges,
+ );
+
+ return new self(\array_values($privs));
+ }
+
+ public function cascade() : RevokeFinalStep
+ {
+ return new self(
+ $this->privileges,
+ $this->targetType,
+ $this->objectType,
+ $this->objects,
+ $this->grantees,
+ DropBehavior::DROP_CASCADE,
+ );
+ }
+
+ public function from(string ...$roles) : RevokeFinalStep
+ {
+ return new self(
+ $this->privileges,
+ $this->targetType,
+ $this->objectType,
+ $this->objects,
+ \array_values($roles),
+ $this->behavior,
+ );
+ }
+
+ public function fromPublic() : RevokeFinalStep
+ {
+ return $this->from('public');
+ }
+
+ public function onAllTablesInSchema(string ...$schemas) : RevokeFromStep
+ {
+ return new self(
+ $this->privileges,
+ GrantTargetType::ACL_TARGET_ALL_IN_SCHEMA,
+ ObjectType::OBJECT_TABLE,
+ \array_values($schemas),
+ $this->grantees,
+ $this->behavior,
+ );
+ }
+
+ public function onTable(string ...$tables) : RevokeFromStep
+ {
+ return new self(
+ $this->privileges,
+ GrantTargetType::ACL_TARGET_OBJECT,
+ ObjectType::OBJECT_TABLE,
+ \array_values($tables),
+ $this->grantees,
+ $this->behavior,
+ );
+ }
+
+ public function restrict() : RevokeFinalStep
+ {
+ return new self(
+ $this->privileges,
+ $this->targetType,
+ $this->objectType,
+ $this->objects,
+ $this->grantees,
+ DropBehavior::DROP_RESTRICT,
+ );
+ }
+
+ public function toAst() : GrantStmt
+ {
+ $stmt = new GrantStmt();
+ $stmt->setIsGrant(false);
+ $stmt->setTargtype($this->targetType);
+ $stmt->setObjtype($this->objectType);
+ $stmt->setBehavior($this->behavior);
+
+ $privilegeNodes = [];
+
+ foreach ($this->privileges as $privilege) {
+ if (\strtolower($privilege) === 'all') {
+ $privilegeNodes = [];
+
+ break;
+ }
+
+ $accessPriv = new AccessPriv();
+ $accessPriv->setPrivName($privilege);
+
+ $node = new Node();
+ $node->setAccessPriv($accessPriv);
+ $privilegeNodes[] = $node;
+ }
+
+ $stmt->setPrivileges($privilegeNodes);
+
+ $objectNodes = [];
+
+ if ($this->targetType === GrantTargetType::ACL_TARGET_ALL_IN_SCHEMA) {
+ foreach ($this->objects as $schemaName) {
+ $str = new PBString();
+ $str->setSval($schemaName);
+
+ $node = new Node();
+ $node->setString($str);
+ $objectNodes[] = $node;
+ }
+ } else {
+ foreach ($this->objects as $tableName) {
+ $identifier = QualifiedIdentifier::parse($tableName);
+ $rangeVar = new RangeVar();
+
+ $schema = $identifier->schema();
+
+ if ($schema !== null) {
+ $rangeVar->setSchemaname($schema);
+ }
+
+ $rangeVar->setRelname($identifier->name());
+ $rangeVar->setInh(true);
+
+ $node = new Node();
+ $node->setRangeVar($rangeVar);
+ $objectNodes[] = $node;
+ }
+ }
+
+ $stmt->setObjects($objectNodes);
+
+ $granteeNodes = [];
+
+ foreach ($this->grantees as $grantee) {
+ $roleSpec = new RoleSpec();
+
+ if (\strtolower($grantee) === 'public') {
+ $roleSpec->setRoletype(RoleSpecType::ROLESPEC_PUBLIC);
+ } else {
+ $roleSpec->setRoletype(RoleSpecType::ROLESPEC_CSTRING);
+ $roleSpec->setRolename($grantee);
+ }
+
+ $node = new Node();
+ $node->setRoleSpec($roleSpec);
+ $granteeNodes[] = $node;
+ }
+
+ $stmt->setGrantees($granteeNodes);
+
+ return $stmt;
+ }
+}
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
new file mode 100644
index 000000000..9aba7555e
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Grant/RevokeFinalStep.php
@@ -0,0 +1,18 @@
+ $revokedRoles
+ * @param list $fromRoles
+ */
+ private function __construct(
+ private array $revokedRoles,
+ private array $fromRoles = [],
+ private int $behavior = DropBehavior::DROP_RESTRICT,
+ ) {
+ }
+
+ public static function create(string ...$roles) : RevokeRoleFromStep
+ {
+ return new self(\array_values($roles));
+ }
+
+ public function cascade() : RevokeRoleFinalStep
+ {
+ return new self(
+ $this->revokedRoles,
+ $this->fromRoles,
+ DropBehavior::DROP_CASCADE,
+ );
+ }
+
+ public function from(string ...$roles) : RevokeRoleFinalStep
+ {
+ return new self(
+ $this->revokedRoles,
+ \array_values($roles),
+ $this->behavior,
+ );
+ }
+
+ public function restrict() : RevokeRoleFinalStep
+ {
+ return new self(
+ $this->revokedRoles,
+ $this->fromRoles,
+ DropBehavior::DROP_RESTRICT,
+ );
+ }
+
+ public function toAst() : GrantRoleStmt
+ {
+ $stmt = new GrantRoleStmt();
+ $stmt->setIsGrant(false);
+ $stmt->setBehavior($this->behavior);
+
+ $grantedRoleNodes = [];
+
+ foreach ($this->revokedRoles as $roleName) {
+ $roleSpec = new RoleSpec();
+ $roleSpec->setRoletype(RoleSpecType::ROLESPEC_CSTRING);
+ $roleSpec->setRolename($roleName);
+
+ $node = new Node();
+ $node->setRoleSpec($roleSpec);
+ $grantedRoleNodes[] = $node;
+ }
+
+ $stmt->setGrantedRoles($grantedRoleNodes);
+
+ $granteeRoleNodes = [];
+
+ foreach ($this->fromRoles as $roleName) {
+ $roleSpec = new RoleSpec();
+ $roleSpec->setRoletype(RoleSpecType::ROLESPEC_CSTRING);
+ $roleSpec->setRolename($roleName);
+
+ $node = new Node();
+ $node->setRoleSpec($roleSpec);
+ $granteeRoleNodes[] = $node;
+ }
+
+ $stmt->setGranteeRoles($granteeRoleNodes);
+
+ return $stmt;
+ }
+}
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
new file mode 100644
index 000000000..4e66c7a4d
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Grant/RevokeRoleFinalStep.php
@@ -0,0 +1,18 @@
+index,
+ $this->schema,
+ true,
+ );
+ }
+
+ public function renameTo(string $newName) : RenameIndexFinalStep
+ {
+ return RenameIndexBuilder::create($this->index, $this->schema, $newName, $this->ifExists);
+ }
+
+ public function setTablespace(string $tablespace) : AlterTablespaceIndexFinalStep
+ {
+ return AlterTablespaceIndexBuilder::create($this->index, $this->schema, $tablespace, $this->ifExists);
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Index/AlterIndex/AlterIndexFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Index/AlterIndex/AlterIndexFinalStep.php
new file mode 100644
index 000000000..aae96c088
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Index/AlterIndex/AlterIndexFinalStep.php
@@ -0,0 +1,14 @@
+setObjtype(ObjectType::OBJECT_INDEX);
+
+ $rangeVar = new RangeVar();
+ $rangeVar->setRelname($this->index);
+ $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(AlterTableType::AT_SetTableSpace);
+ $cmd->setName($this->tablespace);
+
+ $cmdNode = new Node();
+ $cmdNode->setAlterTableCmd($cmd);
+
+ $stmt->setCmds([$cmdNode]);
+
+ return $stmt;
+ }
+}
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
new file mode 100644
index 000000000..2d7f94b45
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Index/AlterIndex/AlterTablespaceIndexFinalStep.php
@@ -0,0 +1,14 @@
+setRenameType(ObjectType::OBJECT_INDEX);
+
+ $rangeVar = new RangeVar();
+ $rangeVar->setRelname($this->index);
+ $rangeVar->setInh(true);
+ $rangeVar->setRelpersistence('p');
+
+ if ($this->schema !== null) {
+ $rangeVar->setSchemaname($this->schema);
+ }
+
+ $stmt->setRelation($rangeVar);
+ $stmt->setNewname($this->newName);
+
+ if ($this->ifExists) {
+ $stmt->setMissingOk(true);
+ }
+
+ return $stmt;
+ }
+}
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
new file mode 100644
index 000000000..114bcb87f
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Index/AlterIndex/RenameIndexFinalStep.php
@@ -0,0 +1,14 @@
+ $columns
+ * @param list $includeColumns
+ */
+ private function __construct(
+ private string $name,
+ private ?string $table = null,
+ private ?string $schema = null,
+ private array $columns = [],
+ private bool $unique = false,
+ private bool $concurrent = false,
+ private bool $ifNotExists = false,
+ private bool $onlyTable = false,
+ private ?IndexMethod $method = null,
+ private array $includeColumns = [],
+ private ?Condition $whereCondition = null,
+ private ?string $tablespace = null,
+ private bool $nullsNotDistinct = false,
+ ) {
+ }
+
+ public static function create(string $name) : CreateIndexOnStep
+ {
+ return new self($name);
+ }
+
+ public function columns(IndexColumn|string ...$columns) : CreateIndexFinalStep
+ {
+ $indexColumns = [];
+
+ foreach ($columns as $column) {
+ if (\is_string($column)) {
+ $indexColumns[] = IndexColumn::column($column);
+ } else {
+ $indexColumns[] = $column;
+ }
+ }
+
+ return new self(
+ $this->name,
+ $this->table,
+ $this->schema,
+ $indexColumns,
+ $this->unique,
+ $this->concurrent,
+ $this->ifNotExists,
+ $this->onlyTable,
+ $this->method,
+ $this->includeColumns,
+ $this->whereCondition,
+ $this->tablespace,
+ $this->nullsNotDistinct,
+ );
+ }
+
+ public function concurrently() : CreateIndexOnStep
+ {
+ return new self(
+ $this->name,
+ $this->table,
+ $this->schema,
+ $this->columns,
+ $this->unique,
+ true,
+ $this->ifNotExists,
+ $this->onlyTable,
+ $this->method,
+ $this->includeColumns,
+ $this->whereCondition,
+ $this->tablespace,
+ $this->nullsNotDistinct,
+ );
+ }
+
+ public function ifNotExists() : CreateIndexOnStep
+ {
+ return new self(
+ $this->name,
+ $this->table,
+ $this->schema,
+ $this->columns,
+ $this->unique,
+ $this->concurrent,
+ true,
+ $this->onlyTable,
+ $this->method,
+ $this->includeColumns,
+ $this->whereCondition,
+ $this->tablespace,
+ $this->nullsNotDistinct,
+ );
+ }
+
+ public function include(string ...$columns) : CreateIndexFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->table,
+ $this->schema,
+ $this->columns,
+ $this->unique,
+ $this->concurrent,
+ $this->ifNotExists,
+ $this->onlyTable,
+ $this->method,
+ \array_values([...$this->includeColumns, ...$columns]),
+ $this->whereCondition,
+ $this->tablespace,
+ $this->nullsNotDistinct,
+ );
+ }
+
+ public function nullsDistinct() : CreateIndexFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->table,
+ $this->schema,
+ $this->columns,
+ $this->unique,
+ $this->concurrent,
+ $this->ifNotExists,
+ $this->onlyTable,
+ $this->method,
+ $this->includeColumns,
+ $this->whereCondition,
+ $this->tablespace,
+ false,
+ );
+ }
+
+ public function nullsNotDistinct() : CreateIndexFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->table,
+ $this->schema,
+ $this->columns,
+ $this->unique,
+ $this->concurrent,
+ $this->ifNotExists,
+ $this->onlyTable,
+ $this->method,
+ $this->includeColumns,
+ $this->whereCondition,
+ $this->tablespace,
+ true,
+ );
+ }
+
+ public function on(string $table, ?string $schema = null) : CreateIndexColumnsStep
+ {
+ return new self(
+ $this->name,
+ $table,
+ $schema,
+ $this->columns,
+ $this->unique,
+ $this->concurrent,
+ $this->ifNotExists,
+ false,
+ $this->method,
+ $this->includeColumns,
+ $this->whereCondition,
+ $this->tablespace,
+ $this->nullsNotDistinct,
+ );
+ }
+
+ public function onOnly(string $table, ?string $schema = null) : CreateIndexColumnsStep
+ {
+ return new self(
+ $this->name,
+ $table,
+ $schema,
+ $this->columns,
+ $this->unique,
+ $this->concurrent,
+ $this->ifNotExists,
+ true,
+ $this->method,
+ $this->includeColumns,
+ $this->whereCondition,
+ $this->tablespace,
+ $this->nullsNotDistinct,
+ );
+ }
+
+ public function tablespace(string $tablespace) : CreateIndexFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->table,
+ $this->schema,
+ $this->columns,
+ $this->unique,
+ $this->concurrent,
+ $this->ifNotExists,
+ $this->onlyTable,
+ $this->method,
+ $this->includeColumns,
+ $this->whereCondition,
+ $tablespace,
+ $this->nullsNotDistinct,
+ );
+ }
+
+ public function toAst() : IndexStmt
+ {
+ $stmt = new IndexStmt();
+
+ $stmt->setIdxname($this->name);
+
+ if ($this->table !== null) {
+ $rangeVar = new RangeVar();
+ $rangeVar->setRelname($this->table);
+ $rangeVar->setInh(!$this->onlyTable);
+ $rangeVar->setRelpersistence('p');
+
+ if ($this->schema !== null) {
+ $rangeVar->setSchemaname($this->schema);
+ }
+
+ $stmt->setRelation($rangeVar);
+ }
+
+ if ($this->unique) {
+ $stmt->setUnique(true);
+ }
+
+ if ($this->concurrent) {
+ $stmt->setConcurrent(true);
+ }
+
+ if ($this->ifNotExists) {
+ $stmt->setIfNotExists(true);
+ }
+
+ if ($this->method !== null) {
+ $stmt->setAccessMethod($this->method->value);
+ }
+
+ if ($this->columns !== []) {
+ $indexParams = [];
+
+ foreach ($this->columns as $column) {
+ $node = new Node();
+ $node->setIndexElem($column->toAst());
+ $indexParams[] = $node;
+ }
+
+ $stmt->setIndexParams($indexParams);
+ }
+
+ if ($this->includeColumns !== []) {
+ $includeParams = [];
+
+ foreach ($this->includeColumns as $columnName) {
+ $indexElem = new IndexElem();
+ $indexElem->setName($columnName);
+
+ $node = new Node();
+ $node->setIndexElem($indexElem);
+ $includeParams[] = $node;
+ }
+
+ $stmt->setIndexIncludingParams($includeParams);
+ }
+
+ if ($this->whereCondition !== null) {
+ $stmt->setWhereClause($this->whereCondition->toAst());
+ }
+
+ if ($this->tablespace !== null) {
+ $stmt->setTableSpace($this->tablespace);
+ }
+
+ if ($this->nullsNotDistinct) {
+ $stmt->setNullsNotDistinct(true);
+ }
+
+ return $stmt;
+ }
+
+ public function unique() : CreateIndexOnStep
+ {
+ return new self(
+ $this->name,
+ $this->table,
+ $this->schema,
+ $this->columns,
+ true,
+ $this->concurrent,
+ $this->ifNotExists,
+ $this->onlyTable,
+ $this->method,
+ $this->includeColumns,
+ $this->whereCondition,
+ $this->tablespace,
+ $this->nullsNotDistinct,
+ );
+ }
+
+ public function using(IndexMethod $method) : CreateIndexColumnsStep
+ {
+ return new self(
+ $this->name,
+ $this->table,
+ $this->schema,
+ $this->columns,
+ $this->unique,
+ $this->concurrent,
+ $this->ifNotExists,
+ $this->onlyTable,
+ $method,
+ $this->includeColumns,
+ $this->whereCondition,
+ $this->tablespace,
+ $this->nullsNotDistinct,
+ );
+ }
+
+ public function where(Condition $predicate) : CreateIndexFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->table,
+ $this->schema,
+ $this->columns,
+ $this->unique,
+ $this->concurrent,
+ $this->ifNotExists,
+ $this->onlyTable,
+ $this->method,
+ $this->includeColumns,
+ $predicate,
+ $this->tablespace,
+ $this->nullsNotDistinct,
+ );
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Index/CreateIndex/CreateIndexColumnsStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Index/CreateIndex/CreateIndexColumnsStep.php
new file mode 100644
index 000000000..d1cd55d26
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Index/CreateIndex/CreateIndexColumnsStep.php
@@ -0,0 +1,14 @@
+ $indexes
+ */
+ private function __construct(
+ private array $indexes,
+ private bool $ifExists = false,
+ private bool $concurrent = false,
+ private int $behavior = DropBehavior::DROP_BEHAVIOR_UNDEFINED,
+ ) {
+ }
+
+ public static function create(string ...$indexes) : DropIndexFinalStep
+ {
+ return new self(\array_values($indexes));
+ }
+
+ public function cascade() : DropIndexFinalStep
+ {
+ return new self(
+ $this->indexes,
+ $this->ifExists,
+ $this->concurrent,
+ DropBehavior::DROP_CASCADE,
+ );
+ }
+
+ public function concurrently() : DropIndexFinalStep
+ {
+ return new self(
+ $this->indexes,
+ $this->ifExists,
+ true,
+ $this->behavior,
+ );
+ }
+
+ public function ifExists() : DropIndexFinalStep
+ {
+ return new self(
+ $this->indexes,
+ true,
+ $this->concurrent,
+ $this->behavior,
+ );
+ }
+
+ public function restrict() : DropIndexFinalStep
+ {
+ return new self(
+ $this->indexes,
+ $this->ifExists,
+ $this->concurrent,
+ DropBehavior::DROP_RESTRICT,
+ );
+ }
+
+ public function toAst() : DropStmt
+ {
+ $stmt = new DropStmt();
+ $stmt->setRemoveType(ObjectType::OBJECT_INDEX);
+
+ if ($this->ifExists) {
+ $stmt->setMissingOk(true);
+ }
+
+ if ($this->concurrent) {
+ $stmt->setConcurrent(true);
+ }
+
+ if ($this->behavior !== DropBehavior::DROP_BEHAVIOR_UNDEFINED) {
+ $stmt->setBehavior($this->behavior);
+ }
+
+ $objects = [];
+
+ foreach ($this->indexes as $index) {
+ $objects[] = $this->createIndexListNode($index);
+ }
+
+ $stmt->setObjects($objects);
+
+ return $stmt;
+ }
+
+ private function createIndexListNode(string $index) : Node
+ {
+ $identifier = QualifiedIdentifier::parse($index);
+ $listItems = [];
+
+ foreach ($identifier->parts() as $part) {
+ $str = new PBString();
+ $str->setSval($part);
+
+ $strNode = new Node();
+ $strNode->setString($str);
+ $listItems[] = $strNode;
+ }
+
+ $list = new PBList();
+ $list->setItems($listItems);
+
+ $node = new Node();
+ $node->setList($list);
+
+ return $node;
+ }
+}
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
new file mode 100644
index 000000000..c46d7cde5
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Index/DropIndex/DropIndexFinalStep.php
@@ -0,0 +1,22 @@
+name,
+ $this->expression,
+ $this->opclass,
+ SortByDir::SORTBY_ASC,
+ $this->nullsOrdering,
+ $this->collation,
+ );
+ }
+
+ public function collate(string $collation) : self
+ {
+ return new self(
+ $this->name,
+ $this->expression,
+ $this->opclass,
+ $this->ordering,
+ $this->nullsOrdering,
+ $collation,
+ );
+ }
+
+ public function desc() : self
+ {
+ return new self(
+ $this->name,
+ $this->expression,
+ $this->opclass,
+ SortByDir::SORTBY_DESC,
+ $this->nullsOrdering,
+ $this->collation,
+ );
+ }
+
+ public function nullsFirst() : self
+ {
+ return new self(
+ $this->name,
+ $this->expression,
+ $this->opclass,
+ $this->ordering,
+ SortByNulls::SORTBY_NULLS_FIRST,
+ $this->collation,
+ );
+ }
+
+ public function nullsLast() : self
+ {
+ return new self(
+ $this->name,
+ $this->expression,
+ $this->opclass,
+ $this->ordering,
+ SortByNulls::SORTBY_NULLS_LAST,
+ $this->collation,
+ );
+ }
+
+ public function opclass(string $opclass) : self
+ {
+ return new self(
+ $this->name,
+ $this->expression,
+ $opclass,
+ $this->ordering,
+ $this->nullsOrdering,
+ $this->collation,
+ );
+ }
+
+ public function toAst() : IndexElem
+ {
+ $elem = new IndexElem();
+
+ if ($this->name !== null) {
+ $elem->setName($this->name);
+ }
+
+ if ($this->expression !== null) {
+ $elem->setExpr($this->expression->toAst());
+ }
+
+ if ($this->ordering !== SortByDir::SORT_BY_DIR_UNDEFINED) {
+ $elem->setOrdering($this->ordering);
+ }
+
+ if ($this->nullsOrdering !== SortByNulls::SORT_BY_NULLS_UNDEFINED) {
+ $elem->setNullsOrdering($this->nullsOrdering);
+ }
+
+ if ($this->opclass !== null) {
+ $opclassString = new PBString();
+ $opclassString->setSval($this->opclass);
+
+ $opclassNode = new Node();
+ $opclassNode->setString($opclassString);
+
+ $elem->setOpclass([$opclassNode]);
+ }
+
+ if ($this->collation !== null) {
+ $collationString = new PBString();
+ $collationString->setSval($this->collation);
+
+ $collationNode = new Node();
+ $collationNode->setString($collationString);
+
+ $elem->setCollation([$collationNode]);
+ }
+
+ return $elem;
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Index/IndexMethod.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Index/IndexMethod.php
new file mode 100644
index 000000000..2ea4b2728
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Index/IndexMethod.php
@@ -0,0 +1,15 @@
+kind,
+ $this->name,
+ true,
+ $this->tablespace,
+ $this->verbose,
+ );
+ }
+
+ public function tablespace(string $tablespace) : ReindexFinalStep
+ {
+ return new self(
+ $this->kind,
+ $this->name,
+ $this->concurrent,
+ $tablespace,
+ $this->verbose,
+ );
+ }
+
+ public function toAst() : ReindexStmt
+ {
+ $stmt = new ReindexStmt();
+ $stmt->setKind($this->kind);
+
+ if ($this->kind === ReindexObjectType::REINDEX_OBJECT_INDEX || $this->kind === ReindexObjectType::REINDEX_OBJECT_TABLE) {
+ $rangeVar = new RangeVar();
+
+ $identifier = QualifiedIdentifier::parse($this->name);
+
+ if ($identifier->hasSchema()) {
+ $rangeVar->setSchemaname($identifier->schema());
+ }
+
+ $rangeVar->setRelname($identifier->name());
+
+ $rangeVar->setInh(true);
+ $rangeVar->setRelpersistence('p');
+ $stmt->setRelation($rangeVar);
+ } else {
+ $stmt->setName($this->name);
+ }
+
+ $params = [];
+
+ if ($this->concurrent) {
+ $params[] = $this->createDefElemBool('concurrently');
+ }
+
+ if ($this->tablespace !== null) {
+ $params[] = $this->createDefElemString('tablespace', $this->tablespace);
+ }
+
+ if ($this->verbose) {
+ $params[] = $this->createDefElemBool('verbose');
+ }
+
+ if ($params !== []) {
+ $stmt->setParams($params);
+ }
+
+ return $stmt;
+ }
+
+ public function verbose() : ReindexFinalStep
+ {
+ return new self(
+ $this->kind,
+ $this->name,
+ $this->concurrent,
+ $this->tablespace,
+ true,
+ );
+ }
+
+ private function createDefElemBool(string $name) : Node
+ {
+ $defElem = new DefElem();
+ $defElem->setDefname($name);
+
+ $node = new Node();
+ $node->setDefElem($defElem);
+
+ return $node;
+ }
+
+ private function createDefElemString(string $name, string $value) : Node
+ {
+ $defElem = new DefElem();
+ $defElem->setDefname($name);
+
+ $str = new PBString();
+ $str->setSval($value);
+
+ $strNode = new Node();
+ $strNode->setString($str);
+ $defElem->setArg($strNode);
+
+ $node = new Node();
+ $node->setDefElem($defElem);
+
+ return $node;
+ }
+}
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
new file mode 100644
index 000000000..041b451bc
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Index/Reindex/ReindexFinalStep.php
@@ -0,0 +1,20 @@
+ $roles
+ */
+ private function __construct(
+ private array $roles,
+ private int $behavior = DropBehavior::DROP_RESTRICT,
+ ) {
+ }
+
+ public static function create(string ...$roles) : DropOwnedFinalStep
+ {
+ return new self(\array_values($roles));
+ }
+
+ public function cascade() : DropOwnedFinalStep
+ {
+ return new self(
+ $this->roles,
+ DropBehavior::DROP_CASCADE,
+ );
+ }
+
+ public function restrict() : DropOwnedFinalStep
+ {
+ return new self(
+ $this->roles,
+ DropBehavior::DROP_RESTRICT,
+ );
+ }
+
+ public function toAst() : DropOwnedStmt
+ {
+ $stmt = new DropOwnedStmt();
+ $stmt->setBehavior($this->behavior);
+
+ $roleNodes = [];
+
+ foreach ($this->roles as $roleName) {
+ $roleSpec = new RoleSpec();
+ $roleSpec->setRoletype(RoleSpecType::ROLESPEC_CSTRING);
+ $roleSpec->setRolename($roleName);
+
+ $node = new Node();
+ $node->setRoleSpec($roleSpec);
+ $roleNodes[] = $node;
+ }
+
+ $stmt->setRoles($roleNodes);
+
+ return $stmt;
+ }
+}
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
new file mode 100644
index 000000000..43254b693
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Ownership/DropOwnedFinalStep.php
@@ -0,0 +1,18 @@
+ $roles
+ */
+ private function __construct(
+ private array $roles,
+ private ?string $newRole = null,
+ ) {
+ }
+
+ public static function create(string ...$roles) : ReassignOwnedToStep
+ {
+ return new self(\array_values($roles));
+ }
+
+ public function to(string $newRole) : ReassignOwnedFinalStep
+ {
+ return new self(
+ $this->roles,
+ $newRole,
+ );
+ }
+
+ public function toAst() : ReassignOwnedStmt
+ {
+ $stmt = new ReassignOwnedStmt();
+
+ $roleNodes = [];
+
+ foreach ($this->roles as $roleName) {
+ $roleSpec = new RoleSpec();
+ $roleSpec->setRoletype(RoleSpecType::ROLESPEC_CSTRING);
+ $roleSpec->setRolename($roleName);
+
+ $node = new Node();
+ $node->setRoleSpec($roleSpec);
+ $roleNodes[] = $node;
+ }
+
+ $stmt->setRoles($roleNodes);
+
+ if ($this->newRole !== null) {
+ $newRoleSpec = new RoleSpec();
+ $newRoleSpec->setRoletype(RoleSpecType::ROLESPEC_CSTRING);
+ $newRoleSpec->setRolename($this->newRole);
+ $stmt->setNewrole($newRoleSpec);
+ }
+
+ return $stmt;
+ }
+}
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
new file mode 100644
index 000000000..8a78318f9
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Ownership/ReassignOwnedFinalStep.php
@@ -0,0 +1,14 @@
+ $options
+ */
+ private function __construct(
+ private string $name,
+ private array $options = [],
+ ) {
+ }
+
+ public static function create(string $name) : AlterRoleActionStep
+ {
+ return new self($name);
+ }
+
+ public function bypassRls() : AlterRoleFinalStep
+ {
+ return $this->withBooleanOption(RoleOption::BYPASSRLS->value, true);
+ }
+
+ public function connectionLimit(int $limit) : AlterRoleFinalStep
+ {
+ return $this->withIntegerOption('connectionlimit', $limit);
+ }
+
+ public function createDb() : AlterRoleFinalStep
+ {
+ return $this->withBooleanOption(RoleOption::CREATEDB->value, true);
+ }
+
+ public function createRole() : AlterRoleFinalStep
+ {
+ return $this->withBooleanOption(RoleOption::CREATEROLE->value, true);
+ }
+
+ public function inherit() : AlterRoleFinalStep
+ {
+ return $this->withBooleanOption(RoleOption::INHERIT->value, true);
+ }
+
+ public function login() : AlterRoleFinalStep
+ {
+ return $this->withBooleanOption(RoleOption::LOGIN->value, true);
+ }
+
+ public function noBypassRls() : AlterRoleFinalStep
+ {
+ return $this->withBooleanOption(RoleOption::BYPASSRLS->value, false);
+ }
+
+ public function noCreateDb() : AlterRoleFinalStep
+ {
+ return $this->withBooleanOption(RoleOption::CREATEDB->value, false);
+ }
+
+ public function noCreateRole() : AlterRoleFinalStep
+ {
+ return $this->withBooleanOption(RoleOption::CREATEROLE->value, false);
+ }
+
+ public function noInherit() : AlterRoleFinalStep
+ {
+ return $this->withBooleanOption(RoleOption::INHERIT->value, false);
+ }
+
+ public function noLogin() : AlterRoleFinalStep
+ {
+ return $this->withBooleanOption(RoleOption::LOGIN->value, false);
+ }
+
+ public function noReplication() : AlterRoleFinalStep
+ {
+ return $this->withBooleanOption(RoleOption::REPLICATION->value, false);
+ }
+
+ public function noSuperuser() : AlterRoleFinalStep
+ {
+ return $this->withBooleanOption(RoleOption::SUPERUSER->value, false);
+ }
+
+ public function renameTo(string $newName) : AlterRoleRenameFinalStep
+ {
+ return AlterRoleRenameBuilder::create($this->name, $newName);
+ }
+
+ public function replication() : AlterRoleFinalStep
+ {
+ return $this->withBooleanOption(RoleOption::REPLICATION->value, true);
+ }
+
+ public function set() : AlterRoleFinalStep
+ {
+ return $this;
+ }
+
+ public function superuser() : AlterRoleFinalStep
+ {
+ return $this->withBooleanOption(RoleOption::SUPERUSER->value, true);
+ }
+
+ public function toAst() : AlterRoleStmt
+ {
+ $stmt = new AlterRoleStmt();
+
+ $roleSpec = new RoleSpec();
+ $roleSpec->setRoletype(RoleSpecType::ROLESPEC_CSTRING);
+ $roleSpec->setRolename($this->name);
+ $stmt->setRole($roleSpec);
+
+ $stmt->setAction(1);
+
+ $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;
+ }
+
+ public function validUntil(string $timestamp) : AlterRoleFinalStep
+ {
+ return $this->withStringOption('validUntil', $timestamp);
+ }
+
+ public function withPassword(string $password) : AlterRoleFinalStep
+ {
+ return $this->withStringOption('password', $password);
+ }
+
+ private function withBooleanOption(string $name, bool $value) : self
+ {
+ $integer = new Integer();
+ $integer->setIval($value ? 1 : 0);
+
+ $argNode = new Node();
+ /** @phpstan-ignore argument.type (protobuf PHPDoc says int but actually expects Integer) */
+ $argNode->setInteger($integer);
+
+ return $this->withOption($name, $argNode);
+ }
+
+ private function withIntegerOption(string $name, int $value) : self
+ {
+ $integer = new Integer();
+ $integer->setIval($value);
+
+ $argNode = new Node();
+ /** @phpstan-ignore argument.type (protobuf PHPDoc says int but actually expects Integer) */
+ $argNode->setInteger($integer);
+
+ return $this->withOption($name, $argNode);
+ }
+
+ private function withOption(string $name, ?Node $arg) : self
+ {
+ $newOptions = $this->options;
+ $newOptions[] = ['name' => $name, 'arg' => $arg];
+
+ return new self(
+ $this->name,
+ $newOptions,
+ );
+ }
+
+ private function withStringOption(string $name, string $value) : self
+ {
+ $str = new PBString();
+ $str->setSval($value);
+
+ $argNode = new Node();
+ $argNode->setString($str);
+
+ return $this->withOption($name, $argNode);
+ }
+}
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
new file mode 100644
index 000000000..1aed67e7c
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Role/AlterRoleFinalStep.php
@@ -0,0 +1,48 @@
+setRenameType(ObjectType::OBJECT_ROLE);
+ $stmt->setSubname($this->name);
+ $stmt->setNewname($this->newName);
+
+ return $stmt;
+ }
+}
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
new file mode 100644
index 000000000..dcce6e284
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Role/AlterRoleRenameFinalStep.php
@@ -0,0 +1,14 @@
+ $options
+ * @param list $inRoles
+ */
+ private function __construct(
+ private string $name,
+ private array $options = [],
+ private array $inRoles = [],
+ ) {
+ }
+
+ public static function create(string $name) : CreateRoleOptionsStep
+ {
+ return new self($name);
+ }
+
+ public function bypassRls() : CreateRoleOptionsStep
+ {
+ return $this->withBooleanOption(RoleOption::BYPASSRLS->value, true);
+ }
+
+ public function connectionLimit(int $limit) : CreateRoleOptionsStep
+ {
+ return $this->withIntegerOption('connectionlimit', $limit);
+ }
+
+ public function createDb() : CreateRoleOptionsStep
+ {
+ return $this->withBooleanOption(RoleOption::CREATEDB->value, true);
+ }
+
+ public function createRole() : CreateRoleOptionsStep
+ {
+ return $this->withBooleanOption(RoleOption::CREATEROLE->value, true);
+ }
+
+ public function inherit() : CreateRoleOptionsStep
+ {
+ return $this->withBooleanOption(RoleOption::INHERIT->value, true);
+ }
+
+ public function inRole(string ...$roles) : CreateRoleOptionsStep
+ {
+ return new self(
+ $this->name,
+ $this->options,
+ \array_values($roles),
+ );
+ }
+
+ public function login() : CreateRoleOptionsStep
+ {
+ return $this->withBooleanOption(RoleOption::LOGIN->value, true);
+ }
+
+ public function noBypassRls() : CreateRoleOptionsStep
+ {
+ return $this->withBooleanOption(RoleOption::BYPASSRLS->value, false);
+ }
+
+ public function noCreateDb() : CreateRoleOptionsStep
+ {
+ return $this->withBooleanOption(RoleOption::CREATEDB->value, false);
+ }
+
+ public function noCreateRole() : CreateRoleOptionsStep
+ {
+ return $this->withBooleanOption(RoleOption::CREATEROLE->value, false);
+ }
+
+ public function noInherit() : CreateRoleOptionsStep
+ {
+ return $this->withBooleanOption(RoleOption::INHERIT->value, false);
+ }
+
+ public function noLogin() : CreateRoleOptionsStep
+ {
+ return $this->withBooleanOption(RoleOption::LOGIN->value, false);
+ }
+
+ public function noReplication() : CreateRoleOptionsStep
+ {
+ return $this->withBooleanOption(RoleOption::REPLICATION->value, false);
+ }
+
+ public function noSuperuser() : CreateRoleOptionsStep
+ {
+ return $this->withBooleanOption(RoleOption::SUPERUSER->value, false);
+ }
+
+ public function replication() : CreateRoleOptionsStep
+ {
+ return $this->withBooleanOption(RoleOption::REPLICATION->value, true);
+ }
+
+ public function superuser() : CreateRoleOptionsStep
+ {
+ return $this->withBooleanOption(RoleOption::SUPERUSER->value, true);
+ }
+
+ public function toAst() : CreateRoleStmt
+ {
+ $stmt = new CreateRoleStmt();
+ $stmt->setStmtType(RoleStmtType::ROLESTMT_ROLE);
+ $stmt->setRole($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 ($this->inRoles !== []) {
+ $roleNodes = [];
+
+ foreach ($this->inRoles as $roleName) {
+ $roleSpec = new RoleSpec();
+ $roleSpec->setRoletype(RoleSpecType::ROLESPEC_CSTRING);
+ $roleSpec->setRolename($roleName);
+
+ $node = new Node();
+ $node->setRoleSpec($roleSpec);
+ $roleNodes[] = $node;
+ }
+
+ $defElem = new DefElem();
+ $defElem->setDefname('addroleto');
+
+ $listNode = new Node();
+ $list = new PBList();
+ $list->setItems($roleNodes);
+ $listNode->setList($list);
+ $defElem->setArg($listNode);
+
+ $node = new Node();
+ $node->setDefElem($defElem);
+ $optionNodes[] = $node;
+ }
+
+ if ($optionNodes !== []) {
+ $stmt->setOptions($optionNodes);
+ }
+
+ return $stmt;
+ }
+
+ public function validUntil(string $timestamp) : CreateRoleOptionsStep
+ {
+ return $this->withStringOption('validUntil', $timestamp);
+ }
+
+ public function withPassword(string $password) : CreateRoleOptionsStep
+ {
+ return $this->withStringOption('password', $password);
+ }
+
+ private function withBooleanOption(string $name, bool $value) : self
+ {
+ $integer = new Integer();
+ $integer->setIval($value ? 1 : 0);
+
+ $argNode = new Node();
+ /** @phpstan-ignore argument.type (protobuf PHPDoc says int but actually expects Integer) */
+ $argNode->setInteger($integer);
+
+ return $this->withOption($name, $argNode);
+ }
+
+ private function withIntegerOption(string $name, int $value) : self
+ {
+ $integer = new Integer();
+ $integer->setIval($value);
+
+ $argNode = new Node();
+ /** @phpstan-ignore argument.type (protobuf PHPDoc says int but actually expects Integer) */
+ $argNode->setInteger($integer);
+
+ return $this->withOption($name, $argNode);
+ }
+
+ private function withOption(string $name, ?Node $arg) : self
+ {
+ $newOptions = $this->options;
+ $newOptions[] = ['name' => $name, 'arg' => $arg];
+
+ return new self(
+ $this->name,
+ $newOptions,
+ $this->inRoles,
+ );
+ }
+
+ private function withStringOption(string $name, string $value) : self
+ {
+ $str = new PBString();
+ $str->setSval($value);
+
+ $argNode = new Node();
+ $argNode->setString($str);
+
+ return $this->withOption($name, $argNode);
+ }
+}
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
new file mode 100644
index 000000000..90f2696cb
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Role/CreateRoleFinalStep.php
@@ -0,0 +1,14 @@
+ $names
+ */
+ private function __construct(
+ private array $names,
+ private bool $ifExists = false,
+ ) {
+ }
+
+ public static function create(string ...$names) : DropRoleFinalStep
+ {
+ return new self(\array_values($names));
+ }
+
+ public function ifExists() : DropRoleFinalStep
+ {
+ return new self(
+ $this->names,
+ true,
+ );
+ }
+
+ public function toAst() : DropRoleStmt
+ {
+ $stmt = new DropRoleStmt();
+ $stmt->setMissingOk($this->ifExists);
+
+ $roleNodes = [];
+
+ foreach ($this->names as $name) {
+ $roleSpec = new RoleSpec();
+ $roleSpec->setRoletype(RoleSpecType::ROLESPEC_CSTRING);
+ $roleSpec->setRolename($name);
+
+ $node = new Node();
+ $node->setRoleSpec($roleSpec);
+ $roleNodes[] = $node;
+ }
+
+ $stmt->setRoles($roleNodes);
+
+ return $stmt;
+ }
+}
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
new file mode 100644
index 000000000..765320efd
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Role/DropRoleFinalStep.php
@@ -0,0 +1,16 @@
+ $actions
+ */
+ private function __construct(
+ private string $name,
+ private bool $replace = false,
+ private ?RuleEvent $event = null,
+ private ?string $table = null,
+ private ?string $schema = null,
+ private ?string $whereCondition = null,
+ private bool $instead = false,
+ private array $actions = [],
+ ) {
+ }
+
+ public static function create(string $name) : CreateRuleEventStep
+ {
+ return new self($name);
+ }
+
+ public function asOnDelete() : CreateRuleToStep
+ {
+ return new self(
+ $this->name,
+ $this->replace,
+ RuleEvent::DELETE,
+ $this->table,
+ $this->schema,
+ $this->whereCondition,
+ $this->instead,
+ $this->actions,
+ );
+ }
+
+ public function asOnInsert() : CreateRuleToStep
+ {
+ return new self(
+ $this->name,
+ $this->replace,
+ RuleEvent::INSERT,
+ $this->table,
+ $this->schema,
+ $this->whereCondition,
+ $this->instead,
+ $this->actions,
+ );
+ }
+
+ public function asOnSelect() : CreateRuleToStep
+ {
+ return new self(
+ $this->name,
+ $this->replace,
+ RuleEvent::SELECT,
+ $this->table,
+ $this->schema,
+ $this->whereCondition,
+ $this->instead,
+ $this->actions,
+ );
+ }
+
+ public function asOnUpdate() : CreateRuleToStep
+ {
+ return new self(
+ $this->name,
+ $this->replace,
+ RuleEvent::UPDATE,
+ $this->table,
+ $this->schema,
+ $this->whereCondition,
+ $this->instead,
+ $this->actions,
+ );
+ }
+
+ public function doAlso(string $command) : CreateRuleFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->replace,
+ $this->event,
+ $this->table,
+ $this->schema,
+ $this->whereCondition,
+ false,
+ [$this->parseCommand($command)],
+ );
+ }
+
+ public function doInstead(string $command) : CreateRuleFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->replace,
+ $this->event,
+ $this->table,
+ $this->schema,
+ $this->whereCondition,
+ true,
+ [$this->parseCommand($command)],
+ );
+ }
+
+ public function doNothing() : CreateRuleFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->replace,
+ $this->event,
+ $this->table,
+ $this->schema,
+ $this->whereCondition,
+ false,
+ [],
+ );
+ }
+
+ public function orReplace() : CreateRuleEventStep
+ {
+ return new self(
+ $this->name,
+ true,
+ $this->event,
+ $this->table,
+ $this->schema,
+ $this->whereCondition,
+ $this->instead,
+ $this->actions,
+ );
+ }
+
+ public function to(string $table, ?string $schema = null) : CreateRuleWhereStep
+ {
+ $identifier = QualifiedIdentifier::parse($table);
+
+ return new self(
+ $this->name,
+ $this->replace,
+ $this->event,
+ $identifier->name(),
+ $schema ?? $identifier->schema(),
+ $this->whereCondition,
+ $this->instead,
+ $this->actions,
+ );
+ }
+
+ public function toAst() : RuleStmt
+ {
+ $stmt = new RuleStmt();
+
+ $stmt->setRulename($this->name);
+
+ if ($this->replace) {
+ $stmt->setReplace(true);
+ }
+
+ if ($this->event !== null) {
+ $stmt->setEvent($this->event->value);
+ }
+
+ if ($this->table !== null) {
+ $relation = new RangeVar();
+ $relation->setRelname($this->table);
+ $relation->setRelpersistence('p');
+ $relation->setInh(true);
+
+ if ($this->schema !== null) {
+ $relation->setSchemaname($this->schema);
+ }
+
+ $stmt->setRelation($relation);
+ }
+
+ if ($this->whereCondition !== null) {
+ $stmt->setWhereClause($this->parseCondition($this->whereCondition));
+ }
+
+ $stmt->setInstead($this->instead);
+
+ if ($this->actions !== []) {
+ $stmt->setActions($this->actions);
+ }
+
+ return $stmt;
+ }
+
+ public function where(string $condition) : CreateRuleDoStep
+ {
+ return new self(
+ $this->name,
+ $this->replace,
+ $this->event,
+ $this->table,
+ $this->schema,
+ $condition,
+ $this->instead,
+ $this->actions,
+ );
+ }
+
+ private function parseCommand(string $command) : Node
+ {
+ $parser = new Parser();
+ $parsed = $parser->parse($command);
+
+ $stmts = $parsed->raw()->getStmts();
+
+ if ($stmts === null || \count($stmts) === 0) {
+ throw InvalidAstException::invalidFieldValue('stmts', 'ParseResult', 'expected at least one statement');
+ }
+
+ $stmt = $stmts[0]->getStmt();
+
+ if ($stmt === null) {
+ throw InvalidAstException::missingRequiredField('stmt', 'RawStmt');
+ }
+
+ 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/CreateRuleDoStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Rule/CreateRuleDoStep.php
new file mode 100644
index 000000000..7ab2cf508
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Rule/CreateRuleDoStep.php
@@ -0,0 +1,14 @@
+name,
+ $this->ifExists,
+ $this->table,
+ $this->schema,
+ DropBehavior::DROP_CASCADE,
+ );
+ }
+
+ public function ifExists() : DropRuleOnStep
+ {
+ return new self(
+ $this->name,
+ true,
+ $this->table,
+ $this->schema,
+ $this->behavior,
+ );
+ }
+
+ public function on(string $table, ?string $schema = null) : DropRuleFinalStep
+ {
+ if ($schema !== null) {
+ return new self(
+ $this->name,
+ $this->ifExists,
+ $table,
+ $schema,
+ $this->behavior,
+ );
+ }
+
+ $identifier = QualifiedIdentifier::parse($table);
+
+ return new self(
+ $this->name,
+ $this->ifExists,
+ $identifier->name(),
+ $identifier->schema(),
+ $this->behavior,
+ );
+ }
+
+ public function restrict() : DropRuleFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->ifExists,
+ $this->table,
+ $this->schema,
+ DropBehavior::DROP_RESTRICT,
+ );
+ }
+
+ public function toAst() : DropStmt
+ {
+ $stmt = new DropStmt();
+
+ $stmt->setRemoveType(ObjectType::OBJECT_RULE);
+ $stmt->setMissingOk($this->ifExists);
+ $stmt->setBehavior($this->behavior);
+
+ $listItems = [];
+
+ if ($this->schema !== null) {
+ $schemaStr = new PBString();
+ $schemaStr->setSval($this->schema);
+ $schemaNode = new Node();
+ $schemaNode->setString($schemaStr);
+ $listItems[] = $schemaNode;
+ }
+
+ if ($this->table !== null) {
+ $tableStr = new PBString();
+ $tableStr->setSval($this->table);
+ $tableNode = new Node();
+ $tableNode->setString($tableStr);
+ $listItems[] = $tableNode;
+ }
+
+ $nameStr = new PBString();
+ $nameStr->setSval($this->name);
+ $nameNode = new Node();
+ $nameNode->setString($nameStr);
+ $listItems[] = $nameNode;
+
+ $list = new PBList();
+ $list->setItems($listItems);
+
+ $objectNode = new Node();
+ $objectNode->setList($list);
+
+ $stmt->setObjects([$objectNode]);
+
+ return $stmt;
+ }
+}
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
new file mode 100644
index 000000000..2330fd0c2
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Rule/DropRuleFinalStep.php
@@ -0,0 +1,18 @@
+name, $owner);
+ }
+
+ public function renameTo(string $newName) : AlterSchemaRenameFinalStep
+ {
+ return AlterSchemaRenameBuilder::create($this->name, $newName);
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Schema/AlterSchemaOwnerBuilder.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Schema/AlterSchemaOwnerBuilder.php
new file mode 100644
index 000000000..185b9fb15
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Schema/AlterSchemaOwnerBuilder.php
@@ -0,0 +1,43 @@
+setObjectType(ObjectType::OBJECT_SCHEMA);
+
+ $str = new PBString();
+ $str->setSval($this->name);
+ $node = new Node();
+ $node->setString($str);
+ $stmt->setObject($node);
+
+ $roleSpec = new RoleSpec();
+ $roleSpec->setRoletype(RoleSpecType::ROLESPEC_CSTRING);
+ $roleSpec->setRolename($this->owner);
+ $stmt->setNewowner($roleSpec);
+
+ return $stmt;
+ }
+}
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
new file mode 100644
index 000000000..5ac8b22b3
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Schema/AlterSchemaOwnerFinalStep.php
@@ -0,0 +1,14 @@
+setRenameType(ObjectType::OBJECT_SCHEMA);
+ $stmt->setSubname($this->name);
+ $stmt->setNewname($this->newName);
+
+ return $stmt;
+ }
+}
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
new file mode 100644
index 000000000..041ff8fbf
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Schema/AlterSchemaRenameFinalStep.php
@@ -0,0 +1,14 @@
+name,
+ $role,
+ $this->ifNotExists,
+ );
+ }
+
+ public function ifNotExists() : CreateSchemaOptionsStep
+ {
+ return new self(
+ $this->name,
+ $this->authRole,
+ true,
+ );
+ }
+
+ public function toAst() : CreateSchemaStmt
+ {
+ $stmt = new CreateSchemaStmt();
+
+ if ($this->name !== null) {
+ $stmt->setSchemaname($this->name);
+ }
+
+ if ($this->authRole !== null) {
+ $roleSpec = new RoleSpec();
+ $roleSpec->setRoletype(RoleSpecType::ROLESPEC_CSTRING);
+ $roleSpec->setRolename($this->authRole);
+ $stmt->setAuthrole($roleSpec);
+ }
+
+ $stmt->setIfNotExists($this->ifNotExists);
+
+ return $stmt;
+ }
+}
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
new file mode 100644
index 000000000..0f5ffbd7e
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Schema/CreateSchemaFinalStep.php
@@ -0,0 +1,14 @@
+ $names
+ */
+ private function __construct(
+ private array $names,
+ private bool $ifExists = false,
+ private int $behavior = DropBehavior::DROP_RESTRICT,
+ ) {
+ }
+
+ public static function create(string ...$names) : DropSchemaFinalStep
+ {
+ return new self(\array_values($names));
+ }
+
+ public function cascade() : DropSchemaFinalStep
+ {
+ return new self(
+ $this->names,
+ $this->ifExists,
+ DropBehavior::DROP_CASCADE,
+ );
+ }
+
+ public function ifExists() : DropSchemaFinalStep
+ {
+ return new self(
+ $this->names,
+ true,
+ $this->behavior,
+ );
+ }
+
+ public function restrict() : DropSchemaFinalStep
+ {
+ return new self(
+ $this->names,
+ $this->ifExists,
+ DropBehavior::DROP_RESTRICT,
+ );
+ }
+
+ public function toAst() : DropStmt
+ {
+ $stmt = new DropStmt();
+ $stmt->setRemoveType(ObjectType::OBJECT_SCHEMA);
+ $stmt->setBehavior($this->behavior);
+ $stmt->setMissingOk($this->ifExists);
+
+ $objects = [];
+
+ foreach ($this->names as $name) {
+ $str = new PBString();
+ $str->setSval($name);
+ $node = new Node();
+ $node->setString($str);
+ $objects[] = $node;
+ }
+
+ $stmt->setObjects($objects);
+
+ return $stmt;
+ }
+}
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
new file mode 100644
index 000000000..2005dd159
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Schema/DropSchemaFinalStep.php
@@ -0,0 +1,20 @@
+setKind(VariableSetKind::VAR_RESET);
+ $stmt->setName('role');
+
+ return $stmt;
+ }
+}
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
new file mode 100644
index 000000000..70d778f99
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Session/ResetRoleFinalStep.php
@@ -0,0 +1,14 @@
+setKind(VariableSetKind::VAR_SET_VALUE);
+ $stmt->setName('role');
+
+ $str = new PBString();
+ $str->setSval($this->roleName);
+
+ $aConst = new A_Const();
+ $aConst->setSval($str);
+
+ $node = new Node();
+ $node->setAConst($aConst);
+
+ $stmt->setArgs([$node]);
+
+ return $stmt;
+ }
+}
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
new file mode 100644
index 000000000..ad1a81a23
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Session/SetRoleFinalStep.php
@@ -0,0 +1,14 @@
+name,
+ $this->table,
+ $this->schema,
+ null,
+ $extension,
+ false,
+ );
+ }
+
+ public function noDependsOnExtension(string $extension) : AlterTriggerFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->table,
+ $this->schema,
+ null,
+ $extension,
+ true,
+ );
+ }
+
+ public function on(string $table, ?string $schema = null) : AlterTriggerActionStep
+ {
+ if ($schema !== null) {
+ return new self(
+ $this->name,
+ $table,
+ $schema,
+ $this->newName,
+ $this->extension,
+ $this->removeDepends,
+ );
+ }
+
+ $identifier = QualifiedIdentifier::parse($table);
+
+ return new self(
+ $this->name,
+ $identifier->name(),
+ $identifier->schema(),
+ $this->newName,
+ $this->extension,
+ $this->removeDepends,
+ );
+ }
+
+ public function renameTo(string $newName) : AlterTriggerFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->table,
+ $this->schema,
+ $newName,
+ null,
+ false,
+ );
+ }
+
+ public function toAst() : RenameStmt|AlterObjectDependsStmt
+ {
+ if ($this->newName !== null && $this->extension !== null) {
+ throw InvalidBuilderStateException::mutuallyExclusiveOptions('RENAME TO', 'DEPENDS ON EXTENSION');
+ }
+
+ if ($this->newName !== null) {
+ return $this->buildRenameAst();
+ }
+
+ return $this->buildDependsAst();
+ }
+
+ private function buildDependsAst() : AlterObjectDependsStmt
+ {
+ $stmt = new AlterObjectDependsStmt();
+
+ $stmt->setObjectType(ObjectType::OBJECT_TRIGGER);
+ $stmt->setRemove($this->removeDepends);
+
+ if ($this->table !== null) {
+ $rangeVar = new RangeVar();
+ $rangeVar->setRelname($this->table);
+ $rangeVar->setRelpersistence('p');
+ $rangeVar->setInh(true);
+
+ if ($this->schema !== null) {
+ $rangeVar->setSchemaname($this->schema);
+ }
+ $stmt->setRelation($rangeVar);
+ }
+
+ $str = new PBString();
+ $str->setSval($this->name);
+ $itemNode = new Node();
+ $itemNode->setString($str);
+
+ $list = new PBList();
+ $list->setItems([$itemNode]);
+
+ $objectNode = new Node();
+ $objectNode->setList($list);
+ $stmt->setObject($objectNode);
+
+ if ($this->extension !== null) {
+ $extStr = new PBString();
+ $extStr->setSval($this->extension);
+ $stmt->setExtname($extStr);
+ }
+
+ return $stmt;
+ }
+
+ private function buildRenameAst() : RenameStmt
+ {
+ $stmt = new RenameStmt();
+
+ $stmt->setRenameType(ObjectType::OBJECT_TRIGGER);
+ $stmt->setSubname($this->name);
+
+ if ($this->newName !== null) {
+ $stmt->setNewname($this->newName);
+ }
+
+ if ($this->table !== null) {
+ $rangeVar = new RangeVar();
+ $rangeVar->setRelname($this->table);
+ $rangeVar->setRelpersistence('p');
+ $rangeVar->setInh(true);
+
+ if ($this->schema !== null) {
+ $rangeVar->setSchemaname($this->schema);
+ }
+ $stmt->setRelation($rangeVar);
+ }
+
+ return $stmt;
+ }
+}
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
new file mode 100644
index 000000000..dd28ea084
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Trigger/AlterTriggerFinalStep.php
@@ -0,0 +1,14 @@
+ $events
+ * @param list $columns
+ * @param list $transitionTables
+ * @param list $functionArgs
+ */
+ private function __construct(
+ private string $name,
+ private bool $replace = false,
+ private bool $constraint = false,
+ private ?TriggerTiming $timing = null,
+ private array $events = [],
+ private array $columns = [],
+ private ?string $table = null,
+ private ?string $schema = null,
+ private ?string $fromTable = null,
+ private bool $deferrable = false,
+ private bool $initDeferred = false,
+ private array $transitionTables = [],
+ private TriggerLevel $level = TriggerLevel::STATEMENT,
+ private ?Condition $when = null,
+ private ?string $functionName = null,
+ private array $functionArgs = [],
+ ) {
+ }
+
+ public static function create(string $name) : CreateTriggerTimingStep
+ {
+ return new self($name);
+ }
+
+ public function after(TriggerEvent ...$events) : CreateTriggerOnStep
+ {
+ return new self(
+ $this->name,
+ $this->replace,
+ $this->constraint,
+ TriggerTiming::AFTER,
+ \array_values($events),
+ [],
+ $this->table,
+ $this->schema,
+ $this->fromTable,
+ $this->deferrable,
+ $this->initDeferred,
+ $this->transitionTables,
+ $this->level,
+ $this->when,
+ $this->functionName,
+ $this->functionArgs,
+ );
+ }
+
+ public function afterUpdateOf(string ...$columns) : CreateTriggerOnStep
+ {
+ return new self(
+ $this->name,
+ $this->replace,
+ $this->constraint,
+ TriggerTiming::AFTER,
+ [TriggerEvent::UPDATE],
+ \array_values($columns),
+ $this->table,
+ $this->schema,
+ $this->fromTable,
+ $this->deferrable,
+ $this->initDeferred,
+ $this->transitionTables,
+ $this->level,
+ $this->when,
+ $this->functionName,
+ $this->functionArgs,
+ );
+ }
+
+ public function before(TriggerEvent ...$events) : CreateTriggerOnStep
+ {
+ return new self(
+ $this->name,
+ $this->replace,
+ $this->constraint,
+ TriggerTiming::BEFORE,
+ \array_values($events),
+ [],
+ $this->table,
+ $this->schema,
+ $this->fromTable,
+ $this->deferrable,
+ $this->initDeferred,
+ $this->transitionTables,
+ $this->level,
+ $this->when,
+ $this->functionName,
+ $this->functionArgs,
+ );
+ }
+
+ public function beforeUpdateOf(string ...$columns) : CreateTriggerOnStep
+ {
+ return new self(
+ $this->name,
+ $this->replace,
+ $this->constraint,
+ TriggerTiming::BEFORE,
+ [TriggerEvent::UPDATE],
+ \array_values($columns),
+ $this->table,
+ $this->schema,
+ $this->fromTable,
+ $this->deferrable,
+ $this->initDeferred,
+ $this->transitionTables,
+ $this->level,
+ $this->when,
+ $this->functionName,
+ $this->functionArgs,
+ );
+ }
+
+ public function constraint() : CreateTriggerTimingStep
+ {
+ return new self(
+ $this->name,
+ $this->replace,
+ true,
+ $this->timing,
+ $this->events,
+ $this->columns,
+ $this->table,
+ $this->schema,
+ $this->fromTable,
+ $this->deferrable,
+ $this->initDeferred,
+ $this->transitionTables,
+ $this->level,
+ $this->when,
+ $this->functionName,
+ $this->functionArgs,
+ );
+ }
+
+ public function deferrable() : CreateTriggerOptionsStep
+ {
+ return new self(
+ $this->name,
+ $this->replace,
+ $this->constraint,
+ $this->timing,
+ $this->events,
+ $this->columns,
+ $this->table,
+ $this->schema,
+ $this->fromTable,
+ true,
+ $this->initDeferred,
+ $this->transitionTables,
+ $this->level,
+ $this->when,
+ $this->functionName,
+ $this->functionArgs,
+ );
+ }
+
+ public function execute(string $functionName, Expression ...$args) : CreateTriggerFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->replace,
+ $this->constraint,
+ $this->timing,
+ $this->events,
+ $this->columns,
+ $this->table,
+ $this->schema,
+ $this->fromTable,
+ $this->deferrable,
+ $this->initDeferred,
+ $this->transitionTables,
+ $this->level,
+ $this->when,
+ $functionName,
+ \array_values($args),
+ );
+ }
+
+ public function forEachRow() : CreateTriggerOptionsStep
+ {
+ return new self(
+ $this->name,
+ $this->replace,
+ $this->constraint,
+ $this->timing,
+ $this->events,
+ $this->columns,
+ $this->table,
+ $this->schema,
+ $this->fromTable,
+ $this->deferrable,
+ $this->initDeferred,
+ $this->transitionTables,
+ TriggerLevel::ROW,
+ $this->when,
+ $this->functionName,
+ $this->functionArgs,
+ );
+ }
+
+ public function forEachStatement() : CreateTriggerOptionsStep
+ {
+ return new self(
+ $this->name,
+ $this->replace,
+ $this->constraint,
+ $this->timing,
+ $this->events,
+ $this->columns,
+ $this->table,
+ $this->schema,
+ $this->fromTable,
+ $this->deferrable,
+ $this->initDeferred,
+ $this->transitionTables,
+ TriggerLevel::STATEMENT,
+ $this->when,
+ $this->functionName,
+ $this->functionArgs,
+ );
+ }
+
+ public function from(string $referencedTable) : CreateTriggerOptionsStep
+ {
+ return new self(
+ $this->name,
+ $this->replace,
+ $this->constraint,
+ $this->timing,
+ $this->events,
+ $this->columns,
+ $this->table,
+ $this->schema,
+ $referencedTable,
+ $this->deferrable,
+ $this->initDeferred,
+ $this->transitionTables,
+ $this->level,
+ $this->when,
+ $this->functionName,
+ $this->functionArgs,
+ );
+ }
+
+ public function initiallyDeferred() : CreateTriggerOptionsStep
+ {
+ return new self(
+ $this->name,
+ $this->replace,
+ $this->constraint,
+ $this->timing,
+ $this->events,
+ $this->columns,
+ $this->table,
+ $this->schema,
+ $this->fromTable,
+ $this->deferrable,
+ true,
+ $this->transitionTables,
+ $this->level,
+ $this->when,
+ $this->functionName,
+ $this->functionArgs,
+ );
+ }
+
+ public function initiallyImmediate() : CreateTriggerOptionsStep
+ {
+ return new self(
+ $this->name,
+ $this->replace,
+ $this->constraint,
+ $this->timing,
+ $this->events,
+ $this->columns,
+ $this->table,
+ $this->schema,
+ $this->fromTable,
+ $this->deferrable,
+ false,
+ $this->transitionTables,
+ $this->level,
+ $this->when,
+ $this->functionName,
+ $this->functionArgs,
+ );
+ }
+
+ public function insteadOf(TriggerEvent ...$events) : CreateTriggerOnStep
+ {
+ return new self(
+ $this->name,
+ $this->replace,
+ $this->constraint,
+ TriggerTiming::INSTEAD_OF,
+ \array_values($events),
+ [],
+ $this->table,
+ $this->schema,
+ $this->fromTable,
+ $this->deferrable,
+ $this->initDeferred,
+ $this->transitionTables,
+ $this->level,
+ $this->when,
+ $this->functionName,
+ $this->functionArgs,
+ );
+ }
+
+ public function notDeferrable() : CreateTriggerOptionsStep
+ {
+ return new self(
+ $this->name,
+ $this->replace,
+ $this->constraint,
+ $this->timing,
+ $this->events,
+ $this->columns,
+ $this->table,
+ $this->schema,
+ $this->fromTable,
+ false,
+ false,
+ $this->transitionTables,
+ $this->level,
+ $this->when,
+ $this->functionName,
+ $this->functionArgs,
+ );
+ }
+
+ public function on(string $table, ?string $schema = null) : CreateTriggerOptionsStep
+ {
+ $identifier = QualifiedIdentifier::parse($table);
+
+ return new self(
+ $this->name,
+ $this->replace,
+ $this->constraint,
+ $this->timing,
+ $this->events,
+ $this->columns,
+ $identifier->name(),
+ $schema ?? $identifier->schema(),
+ $this->fromTable,
+ $this->deferrable,
+ $this->initDeferred,
+ $this->transitionTables,
+ $this->level,
+ $this->when,
+ $this->functionName,
+ $this->functionArgs,
+ );
+ }
+
+ public function orReplace() : CreateTriggerTimingStep
+ {
+ return new self(
+ $this->name,
+ true,
+ $this->constraint,
+ $this->timing,
+ $this->events,
+ $this->columns,
+ $this->table,
+ $this->schema,
+ $this->fromTable,
+ $this->deferrable,
+ $this->initDeferred,
+ $this->transitionTables,
+ $this->level,
+ $this->when,
+ $this->functionName,
+ $this->functionArgs,
+ );
+ }
+
+ public function referencingNewTableAs(string $name) : CreateTriggerOptionsStep
+ {
+ return new self(
+ $this->name,
+ $this->replace,
+ $this->constraint,
+ $this->timing,
+ $this->events,
+ $this->columns,
+ $this->table,
+ $this->schema,
+ $this->fromTable,
+ $this->deferrable,
+ $this->initDeferred,
+ [...$this->transitionTables, ['name' => $name, 'isNew' => true]],
+ $this->level,
+ $this->when,
+ $this->functionName,
+ $this->functionArgs,
+ );
+ }
+
+ public function referencingOldTableAs(string $name) : CreateTriggerOptionsStep
+ {
+ return new self(
+ $this->name,
+ $this->replace,
+ $this->constraint,
+ $this->timing,
+ $this->events,
+ $this->columns,
+ $this->table,
+ $this->schema,
+ $this->fromTable,
+ $this->deferrable,
+ $this->initDeferred,
+ [...$this->transitionTables, ['name' => $name, 'isNew' => false]],
+ $this->level,
+ $this->when,
+ $this->functionName,
+ $this->functionArgs,
+ );
+ }
+
+ public function toAst() : CreateTrigStmt
+ {
+ $stmt = new CreateTrigStmt();
+
+ $stmt->setTrigname($this->name);
+ $stmt->setReplace($this->replace);
+ $stmt->setIsconstraint($this->constraint);
+
+ if ($this->timing !== null) {
+ $stmt->setTiming($this->timing->value);
+ }
+
+ $eventsMask = 0;
+
+ foreach ($this->events as $event) {
+ $eventsMask |= $event->value;
+ }
+ $stmt->setEvents($eventsMask);
+
+ if ($this->columns !== []) {
+ $columnNodes = [];
+
+ foreach ($this->columns as $column) {
+ $str = new PBString();
+ $str->setSval($column);
+ $node = new Node();
+ $node->setString($str);
+ $columnNodes[] = $node;
+ }
+ $stmt->setColumns($columnNodes);
+ }
+
+ if ($this->table !== null) {
+ $rangeVar = new RangeVar();
+ $rangeVar->setRelname($this->table);
+ $rangeVar->setRelpersistence('p');
+ $rangeVar->setInh(true);
+
+ if ($this->schema !== null) {
+ $rangeVar->setSchemaname($this->schema);
+ }
+ $stmt->setRelation($rangeVar);
+ }
+
+ if ($this->fromTable !== null) {
+ $constrrel = new RangeVar();
+ $constrrel->setRelname($this->fromTable);
+ $constrrel->setRelpersistence('p');
+ $constrrel->setInh(true);
+ $stmt->setConstrrel($constrrel);
+ }
+
+ $stmt->setDeferrable($this->deferrable);
+ $stmt->setInitdeferred($this->initDeferred);
+
+ if ($this->transitionTables !== []) {
+ $transitionNodes = [];
+
+ foreach ($this->transitionTables as $trans) {
+ $transition = new TriggerTransition();
+ $transition->setName($trans['name']);
+ $transition->setIsNew($trans['isNew']);
+ $transition->setIsTable(true);
+
+ $node = new Node();
+ $node->setTriggerTransition($transition);
+ $transitionNodes[] = $node;
+ }
+ $stmt->setTransitionRels($transitionNodes);
+ }
+
+ $stmt->setRow($this->level->toBool());
+
+ if ($this->when !== null) {
+ $stmt->setWhenClause($this->when->toAst());
+ }
+
+ if ($this->functionName !== null) {
+ $funcIdentifier = QualifiedIdentifier::parse($this->functionName);
+ $funcnameNodes = [];
+
+ foreach ($funcIdentifier->parts() as $part) {
+ $str = new PBString();
+ $str->setSval($part);
+ $node = new Node();
+ $node->setString($str);
+ $funcnameNodes[] = $node;
+ }
+ $stmt->setFuncname($funcnameNodes);
+ }
+
+ if ($this->functionArgs !== []) {
+ $argNodes = [];
+
+ foreach ($this->functionArgs as $arg) {
+ $argNodes[] = $arg->toAst();
+ }
+ $stmt->setArgs($argNodes);
+ }
+
+ return $stmt;
+ }
+
+ public function when(Condition $condition) : CreateTriggerOptionsStep
+ {
+ return new self(
+ $this->name,
+ $this->replace,
+ $this->constraint,
+ $this->timing,
+ $this->events,
+ $this->columns,
+ $this->table,
+ $this->schema,
+ $this->fromTable,
+ $this->deferrable,
+ $this->initDeferred,
+ $this->transitionTables,
+ $this->level,
+ $condition,
+ $this->functionName,
+ $this->functionArgs,
+ );
+ }
+}
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
new file mode 100644
index 000000000..2fa2e2ffd
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Trigger/CreateTriggerFinalStep.php
@@ -0,0 +1,14 @@
+name,
+ $this->ifExists,
+ $this->table,
+ $this->schema,
+ DropBehavior::DROP_CASCADE,
+ );
+ }
+
+ public function ifExists() : DropTriggerOnStep
+ {
+ return new self(
+ $this->name,
+ true,
+ $this->table,
+ $this->schema,
+ $this->behavior,
+ );
+ }
+
+ public function on(string $table, ?string $schema = null) : DropTriggerFinalStep
+ {
+ if ($schema !== null) {
+ return new self(
+ $this->name,
+ $this->ifExists,
+ $table,
+ $schema,
+ $this->behavior,
+ );
+ }
+
+ $identifier = QualifiedIdentifier::parse($table);
+
+ return new self(
+ $this->name,
+ $this->ifExists,
+ $identifier->name(),
+ $identifier->schema(),
+ $this->behavior,
+ );
+ }
+
+ public function restrict() : DropTriggerFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->ifExists,
+ $this->table,
+ $this->schema,
+ DropBehavior::DROP_RESTRICT,
+ );
+ }
+
+ public function toAst() : DropStmt
+ {
+ $stmt = new DropStmt();
+
+ $stmt->setRemoveType(ObjectType::OBJECT_TRIGGER);
+ $stmt->setMissingOk($this->ifExists);
+ $stmt->setBehavior($this->behavior);
+
+ $listItems = [];
+
+ if ($this->schema !== null) {
+ $schemaStr = new PBString();
+ $schemaStr->setSval($this->schema);
+ $schemaNode = new Node();
+ $schemaNode->setString($schemaStr);
+ $listItems[] = $schemaNode;
+ }
+
+ if ($this->table !== null) {
+ $tableStr = new PBString();
+ $tableStr->setSval($this->table);
+ $tableNode = new Node();
+ $tableNode->setString($tableStr);
+ $listItems[] = $tableNode;
+ }
+
+ $nameStr = new PBString();
+ $nameStr->setSval($this->name);
+ $nameNode = new Node();
+ $nameNode->setString($nameStr);
+ $listItems[] = $nameNode;
+
+ $list = new PBList();
+ $list->setItems($listItems);
+
+ $objectNode = new Node();
+ $objectNode->setList($list);
+
+ $stmt->setObjects([$objectNode]);
+
+ return $stmt;
+ }
+}
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
new file mode 100644
index 000000000..3d9a41ac1
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Trigger/DropTriggerFinalStep.php
@@ -0,0 +1,18 @@
+ $tables
+ */
+ private function __construct(
+ private array $tables,
+ private bool $restartIdentity = false,
+ private int $behavior = DropBehavior::DROP_BEHAVIOR_UNDEFINED,
+ ) {
+ }
+
+ public static function create(string ...$tables) : TruncateFinalStep
+ {
+ return new self(\array_values($tables));
+ }
+
+ public function cascade() : TruncateFinalStep
+ {
+ return new self(
+ $this->tables,
+ $this->restartIdentity,
+ DropBehavior::DROP_CASCADE,
+ );
+ }
+
+ public function continueIdentity() : TruncateFinalStep
+ {
+ return new self(
+ $this->tables,
+ false,
+ $this->behavior,
+ );
+ }
+
+ public function restartIdentity() : TruncateFinalStep
+ {
+ return new self(
+ $this->tables,
+ true,
+ $this->behavior,
+ );
+ }
+
+ public function restrict() : TruncateFinalStep
+ {
+ return new self(
+ $this->tables,
+ $this->restartIdentity,
+ DropBehavior::DROP_RESTRICT,
+ );
+ }
+
+ public function toAst() : TruncateStmt
+ {
+ $stmt = new TruncateStmt();
+
+ if ($this->restartIdentity) {
+ $stmt->setRestartSeqs(true);
+ }
+
+ if ($this->behavior !== DropBehavior::DROP_BEHAVIOR_UNDEFINED) {
+ $stmt->setBehavior($this->behavior);
+ }
+
+ $relations = [];
+
+ foreach ($this->tables as $table) {
+ $relations[] = $this->createRangeVarNode($table);
+ }
+
+ $stmt->setRelations($relations);
+
+ return $stmt;
+ }
+
+ private function createRangeVarNode(string $table) : Node
+ {
+ $identifier = QualifiedIdentifier::parse($table);
+
+ $rangeVar = new RangeVar();
+ $rangeVar->setRelpersistence('p');
+ $rangeVar->setInh(true);
+
+ if ($identifier->hasSchema()) {
+ $rangeVar->setSchemaname($identifier->schema());
+ }
+
+ $rangeVar->setRelname($identifier->name());
+
+ $node = new Node();
+ $node->setRangeVar($rangeVar);
+
+ return $node;
+ }
+}
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
new file mode 100644
index 000000000..b2620fcb6
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Truncate/TruncateFinalStep.php
@@ -0,0 +1,22 @@
+name(), $identifier->schema());
+ }
+
+ public function addValue(string $value) : AlterEnumTypeFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ null,
+ $value,
+ null,
+ false,
+ $this->skipIfExists,
+ );
+ }
+
+ public function addValueAfter(string $value, string $neighbor) : AlterEnumTypeFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ null,
+ $value,
+ $neighbor,
+ true,
+ $this->skipIfExists,
+ );
+ }
+
+ public function addValueBefore(string $value, string $neighbor) : AlterEnumTypeFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ null,
+ $value,
+ $neighbor,
+ false,
+ $this->skipIfExists,
+ );
+ }
+
+ public function ifNotExists() : AlterEnumTypeFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ $this->oldVal,
+ $this->newVal,
+ $this->neighbor,
+ $this->isAfter,
+ true,
+ );
+ }
+
+ public function renameValue(string $oldValue, string $newValue) : AlterEnumTypeFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ $oldValue,
+ $newValue,
+ null,
+ false,
+ false,
+ );
+ }
+
+ public function toAst() : AlterEnumStmt
+ {
+ $stmt = new AlterEnumStmt();
+
+ $typeNameNodes = [];
+
+ if ($this->schema !== null) {
+ $str = new PBString();
+ $str->setSval($this->schema);
+ $node = new Node();
+ $node->setString($str);
+ $typeNameNodes[] = $node;
+ }
+
+ $str = new PBString();
+ $str->setSval($this->name);
+ $node = new Node();
+ $node->setString($str);
+ $typeNameNodes[] = $node;
+
+ $stmt->setTypeName($typeNameNodes);
+
+ if ($this->oldVal !== null) {
+ $stmt->setOldVal($this->oldVal);
+ }
+
+ if ($this->newVal !== null) {
+ $stmt->setNewVal($this->newVal);
+ }
+
+ if ($this->neighbor !== null) {
+ $stmt->setNewValNeighbor($this->neighbor);
+ $stmt->setNewValIsAfter($this->isAfter);
+ }
+
+ $stmt->setSkipIfNewValExists($this->skipIfExists);
+
+ return $stmt;
+ }
+}
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
new file mode 100644
index 000000000..b8d986b43
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Type/AlterEnumTypeFinalStep.php
@@ -0,0 +1,16 @@
+ $attributes
+ */
+ private function __construct(
+ private string $name,
+ private ?string $schema = null,
+ private array $attributes = [],
+ ) {
+ }
+
+ public static function create(string $name) : CreateCompositeTypeAttributesStep
+ {
+ $identifier = QualifiedIdentifier::parse($name);
+
+ return new self($identifier->name(), $identifier->schema());
+ }
+
+ public function attributes(TypeAttribute ...$attributes) : CreateCompositeTypeFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ \array_values($attributes),
+ );
+ }
+
+ public function toAst() : CompositeTypeStmt
+ {
+ $stmt = new CompositeTypeStmt();
+
+ $typevar = new RangeVar();
+ $typevar->setRelname($this->name);
+ $typevar->setRelpersistence('p');
+ $typevar->setInh(true);
+
+ if ($this->schema !== null) {
+ $typevar->setSchemaname($this->schema);
+ }
+
+ $stmt->setTypevar($typevar);
+
+ $coldefNodes = [];
+
+ foreach ($this->attributes as $attr) {
+ $coldef = new ColumnDef();
+ $coldef->setColname($attr->name);
+ $coldef->setTypeName($attr->type->toAst());
+
+ if ($attr->collation !== null) {
+ $collClause = new CollateClause();
+
+ $collNameNodes = [];
+ $str = new PBString();
+ $str->setSval($attr->collation);
+ $node = new Node();
+ $node->setString($str);
+ $collNameNodes[] = $node;
+
+ $collClause->setCollname($collNameNodes);
+ $coldef->setCollClause($collClause);
+ }
+
+ $node = new Node();
+ $node->setColumnDef($coldef);
+ $coldefNodes[] = $node;
+ }
+
+ $stmt->setColdeflist($coldefNodes);
+
+ return $stmt;
+ }
+}
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
new file mode 100644
index 000000000..550cb5013
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Type/CreateCompositeTypeFinalStep.php
@@ -0,0 +1,14 @@
+ $labels
+ */
+ private function __construct(
+ private string $name,
+ private ?string $schema = null,
+ private array $labels = [],
+ ) {
+ }
+
+ public static function create(string $name) : CreateEnumTypeLabelsStep
+ {
+ $identifier = QualifiedIdentifier::parse($name);
+
+ return new self($identifier->name(), $identifier->schema());
+ }
+
+ public function labels(string ...$labels) : CreateEnumTypeFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ \array_values($labels),
+ );
+ }
+
+ public function toAst() : CreateEnumStmt
+ {
+ $stmt = new CreateEnumStmt();
+
+ $typeNameNodes = [];
+
+ if ($this->schema !== null) {
+ $str = new PBString();
+ $str->setSval($this->schema);
+ $node = new Node();
+ $node->setString($str);
+ $typeNameNodes[] = $node;
+ }
+
+ $str = new PBString();
+ $str->setSval($this->name);
+ $node = new Node();
+ $node->setString($str);
+ $typeNameNodes[] = $node;
+
+ $stmt->setTypeName($typeNameNodes);
+
+ $valNodes = [];
+
+ foreach ($this->labels as $label) {
+ $str = new PBString();
+ $str->setSval($label);
+ $node = new Node();
+ $node->setString($str);
+ $valNodes[] = $node;
+ }
+
+ $stmt->setVals($valNodes);
+
+ return $stmt;
+ }
+}
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
new file mode 100644
index 000000000..3e59001b1
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Type/CreateEnumTypeFinalStep.php
@@ -0,0 +1,14 @@
+ $params
+ */
+ private function __construct(
+ private string $name,
+ private ?string $schema = null,
+ private array $params = [],
+ ) {
+ }
+
+ public static function create(string $name) : CreateRangeTypeSubtypeStep
+ {
+ $identifier = QualifiedIdentifier::parse($name);
+
+ return new self($identifier->name(), $identifier->schema());
+ }
+
+ public function canonical(string $function) : CreateRangeTypeOptionsStep
+ {
+ return $this->withStringParam('canonical', $function);
+ }
+
+ public function collation(string $collation) : CreateRangeTypeOptionsStep
+ {
+ return $this->withStringParam('collation', $collation);
+ }
+
+ public function multirangeTypeName(string $name) : CreateRangeTypeOptionsStep
+ {
+ return $this->withStringParam('multirange_type_name', $name);
+ }
+
+ public function subtype(string $type) : CreateRangeTypeOptionsStep
+ {
+ return $this->withTypeNameParam('subtype', $type);
+ }
+
+ public function subtypeDiff(string $function) : CreateRangeTypeOptionsStep
+ {
+ return $this->withStringParam('subtype_diff', $function);
+ }
+
+ public function subtypeOpclass(string $opclass) : CreateRangeTypeOptionsStep
+ {
+ return $this->withStringParam('subtype_opclass', $opclass);
+ }
+
+ public function toAst() : CreateRangeStmt
+ {
+ $stmt = new CreateRangeStmt();
+
+ $typeNameNodes = [];
+
+ if ($this->schema !== null) {
+ $str = new PBString();
+ $str->setSval($this->schema);
+ $node = new Node();
+ $node->setString($str);
+ $typeNameNodes[] = $node;
+ }
+
+ $str = new PBString();
+ $str->setSval($this->name);
+ $node = new Node();
+ $node->setString($str);
+ $typeNameNodes[] = $node;
+
+ $stmt->setTypeName($typeNameNodes);
+
+ $paramNodes = [];
+
+ foreach ($this->params as $param) {
+ $defElem = new DefElem();
+ $defElem->setDefname($param['name']);
+ $defElem->setArg($param['arg']);
+
+ $node = new Node();
+ $node->setDefElem($defElem);
+ $paramNodes[] = $node;
+ }
+
+ if ($paramNodes !== []) {
+ $stmt->setParams($paramNodes);
+ }
+
+ return $stmt;
+ }
+
+ private function withParam(string $name, Node $arg) : self
+ {
+ $newParams = $this->params;
+ $newParams[] = ['name' => $name, 'arg' => $arg];
+
+ return new self(
+ $this->name,
+ $this->schema,
+ $newParams,
+ );
+ }
+
+ private function withStringParam(string $name, string $value) : self
+ {
+ $str = new PBString();
+ $str->setSval($value);
+
+ $argNode = new Node();
+ $argNode->setString($str);
+
+ return $this->withParam($name, $argNode);
+ }
+
+ private function withTypeNameParam(string $name, string $type) : self
+ {
+ $typeName = new TypeName();
+
+ $typeNames = [];
+ $str = new PBString();
+ $str->setSval($type);
+ $node = new Node();
+ $node->setString($str);
+ $typeNames[] = $node;
+ $typeName->setNames($typeNames);
+
+ $argNode = new Node();
+ $argNode->setTypeName($typeName);
+
+ return $this->withParam($name, $argNode);
+ }
+}
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
new file mode 100644
index 000000000..eb1126c2d
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Type/CreateRangeTypeFinalStep.php
@@ -0,0 +1,14 @@
+ $names
+ */
+ private function __construct(
+ private array $names,
+ private bool $ifExists = false,
+ private int $behavior = DropBehavior::DROP_RESTRICT,
+ ) {
+ }
+
+ public static function create(string ...$names) : DropTypeFinalStep
+ {
+ return new self(\array_values($names));
+ }
+
+ public function cascade() : DropTypeFinalStep
+ {
+ return new self(
+ $this->names,
+ $this->ifExists,
+ DropBehavior::DROP_CASCADE,
+ );
+ }
+
+ public function ifExists() : DropTypeFinalStep
+ {
+ return new self(
+ $this->names,
+ true,
+ $this->behavior,
+ );
+ }
+
+ public function restrict() : DropTypeFinalStep
+ {
+ return new self(
+ $this->names,
+ $this->ifExists,
+ DropBehavior::DROP_RESTRICT,
+ );
+ }
+
+ public function toAst() : DropStmt
+ {
+ $stmt = new DropStmt();
+ $stmt->setRemoveType(ObjectType::OBJECT_TYPE);
+ $stmt->setBehavior($this->behavior);
+ $stmt->setMissingOk($this->ifExists);
+
+ $objects = [];
+
+ foreach ($this->names as $name) {
+ $identifier = QualifiedIdentifier::parse($name);
+ $nameNodes = [];
+
+ foreach ($identifier->parts() as $part) {
+ $str = new PBString();
+ $str->setSval($part);
+ $node = new Node();
+ $node->setString($str);
+ $nameNodes[] = $node;
+ }
+
+ $typeName = new TypeName();
+ $typeName->setNames($nameNodes);
+ $typeName->setTypemod(-1);
+
+ $node = new Node();
+ $node->setTypeName($typeName);
+ $objects[] = $node;
+ }
+
+ $stmt->setObjects($objects);
+
+ return $stmt;
+ }
+}
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
new file mode 100644
index 000000000..e71130110
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/Type/DropTypeFinalStep.php
@@ -0,0 +1,20 @@
+name, $this->type, $collation);
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterMaterializedView/AlterMatViewActionStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterMaterializedView/AlterMatViewActionStep.php
new file mode 100644
index 000000000..94442c96b
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterMaterializedView/AlterMatViewActionStep.php
@@ -0,0 +1,18 @@
+setObjtype(ObjectType::OBJECT_MATVIEW);
+
+ $rangeVar = new RangeVar();
+ $rangeVar->setRelname($this->view);
+ $rangeVar->setInh(true);
+ $rangeVar->setRelpersistence('p');
+
+ if ($this->schema !== null) {
+ $rangeVar->setSchemaname($this->schema);
+ }
+
+ $stmt->setRelation($rangeVar);
+
+ $cmd = new AlterTableCmd();
+ $cmd->setSubtype(AlterTableType::AT_ChangeOwner);
+ $cmd->setBehavior(DropBehavior::DROP_RESTRICT);
+
+ $roleSpec = new RoleSpec();
+ $roleSpec->setRoletype(RoleSpecType::ROLESPEC_CSTRING);
+ $roleSpec->setRolename($this->owner);
+
+ $cmd->setNewowner($roleSpec);
+
+ $cmdNode = new Node();
+ $cmdNode->setAlterTableCmd($cmd);
+
+ $stmt->setCmds([$cmdNode]);
+
+ return $stmt;
+ }
+}
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
new file mode 100644
index 000000000..b2007f20b
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterMaterializedView/AlterMatViewOwnerFinalStep.php
@@ -0,0 +1,14 @@
+setObjectType(ObjectType::OBJECT_MATVIEW);
+
+ $rangeVar = new RangeVar();
+ $rangeVar->setRelname($this->view);
+ $rangeVar->setInh(true);
+ $rangeVar->setRelpersistence('p');
+
+ if ($this->schema !== null) {
+ $rangeVar->setSchemaname($this->schema);
+ }
+
+ $stmt->setRelation($rangeVar);
+ $stmt->setNewschema($this->newSchema);
+
+ if ($this->ifExists) {
+ $stmt->setMissingOk(true);
+ }
+
+ return $stmt;
+ }
+}
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
new file mode 100644
index 000000000..1f3b29dcb
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterMaterializedView/AlterMatViewSchemaFinalStep.php
@@ -0,0 +1,14 @@
+setObjtype(ObjectType::OBJECT_MATVIEW);
+
+ $rangeVar = new RangeVar();
+ $rangeVar->setRelname($this->view);
+ $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(AlterTableType::AT_SetTableSpace);
+ $cmd->setName($this->tablespace);
+ $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/View/AlterMaterializedView/AlterMatViewTablespaceFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterMaterializedView/AlterMatViewTablespaceFinalStep.php
new file mode 100644
index 000000000..edf1ca86c
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterMaterializedView/AlterMatViewTablespaceFinalStep.php
@@ -0,0 +1,14 @@
+name(), $schema ?? $identifier->schema());
+ }
+
+ public function ifExists() : AlterMatViewActionStep
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ true,
+ );
+ }
+
+ public function ownerTo(string $owner) : AlterMatViewOwnerFinalStep
+ {
+ return AlterMatViewOwnerBuilder::create($this->name ?? '', $this->schema, $owner);
+ }
+
+ public function renameTo(string $newName) : RenameMatViewFinalStep
+ {
+ return RenameMatViewBuilder::create($this->name ?? '', $this->schema, $newName, $this->ifExists);
+ }
+
+ public function setSchema(string $schema) : AlterMatViewSchemaFinalStep
+ {
+ return AlterMatViewSchemaBuilder::create($this->name ?? '', $this->schema, $schema, $this->ifExists);
+ }
+
+ public function setTablespace(string $tablespace) : AlterMatViewTablespaceFinalStep
+ {
+ return AlterMatViewTablespaceBuilder::create($this->name ?? '', $this->schema, $tablespace, $this->ifExists);
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterMaterializedView/RenameMatViewBuilder.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterMaterializedView/RenameMatViewBuilder.php
new file mode 100644
index 000000000..30d01b03e
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterMaterializedView/RenameMatViewBuilder.php
@@ -0,0 +1,51 @@
+setRenameType(ObjectType::OBJECT_MATVIEW);
+
+ $rangeVar = new RangeVar();
+ $rangeVar->setRelname($this->view);
+ $rangeVar->setInh(true);
+ $rangeVar->setRelpersistence('p');
+
+ if ($this->schema !== null) {
+ $rangeVar->setSchemaname($this->schema);
+ }
+
+ $stmt->setRelation($rangeVar);
+ $stmt->setNewname($this->newName);
+ $stmt->setBehavior(DropBehavior::DROP_RESTRICT);
+
+ if ($this->ifExists) {
+ $stmt->setMissingOk(true);
+ }
+
+ return $stmt;
+ }
+}
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
new file mode 100644
index 000000000..e6343261c
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterMaterializedView/RenameMatViewFinalStep.php
@@ -0,0 +1,14 @@
+name(), $identifier->schema());
+ }
+
+ public function ifExists() : AlterViewActionStep
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ true,
+ );
+ }
+
+ public function ownerTo(string $owner) : AlterViewOwnerFinalStep
+ {
+ return AlterViewOwnerBuilder::create($this->name ?? '', $this->schema, $owner);
+ }
+
+ public function renameTo(string $newName) : RenameViewFinalStep
+ {
+ return RenameViewBuilder::create($this->name ?? '', $this->schema, $newName, $this->ifExists);
+ }
+
+ public function setSchema(string $schema) : AlterViewSchemaFinalStep
+ {
+ return AlterViewSchemaBuilder::create($this->name ?? '', $this->schema, $schema, $this->ifExists);
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterView/AlterViewOwnerBuilder.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterView/AlterViewOwnerBuilder.php
new file mode 100644
index 000000000..1a437ff27
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterView/AlterViewOwnerBuilder.php
@@ -0,0 +1,59 @@
+setObjtype(ObjectType::OBJECT_VIEW);
+
+ $rangeVar = new RangeVar();
+ $rangeVar->setRelname($this->view);
+ $rangeVar->setInh(true);
+ $rangeVar->setRelpersistence('p');
+
+ if ($this->schema !== null) {
+ $rangeVar->setSchemaname($this->schema);
+ }
+
+ $stmt->setRelation($rangeVar);
+
+ $cmd = new AlterTableCmd();
+ $cmd->setSubtype(AlterTableType::AT_ChangeOwner);
+ $cmd->setBehavior(DropBehavior::DROP_RESTRICT);
+
+ $roleSpec = new RoleSpec();
+ $roleSpec->setRoletype(RoleSpecType::ROLESPEC_CSTRING);
+ $roleSpec->setRolename($this->owner);
+
+ $cmd->setNewowner($roleSpec);
+
+ $cmdNode = new Node();
+ $cmdNode->setAlterTableCmd($cmd);
+
+ $stmt->setCmds([$cmdNode]);
+
+ return $stmt;
+ }
+}
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
new file mode 100644
index 000000000..fbf420b18
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterView/AlterViewOwnerFinalStep.php
@@ -0,0 +1,14 @@
+setObjectType(ObjectType::OBJECT_VIEW);
+
+ $rangeVar = new RangeVar();
+ $rangeVar->setRelname($this->view);
+ $rangeVar->setInh(true);
+ $rangeVar->setRelpersistence('p');
+
+ if ($this->schema !== null) {
+ $rangeVar->setSchemaname($this->schema);
+ }
+
+ $stmt->setRelation($rangeVar);
+ $stmt->setNewschema($this->newSchema);
+
+ if ($this->ifExists) {
+ $stmt->setMissingOk(true);
+ }
+
+ return $stmt;
+ }
+}
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
new file mode 100644
index 000000000..589ca3637
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterView/AlterViewSchemaFinalStep.php
@@ -0,0 +1,14 @@
+setRenameType(ObjectType::OBJECT_VIEW);
+
+ $rangeVar = new RangeVar();
+ $rangeVar->setRelname($this->view);
+ $rangeVar->setInh(true);
+ $rangeVar->setRelpersistence('p');
+
+ if ($this->schema !== null) {
+ $rangeVar->setSchemaname($this->schema);
+ }
+
+ $stmt->setRelation($rangeVar);
+ $stmt->setNewname($this->newName);
+ $stmt->setBehavior(DropBehavior::DROP_RESTRICT);
+
+ if ($this->ifExists) {
+ $stmt->setMissingOk(true);
+ }
+
+ return $stmt;
+ }
+}
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
new file mode 100644
index 000000000..db5067241
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/AlterView/RenameViewFinalStep.php
@@ -0,0 +1,14 @@
+ $columns
+ */
+ private function __construct(
+ private ?string $name = null,
+ private ?string $schema = null,
+ private array $columns = [],
+ private ?SelectFinalStep $query = null,
+ private bool $ifNotExists = false,
+ private ?string $accessMethod = null,
+ private ?string $tablespace = null,
+ private ?bool $skipData = null,
+ ) {
+ }
+
+ public static function create(string $name, ?string $schema = null) : CreateMatViewOptionsStep
+ {
+ if ($schema !== null) {
+ return new self($name, $schema);
+ }
+
+ $identifier = QualifiedIdentifier::parse($name);
+
+ return new self($identifier->name(), $identifier->schema());
+ }
+
+ public function as(SelectFinalStep $query) : CreateMatViewDataStep
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ $this->columns,
+ $query,
+ $this->ifNotExists,
+ $this->accessMethod,
+ $this->tablespace,
+ $this->skipData,
+ );
+ }
+
+ public function columns(string ...$columns) : CreateMatViewAsStep
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ \array_values($columns),
+ $this->query,
+ $this->ifNotExists,
+ $this->accessMethod,
+ $this->tablespace,
+ $this->skipData,
+ );
+ }
+
+ public function ifNotExists() : CreateMatViewOptionsStep
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ $this->columns,
+ $this->query,
+ true,
+ $this->accessMethod,
+ $this->tablespace,
+ $this->skipData,
+ );
+ }
+
+ public function tablespace(string $tablespace) : CreateMatViewDataStep
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ $this->columns,
+ $this->query,
+ $this->ifNotExists,
+ $this->accessMethod,
+ $tablespace,
+ $this->skipData,
+ );
+ }
+
+ public function toAst() : CreateTableAsStmt
+ {
+ if ($this->name === null || $this->name === '') {
+ throw InvalidExpressionException::invalidValue('materialized view name', 'null or empty');
+ }
+
+ if ($this->query === null) {
+ throw InvalidExpressionException::invalidValue('query', 'null');
+ }
+
+ $stmt = new CreateTableAsStmt();
+
+ $stmt->setObjtype(ObjectType::OBJECT_MATVIEW);
+
+ $into = new IntoClause();
+
+ $rangeVar = new RangeVar();
+ $rangeVar->setRelname($this->name);
+ $rangeVar->setRelpersistence('p');
+ $rangeVar->setInh(true);
+
+ if ($this->schema !== null) {
+ $rangeVar->setSchemaname($this->schema);
+ }
+
+ $into->setRel($rangeVar);
+
+ if ($this->columns !== []) {
+ $colNames = [];
+
+ foreach ($this->columns as $column) {
+ $str = new PBString();
+ $str->setSval($column);
+ $node = new Node();
+ $node->setString($str);
+ $colNames[] = $node;
+ }
+
+ $into->setColNames($colNames);
+ }
+
+ if ($this->accessMethod !== null) {
+ $into->setAccessMethod($this->accessMethod);
+ }
+
+ if ($this->tablespace !== null) {
+ $into->setTableSpaceName($this->tablespace);
+ }
+
+ if ($this->skipData !== null) {
+ $into->setSkipData($this->skipData);
+ }
+
+ $stmt->setInto($into);
+
+ $queryNode = new Node();
+ $queryNode->setSelectStmt($this->query->toAst());
+ $stmt->setQuery($queryNode);
+
+ if ($this->ifNotExists) {
+ $stmt->setIfNotExists(true);
+ }
+
+ return $stmt;
+ }
+
+ public function using(string $method) : CreateMatViewOptionsStep
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ $this->columns,
+ $this->query,
+ $this->ifNotExists,
+ $method,
+ $this->tablespace,
+ $this->skipData,
+ );
+ }
+
+ public function withData() : CreateMatViewFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ $this->columns,
+ $this->query,
+ $this->ifNotExists,
+ $this->accessMethod,
+ $this->tablespace,
+ false,
+ );
+ }
+
+ public function withNoData() : CreateMatViewFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ $this->columns,
+ $this->query,
+ $this->ifNotExists,
+ $this->accessMethod,
+ $this->tablespace,
+ true,
+ );
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/CreateView/CreateViewAsStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/CreateView/CreateViewAsStep.php
new file mode 100644
index 000000000..4fbfe64f7
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/CreateView/CreateViewAsStep.php
@@ -0,0 +1,12 @@
+ $columns
+ */
+ private function __construct(
+ private ?string $name = null,
+ private ?string $schema = null,
+ private array $columns = [],
+ private ?SelectFinalStep $query = null,
+ private bool $replace = false,
+ private bool $temporary = false,
+ private bool $recursive = false,
+ private ?int $checkOption = null,
+ ) {
+ }
+
+ public static function create(string $name, ?string $schema = null) : CreateViewOptionsStep
+ {
+ if ($schema !== null) {
+ return new self($name, $schema);
+ }
+
+ $identifier = QualifiedIdentifier::parse($name);
+
+ return new self($identifier->name(), $identifier->schema());
+ }
+
+ public function as(SelectFinalStep $query) : CreateViewCheckOptionStep
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ $this->columns,
+ $query,
+ $this->replace,
+ $this->temporary,
+ $this->recursive,
+ $this->checkOption,
+ );
+ }
+
+ public function columns(string ...$columns) : CreateViewAsStep
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ \array_values($columns),
+ $this->query,
+ $this->replace,
+ $this->temporary,
+ $this->recursive,
+ $this->checkOption,
+ );
+ }
+
+ public function orReplace() : CreateViewOptionsStep
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ $this->columns,
+ $this->query,
+ true,
+ $this->temporary,
+ $this->recursive,
+ $this->checkOption,
+ );
+ }
+
+ public function recursive() : CreateViewOptionsStep
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ $this->columns,
+ $this->query,
+ $this->replace,
+ $this->temporary,
+ true,
+ $this->checkOption,
+ );
+ }
+
+ public function temporary() : CreateViewOptionsStep
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ $this->columns,
+ $this->query,
+ $this->replace,
+ true,
+ $this->recursive,
+ $this->checkOption,
+ );
+ }
+
+ public function toAst() : ViewStmt
+ {
+ if ($this->name === null || $this->name === '') {
+ throw InvalidExpressionException::invalidValue('view name', 'null or empty');
+ }
+
+ if ($this->query === null) {
+ throw InvalidExpressionException::invalidValue('query', 'null');
+ }
+
+ $stmt = new ViewStmt();
+
+ $rangeVar = new RangeVar();
+ $rangeVar->setRelname($this->name);
+
+ if ($this->temporary) {
+ $rangeVar->setRelpersistence('t');
+ } else {
+ $rangeVar->setRelpersistence('p');
+ }
+
+ $rangeVar->setInh(true);
+
+ if ($this->schema !== null) {
+ $rangeVar->setSchemaname($this->schema);
+ }
+
+ $stmt->setView($rangeVar);
+
+ $stmt->setReplace($this->replace);
+
+ if ($this->columns !== []) {
+ $aliases = [];
+
+ foreach ($this->columns as $column) {
+ $str = new PBString();
+ $str->setSval($column);
+ $node = new Node();
+ $node->setString($str);
+ $aliases[] = $node;
+ }
+
+ $stmt->setAliases($aliases);
+ }
+
+ $queryNode = new Node();
+ $queryNode->setSelectStmt($this->query->toAst());
+ $stmt->setQuery($queryNode);
+
+ if ($this->checkOption !== null) {
+ $stmt->setWithCheckOption($this->checkOption);
+ }
+
+ return $stmt;
+ }
+
+ public function withCascadedCheckOption() : CreateViewFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ $this->columns,
+ $this->query,
+ $this->replace,
+ $this->temporary,
+ $this->recursive,
+ ViewCheckOption::CASCADED_CHECK_OPTION,
+ );
+ }
+
+ public function withCheckOption() : CreateViewFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ $this->columns,
+ $this->query,
+ $this->replace,
+ $this->temporary,
+ $this->recursive,
+ ViewCheckOption::CASCADED_CHECK_OPTION,
+ );
+ }
+
+ public function withLocalCheckOption() : CreateViewFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ $this->columns,
+ $this->query,
+ $this->replace,
+ $this->temporary,
+ $this->recursive,
+ ViewCheckOption::LOCAL_CHECK_OPTION,
+ );
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/CreateView/CreateViewCheckOptionStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/CreateView/CreateViewCheckOptionStep.php
new file mode 100644
index 000000000..cffd4ef3c
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/CreateView/CreateViewCheckOptionStep.php
@@ -0,0 +1,14 @@
+ $views
+ */
+ private function __construct(
+ private array $views,
+ private bool $ifExists = false,
+ private int $behavior = DropBehavior::DROP_BEHAVIOR_UNDEFINED,
+ ) {
+ }
+
+ public static function create(string ...$views) : DropMatViewFinalStep
+ {
+ return new self(\array_values($views));
+ }
+
+ public function cascade() : DropMatViewFinalStep
+ {
+ return new self(
+ $this->views,
+ $this->ifExists,
+ DropBehavior::DROP_CASCADE,
+ );
+ }
+
+ public function ifExists() : DropMatViewFinalStep
+ {
+ return new self(
+ $this->views,
+ true,
+ $this->behavior,
+ );
+ }
+
+ public function restrict() : DropMatViewFinalStep
+ {
+ return new self(
+ $this->views,
+ $this->ifExists,
+ DropBehavior::DROP_RESTRICT,
+ );
+ }
+
+ public function toAst() : DropStmt
+ {
+ $stmt = new DropStmt();
+ $stmt->setRemoveType(ObjectType::OBJECT_MATVIEW);
+
+ if ($this->ifExists) {
+ $stmt->setMissingOk(true);
+ }
+
+ if ($this->behavior !== DropBehavior::DROP_BEHAVIOR_UNDEFINED) {
+ $stmt->setBehavior($this->behavior);
+ }
+
+ $objects = [];
+
+ foreach ($this->views as $view) {
+ $objects[] = $this->createViewListNode($view);
+ }
+
+ $stmt->setObjects($objects);
+
+ return $stmt;
+ }
+
+ private function createViewListNode(string $view) : Node
+ {
+ $identifier = QualifiedIdentifier::parse($view);
+ $listItems = [];
+
+ foreach ($identifier->parts() as $part) {
+ $str = new PBString();
+ $str->setSval($part);
+
+ $strNode = new Node();
+ $strNode->setString($str);
+ $listItems[] = $strNode;
+ }
+
+ $list = new PBList();
+ $list->setItems($listItems);
+
+ $node = new Node();
+ $node->setList($list);
+
+ return $node;
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/DropView/DropViewBuilder.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/DropView/DropViewBuilder.php
new file mode 100644
index 000000000..0d2f4e12e
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/DropView/DropViewBuilder.php
@@ -0,0 +1,102 @@
+ $views
+ */
+ private function __construct(
+ private array $views,
+ private bool $ifExists = false,
+ private int $behavior = DropBehavior::DROP_BEHAVIOR_UNDEFINED,
+ ) {
+ }
+
+ public static function create(string ...$views) : DropViewFinalStep
+ {
+ return new self(\array_values($views));
+ }
+
+ public function cascade() : DropViewFinalStep
+ {
+ return new self(
+ $this->views,
+ $this->ifExists,
+ DropBehavior::DROP_CASCADE,
+ );
+ }
+
+ public function ifExists() : DropViewFinalStep
+ {
+ return new self(
+ $this->views,
+ true,
+ $this->behavior,
+ );
+ }
+
+ public function restrict() : DropViewFinalStep
+ {
+ return new self(
+ $this->views,
+ $this->ifExists,
+ DropBehavior::DROP_RESTRICT,
+ );
+ }
+
+ public function toAst() : DropStmt
+ {
+ $stmt = new DropStmt();
+ $stmt->setRemoveType(ObjectType::OBJECT_VIEW);
+
+ if ($this->ifExists) {
+ $stmt->setMissingOk(true);
+ }
+
+ if ($this->behavior !== DropBehavior::DROP_BEHAVIOR_UNDEFINED) {
+ $stmt->setBehavior($this->behavior);
+ }
+
+ $objects = [];
+
+ foreach ($this->views as $view) {
+ $objects[] = $this->createViewListNode($view);
+ }
+
+ $stmt->setObjects($objects);
+
+ return $stmt;
+ }
+
+ private function createViewListNode(string $view) : Node
+ {
+ $identifier = QualifiedIdentifier::parse($view);
+ $listItems = [];
+
+ foreach ($identifier->parts() as $part) {
+ $str = new PBString();
+ $str->setSval($part);
+
+ $strNode = new Node();
+ $strNode->setString($str);
+ $listItems[] = $strNode;
+ }
+
+ $list = new PBList();
+ $list->setItems($listItems);
+
+ $node = new Node();
+ $node->setList($list);
+
+ return $node;
+ }
+}
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
new file mode 100644
index 000000000..4013f7ccc
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Schema/View/DropView/DropViewFinalStep.php
@@ -0,0 +1,20 @@
+name(), $identifier->schema());
+ }
+
+ public function concurrently() : RefreshMatViewFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ true,
+ $this->skipData,
+ );
+ }
+
+ public function toAst() : RefreshMatViewStmt
+ {
+ if ($this->name === null || $this->name === '') {
+ throw InvalidExpressionException::invalidValue('materialized view name', 'null or empty');
+ }
+
+ $stmt = new RefreshMatViewStmt();
+
+ $rangeVar = new RangeVar();
+ $rangeVar->setRelname($this->name);
+ $rangeVar->setRelpersistence('p');
+ $rangeVar->setInh(true);
+
+ if ($this->schema !== null) {
+ $rangeVar->setSchemaname($this->schema);
+ }
+
+ $stmt->setRelation($rangeVar);
+
+ if ($this->concurrent) {
+ $stmt->setConcurrent(true);
+ }
+
+ if ($this->skipData !== null) {
+ $stmt->setSkipData($this->skipData);
+ }
+
+ return $stmt;
+ }
+
+ public function withData() : RefreshMatViewFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ $this->concurrent,
+ false,
+ );
+ }
+
+ public function withNoData() : RefreshMatViewFinalStep
+ {
+ return new self(
+ $this->name,
+ $this->schema,
+ $this->concurrent,
+ true,
+ );
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Select/SelectBuilder.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Select/SelectBuilder.php
new file mode 100644
index 000000000..b4d0fdcfc
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Select/SelectBuilder.php
@@ -0,0 +1,1195 @@
+ $selectList
+ * @param array $distinctOn
+ * @param array $from
+ * @param array $joins
+ * @param array $groupBy
+ * @param array $windows
+ * @param array $orderBy
+ * @param array $locks
+ */
+ private function __construct(
+ private ?WithClause $with = null,
+ private array $selectList = [],
+ private bool $distinct = false,
+ private array $distinctOn = [],
+ private array $from = [],
+ private array $joins = [],
+ private ?Condition $where = null,
+ private array $groupBy = [],
+ private ?Condition $having = null,
+ private array $windows = [],
+ private ?SetOperation $setOp = null,
+ private ?SelectFinalStep $setOpRhs = null,
+ private array $orderBy = [],
+ private ?int $limit = null,
+ private ?int $offset = null,
+ private array $locks = [],
+ ) {
+ }
+
+ public static function create() : self
+ {
+ return new self();
+ }
+
+ public static function fromAst(Node $node) : static
+ {
+ $selectStmt = $node->getSelectStmt();
+
+ if ($selectStmt === null) {
+ throw InvalidAstException::unexpectedNodeType('SelectStmt', 'unknown');
+ }
+
+ $with = null;
+ $withClause = $selectStmt->getWithClause();
+
+ if ($withClause !== null) {
+ $withNode = new Node();
+ $withNode->setWithClause($withClause);
+ $with = WithClause::fromAst($withNode);
+ }
+
+ $larg = $selectStmt->getLarg();
+
+ if ($larg !== null) {
+ return self::fromSetOperation($selectStmt, $with);
+ }
+
+ $selectList = [];
+ $targetList = $selectStmt->getTargetList();
+
+ if ($targetList !== null) {
+ foreach ($targetList as $targetNode) {
+ $resTarget = $targetNode->getResTarget();
+
+ if ($resTarget !== null && $resTarget->getName() !== null && $resTarget->getName() !== '') {
+ $selectList[] = AliasedExpression::fromAst($targetNode);
+ } else {
+ $valNode = $resTarget?->getVal();
+
+ if ($valNode !== null) {
+ $selectList[] = ExpressionFactory::fromAst($valNode);
+ }
+ }
+ }
+ }
+
+ $distinct = false;
+ $distinctOn = [];
+ $distinctClause = $selectStmt->getDistinctClause();
+
+ if ($distinctClause !== null && \count($distinctClause) > 0) {
+ $distinct = true;
+
+ foreach ($distinctClause as $distinctNode) {
+ if ($distinctNode->serializeToJsonString() !== '{}') {
+ $distinctOn[] = ExpressionFactory::fromAst($distinctNode);
+ }
+ }
+ }
+
+ $from = [];
+ $joins = [];
+ $fromClause = $selectStmt->getFromClause();
+
+ if ($fromClause !== null) {
+ foreach ($fromClause as $fromNode) {
+ if ($fromNode->hasJoinExpr()) {
+ $flattenedJoins = self::flattenJoins($fromNode);
+ $base = $flattenedJoins['base'];
+
+ if ($base !== null) {
+ $from[] = $base;
+ }
+
+ $joins = \array_merge($joins, $flattenedJoins['joins']);
+ } else {
+ $from[] = self::tableReferenceFromNode($fromNode);
+ }
+ }
+ }
+
+ $where = null;
+ $whereClause = $selectStmt->getWhereClause();
+
+ if ($whereClause !== null) {
+ $where = ConditionFactory::fromAst($whereClause);
+ }
+
+ $groupBy = [];
+ $groupClause = $selectStmt->getGroupClause();
+
+ if ($groupClause !== null) {
+ foreach ($groupClause as $groupNode) {
+ $groupBy[] = ExpressionFactory::fromAst($groupNode);
+ }
+ }
+
+ $having = null;
+ $havingClause = $selectStmt->getHavingClause();
+
+ if ($havingClause !== null) {
+ $having = ConditionFactory::fromAst($havingClause);
+ }
+
+ $windows = [];
+ $windowClause = $selectStmt->getWindowClause();
+
+ if ($windowClause !== null) {
+ foreach ($windowClause as $windowNode) {
+ $windows[] = WindowDefinition::fromAst($windowNode);
+ }
+ }
+
+ $orderBy = [];
+ $sortClause = $selectStmt->getSortClause();
+
+ if ($sortClause !== null) {
+ foreach ($sortClause as $sortNode) {
+ $sortBy = $sortNode->getSortBy();
+
+ if ($sortBy !== null) {
+ $orderBy[] = OrderByItem::fromAst($sortBy);
+ }
+ }
+ }
+
+ $limit = null;
+ $limitCount = $selectStmt->getLimitCount();
+
+ if ($limitCount !== null) {
+ $limitExpr = ExpressionFactory::fromAst($limitCount);
+
+ if ($limitExpr instanceof Literal && $limitExpr->isInt()) {
+ $limitValue = $limitExpr->value();
+ $limit = \is_int($limitValue) ? $limitValue : null;
+ }
+ }
+
+ $offset = null;
+ $limitOffset = $selectStmt->getLimitOffset();
+
+ if ($limitOffset !== null) {
+ $offsetExpr = ExpressionFactory::fromAst($limitOffset);
+
+ if ($offsetExpr instanceof Literal && $offsetExpr->isInt()) {
+ $offsetValue = $offsetExpr->value();
+ $offset = \is_int($offsetValue) ? $offsetValue : null;
+ }
+ }
+
+ $locks = [];
+ $lockingClause = $selectStmt->getLockingClause();
+
+ if ($lockingClause !== null) {
+ foreach ($lockingClause as $lockNode) {
+ $locks[] = LockingClause::fromAst($lockNode);
+ }
+ }
+
+ return new self(
+ with: $with,
+ selectList: $selectList,
+ distinct: $distinct,
+ distinctOn: $distinctOn,
+ from: $from,
+ joins: $joins,
+ where: $where,
+ groupBy: $groupBy,
+ having: $having,
+ windows: $windows,
+ orderBy: $orderBy,
+ limit: $limit,
+ offset: $offset,
+ locks: $locks,
+ );
+ }
+
+ public static function with(WithClause $with) : SelectSelectStep
+ {
+ return new self(with: $with);
+ }
+
+ public function crossJoin(TableReference $table) : SelectJoinStep
+ {
+ $join = new JoinedTable(
+ left: $this->from[\count($this->from) - 1],
+ right: $table,
+ joinType: JoinType::CROSS,
+ );
+
+ return new self(
+ with: $this->with,
+ selectList: $this->selectList,
+ distinct: $this->distinct,
+ distinctOn: $this->distinctOn,
+ from: $this->from,
+ joins: [...$this->joins, $join],
+ where: $this->where,
+ groupBy: $this->groupBy,
+ having: $this->having,
+ windows: $this->windows,
+ setOp: $this->setOp,
+ setOpRhs: $this->setOpRhs,
+ orderBy: $this->orderBy,
+ limit: $this->limit,
+ offset: $this->offset,
+ locks: $this->locks,
+ );
+ }
+
+ public function except(SelectFinalStep $other) : SelectOrderByStep
+ {
+ return new self(
+ with: $this->with,
+ selectList: $this->selectList,
+ distinct: $this->distinct,
+ distinctOn: $this->distinctOn,
+ from: $this->from,
+ joins: $this->joins,
+ where: $this->where,
+ groupBy: $this->groupBy,
+ having: $this->having,
+ windows: $this->windows,
+ setOp: SetOperation::EXCEPT,
+ setOpRhs: $other,
+ );
+ }
+
+ public function exceptAll(SelectFinalStep $other) : SelectOrderByStep
+ {
+ return new self(
+ with: $this->with,
+ selectList: $this->selectList,
+ distinct: $this->distinct,
+ distinctOn: $this->distinctOn,
+ from: $this->from,
+ joins: $this->joins,
+ where: $this->where,
+ groupBy: $this->groupBy,
+ having: $this->having,
+ windows: $this->windows,
+ setOp: SetOperation::EXCEPT_ALL,
+ setOpRhs: $other,
+ );
+ }
+
+ public function forKeyShare(string ...$tables) : SelectFinalStep
+ {
+ $lock = LockingClause::forKeyShare(\array_values($tables));
+
+ return new self(
+ with: $this->with,
+ selectList: $this->selectList,
+ distinct: $this->distinct,
+ distinctOn: $this->distinctOn,
+ from: $this->from,
+ joins: $this->joins,
+ where: $this->where,
+ groupBy: $this->groupBy,
+ having: $this->having,
+ windows: $this->windows,
+ setOp: $this->setOp,
+ setOpRhs: $this->setOpRhs,
+ orderBy: $this->orderBy,
+ limit: $this->limit,
+ offset: $this->offset,
+ locks: [...$this->locks, $lock],
+ );
+ }
+
+ public function forNoKeyUpdate(string ...$tables) : SelectFinalStep
+ {
+ $lock = LockingClause::forNoKeyUpdate(\array_values($tables));
+
+ return new self(
+ with: $this->with,
+ selectList: $this->selectList,
+ distinct: $this->distinct,
+ distinctOn: $this->distinctOn,
+ from: $this->from,
+ joins: $this->joins,
+ where: $this->where,
+ groupBy: $this->groupBy,
+ having: $this->having,
+ windows: $this->windows,
+ setOp: $this->setOp,
+ setOpRhs: $this->setOpRhs,
+ orderBy: $this->orderBy,
+ limit: $this->limit,
+ offset: $this->offset,
+ locks: [...$this->locks, $lock],
+ );
+ }
+
+ public function forShare(string ...$tables) : SelectFinalStep
+ {
+ $lock = LockingClause::forShare(\array_values($tables));
+
+ return new self(
+ with: $this->with,
+ selectList: $this->selectList,
+ distinct: $this->distinct,
+ distinctOn: $this->distinctOn,
+ from: $this->from,
+ joins: $this->joins,
+ where: $this->where,
+ groupBy: $this->groupBy,
+ having: $this->having,
+ windows: $this->windows,
+ setOp: $this->setOp,
+ setOpRhs: $this->setOpRhs,
+ orderBy: $this->orderBy,
+ limit: $this->limit,
+ offset: $this->offset,
+ locks: [...$this->locks, $lock],
+ );
+ }
+
+ public function forUpdate(string ...$tables) : SelectFinalStep
+ {
+ $lock = LockingClause::forUpdate(\array_values($tables));
+
+ return new self(
+ with: $this->with,
+ selectList: $this->selectList,
+ distinct: $this->distinct,
+ distinctOn: $this->distinctOn,
+ from: $this->from,
+ joins: $this->joins,
+ where: $this->where,
+ groupBy: $this->groupBy,
+ having: $this->having,
+ windows: $this->windows,
+ setOp: $this->setOp,
+ setOpRhs: $this->setOpRhs,
+ orderBy: $this->orderBy,
+ limit: $this->limit,
+ offset: $this->offset,
+ locks: [...$this->locks, $lock],
+ );
+ }
+
+ public function from(TableReference ...$tables) : SelectJoinStep
+ {
+ return new self(
+ with: $this->with,
+ selectList: $this->selectList,
+ distinct: $this->distinct,
+ distinctOn: $this->distinctOn,
+ from: $tables,
+ where: $this->where,
+ groupBy: $this->groupBy,
+ having: $this->having,
+ windows: $this->windows,
+ setOp: $this->setOp,
+ setOpRhs: $this->setOpRhs,
+ orderBy: $this->orderBy,
+ limit: $this->limit,
+ offset: $this->offset,
+ locks: $this->locks,
+ );
+ }
+
+ public function fullJoin(TableReference $table, Condition $on) : SelectJoinStep
+ {
+ $join = new JoinedTable(
+ left: $this->from[\count($this->from) - 1],
+ right: $table,
+ joinType: JoinType::FULL,
+ onCondition: $on,
+ );
+
+ return new self(
+ with: $this->with,
+ selectList: $this->selectList,
+ distinct: $this->distinct,
+ distinctOn: $this->distinctOn,
+ from: $this->from,
+ joins: [...$this->joins, $join],
+ where: $this->where,
+ groupBy: $this->groupBy,
+ having: $this->having,
+ windows: $this->windows,
+ setOp: $this->setOp,
+ setOpRhs: $this->setOpRhs,
+ orderBy: $this->orderBy,
+ limit: $this->limit,
+ offset: $this->offset,
+ locks: $this->locks,
+ );
+ }
+
+ public function groupBy(Expression ...$expressions) : SelectHavingStep
+ {
+ return new self(
+ with: $this->with,
+ selectList: $this->selectList,
+ distinct: $this->distinct,
+ distinctOn: $this->distinctOn,
+ from: $this->from,
+ joins: $this->joins,
+ where: $this->where,
+ groupBy: $expressions,
+ having: $this->having,
+ windows: $this->windows,
+ setOp: $this->setOp,
+ setOpRhs: $this->setOpRhs,
+ orderBy: $this->orderBy,
+ limit: $this->limit,
+ offset: $this->offset,
+ locks: $this->locks,
+ );
+ }
+
+ public function having(Condition $condition) : SelectWindowStep
+ {
+ return new self(
+ with: $this->with,
+ selectList: $this->selectList,
+ distinct: $this->distinct,
+ distinctOn: $this->distinctOn,
+ from: $this->from,
+ joins: $this->joins,
+ where: $this->where,
+ groupBy: $this->groupBy,
+ having: $condition,
+ windows: $this->windows,
+ setOp: $this->setOp,
+ setOpRhs: $this->setOpRhs,
+ orderBy: $this->orderBy,
+ limit: $this->limit,
+ offset: $this->offset,
+ locks: $this->locks,
+ );
+ }
+
+ public function intersect(SelectFinalStep $other) : SelectOrderByStep
+ {
+ return new self(
+ with: $this->with,
+ selectList: $this->selectList,
+ distinct: $this->distinct,
+ distinctOn: $this->distinctOn,
+ from: $this->from,
+ joins: $this->joins,
+ where: $this->where,
+ groupBy: $this->groupBy,
+ having: $this->having,
+ windows: $this->windows,
+ setOp: SetOperation::INTERSECT,
+ setOpRhs: $other,
+ );
+ }
+
+ public function intersectAll(SelectFinalStep $other) : SelectOrderByStep
+ {
+ return new self(
+ with: $this->with,
+ selectList: $this->selectList,
+ distinct: $this->distinct,
+ distinctOn: $this->distinctOn,
+ from: $this->from,
+ joins: $this->joins,
+ where: $this->where,
+ groupBy: $this->groupBy,
+ having: $this->having,
+ windows: $this->windows,
+ setOp: SetOperation::INTERSECT_ALL,
+ setOpRhs: $other,
+ );
+ }
+
+ public function join(TableReference $table, Condition $on) : SelectJoinStep
+ {
+ $join = new JoinedTable(
+ left: $this->from[\count($this->from) - 1],
+ right: $table,
+ joinType: JoinType::INNER,
+ onCondition: $on,
+ );
+
+ return new self(
+ with: $this->with,
+ selectList: $this->selectList,
+ distinct: $this->distinct,
+ distinctOn: $this->distinctOn,
+ from: $this->from,
+ joins: [...$this->joins, $join],
+ where: $this->where,
+ groupBy: $this->groupBy,
+ having: $this->having,
+ windows: $this->windows,
+ setOp: $this->setOp,
+ setOpRhs: $this->setOpRhs,
+ orderBy: $this->orderBy,
+ limit: $this->limit,
+ offset: $this->offset,
+ locks: $this->locks,
+ );
+ }
+
+ public function leftJoin(TableReference $table, Condition $on) : SelectJoinStep
+ {
+ $join = new JoinedTable(
+ left: $this->from[\count($this->from) - 1],
+ right: $table,
+ joinType: JoinType::LEFT,
+ onCondition: $on,
+ );
+
+ return new self(
+ with: $this->with,
+ selectList: $this->selectList,
+ distinct: $this->distinct,
+ distinctOn: $this->distinctOn,
+ from: $this->from,
+ joins: [...$this->joins, $join],
+ where: $this->where,
+ groupBy: $this->groupBy,
+ having: $this->having,
+ windows: $this->windows,
+ setOp: $this->setOp,
+ setOpRhs: $this->setOpRhs,
+ orderBy: $this->orderBy,
+ limit: $this->limit,
+ offset: $this->offset,
+ locks: $this->locks,
+ );
+ }
+
+ public function limit(int $limit) : SelectOffsetStep
+ {
+ return new self(
+ with: $this->with,
+ selectList: $this->selectList,
+ distinct: $this->distinct,
+ distinctOn: $this->distinctOn,
+ from: $this->from,
+ joins: $this->joins,
+ where: $this->where,
+ groupBy: $this->groupBy,
+ having: $this->having,
+ windows: $this->windows,
+ setOp: $this->setOp,
+ setOpRhs: $this->setOpRhs,
+ orderBy: $this->orderBy,
+ limit: $limit,
+ offset: $this->offset,
+ locks: $this->locks,
+ );
+ }
+
+ public function offset(int $offset) : SelectLockingStep
+ {
+ return new self(
+ with: $this->with,
+ selectList: $this->selectList,
+ distinct: $this->distinct,
+ distinctOn: $this->distinctOn,
+ from: $this->from,
+ joins: $this->joins,
+ where: $this->where,
+ groupBy: $this->groupBy,
+ having: $this->having,
+ windows: $this->windows,
+ setOp: $this->setOp,
+ setOpRhs: $this->setOpRhs,
+ orderBy: $this->orderBy,
+ limit: $this->limit,
+ offset: $offset,
+ locks: $this->locks,
+ );
+ }
+
+ public function orderBy(OrderByItem ...$items) : SelectLimitStep
+ {
+ return new self(
+ with: $this->with,
+ selectList: $this->selectList,
+ distinct: $this->distinct,
+ distinctOn: $this->distinctOn,
+ from: $this->from,
+ joins: $this->joins,
+ where: $this->where,
+ groupBy: $this->groupBy,
+ having: $this->having,
+ windows: $this->windows,
+ setOp: $this->setOp,
+ setOpRhs: $this->setOpRhs,
+ orderBy: $items,
+ limit: $this->limit,
+ offset: $this->offset,
+ locks: $this->locks,
+ );
+ }
+
+ public function rightJoin(TableReference $table, Condition $on) : SelectJoinStep
+ {
+ $join = new JoinedTable(
+ left: $this->from[\count($this->from) - 1],
+ right: $table,
+ joinType: JoinType::RIGHT,
+ onCondition: $on,
+ );
+
+ return new self(
+ with: $this->with,
+ selectList: $this->selectList,
+ distinct: $this->distinct,
+ distinctOn: $this->distinctOn,
+ from: $this->from,
+ joins: [...$this->joins, $join],
+ where: $this->where,
+ groupBy: $this->groupBy,
+ having: $this->having,
+ windows: $this->windows,
+ setOp: $this->setOp,
+ setOpRhs: $this->setOpRhs,
+ orderBy: $this->orderBy,
+ limit: $this->limit,
+ offset: $this->offset,
+ locks: $this->locks,
+ );
+ }
+
+ public function select(Expression ...$expressions) : self
+ {
+ return new self(
+ with: $this->with,
+ selectList: $expressions,
+ distinct: false,
+ from: $this->from,
+ joins: $this->joins,
+ where: $this->where,
+ groupBy: $this->groupBy,
+ having: $this->having,
+ windows: $this->windows,
+ setOp: $this->setOp,
+ setOpRhs: $this->setOpRhs,
+ orderBy: $this->orderBy,
+ limit: $this->limit,
+ offset: $this->offset,
+ locks: $this->locks,
+ );
+ }
+
+ public function selectDistinct(Expression ...$expressions) : SelectFromStep
+ {
+ return new self(
+ with: $this->with,
+ selectList: $expressions,
+ distinct: true,
+ from: $this->from,
+ joins: $this->joins,
+ where: $this->where,
+ groupBy: $this->groupBy,
+ having: $this->having,
+ windows: $this->windows,
+ setOp: $this->setOp,
+ setOpRhs: $this->setOpRhs,
+ orderBy: $this->orderBy,
+ limit: $this->limit,
+ offset: $this->offset,
+ locks: $this->locks,
+ );
+ }
+
+ public function selectDistinctOn(array $distinctExpressions, Expression ...$selectExpressions) : SelectFromStep
+ {
+ return new self(
+ with: $this->with,
+ selectList: $selectExpressions,
+ distinct: true,
+ distinctOn: $distinctExpressions,
+ from: $this->from,
+ joins: $this->joins,
+ where: $this->where,
+ groupBy: $this->groupBy,
+ having: $this->having,
+ windows: $this->windows,
+ setOp: $this->setOp,
+ setOpRhs: $this->setOpRhs,
+ orderBy: $this->orderBy,
+ limit: $this->limit,
+ offset: $this->offset,
+ locks: $this->locks,
+ );
+ }
+
+ public function toAst() : ProtobufSelectStmt
+ {
+ if ($this->setOp !== null && $this->setOpRhs !== null) {
+ return $this->buildSetOperationAst();
+ }
+
+ return $this->buildSimpleSelectAst();
+ }
+
+ public function union(SelectFinalStep $other) : SelectOrderByStep
+ {
+ return new self(
+ with: $this->with,
+ selectList: $this->selectList,
+ distinct: $this->distinct,
+ distinctOn: $this->distinctOn,
+ from: $this->from,
+ joins: $this->joins,
+ where: $this->where,
+ groupBy: $this->groupBy,
+ having: $this->having,
+ windows: $this->windows,
+ setOp: SetOperation::UNION,
+ setOpRhs: $other,
+ );
+ }
+
+ public function unionAll(SelectFinalStep $other) : SelectOrderByStep
+ {
+ return new self(
+ with: $this->with,
+ selectList: $this->selectList,
+ distinct: $this->distinct,
+ distinctOn: $this->distinctOn,
+ from: $this->from,
+ joins: $this->joins,
+ where: $this->where,
+ groupBy: $this->groupBy,
+ having: $this->having,
+ windows: $this->windows,
+ setOp: SetOperation::UNION_ALL,
+ setOpRhs: $other,
+ );
+ }
+
+ public function where(Condition $condition) : SelectGroupByStep
+ {
+ return new self(
+ with: $this->with,
+ selectList: $this->selectList,
+ distinct: $this->distinct,
+ distinctOn: $this->distinctOn,
+ from: $this->from,
+ joins: $this->joins,
+ where: $condition,
+ groupBy: $this->groupBy,
+ having: $this->having,
+ windows: $this->windows,
+ setOp: $this->setOp,
+ setOpRhs: $this->setOpRhs,
+ orderBy: $this->orderBy,
+ limit: $this->limit,
+ offset: $this->offset,
+ locks: $this->locks,
+ );
+ }
+
+ public function window(WindowDefinition ...$windows) : SelectSetOperationStep
+ {
+ return new self(
+ with: $this->with,
+ selectList: $this->selectList,
+ distinct: $this->distinct,
+ distinctOn: $this->distinctOn,
+ from: $this->from,
+ joins: $this->joins,
+ where: $this->where,
+ groupBy: $this->groupBy,
+ having: $this->having,
+ windows: $windows,
+ setOp: $this->setOp,
+ setOpRhs: $this->setOpRhs,
+ orderBy: $this->orderBy,
+ limit: $this->limit,
+ offset: $this->offset,
+ locks: $this->locks,
+ );
+ }
+
+ private function buildSetOperationAst() : ProtobufSelectStmt
+ {
+ $selectStmt = new ProtobufSelectStmt();
+
+ if ($this->with !== null) {
+ $withNode = $this->with->toAst();
+ $withClause = $withNode->getWithClause();
+
+ if ($withClause !== null) {
+ $selectStmt->setWithClause($withClause);
+ }
+ }
+
+ if ($this->setOp !== null) {
+ $selectStmt->setOp($this->setOp->toProtobuf());
+ $selectStmt->setAll($this->setOp->hasAll());
+ }
+
+ $leftStmt = $this->buildSimpleSelectAst();
+ $selectStmt->setLarg($leftStmt);
+
+ if ($this->setOpRhs !== null) {
+ $rightStmt = $this->setOpRhs->toAst();
+ $selectStmt->setRarg($rightStmt);
+ }
+
+ if ($this->orderBy !== []) {
+ $sortClause = [];
+
+ foreach ($this->orderBy as $orderByItem) {
+ $sortBy = $orderByItem->toAst();
+ $node = new Node();
+ $node->setSortBy($sortBy);
+ $sortClause[] = $node;
+ }
+
+ $selectStmt->setSortClause($sortClause);
+ }
+
+ if ($this->limit !== null) {
+ $selectStmt->setLimitCount(Literal::int($this->limit)->toAst());
+ $selectStmt->setLimitOption(LimitOption::LIMIT_OPTION_COUNT);
+ }
+
+ if ($this->offset !== null) {
+ $selectStmt->setLimitOffset(Literal::int($this->offset)->toAst());
+ }
+
+ if ($this->locks !== []) {
+ $lockingClause = [];
+
+ foreach ($this->locks as $lock) {
+ $lockingClause[] = $lock->toAst();
+ }
+
+ $selectStmt->setLockingClause($lockingClause);
+ }
+
+ return $selectStmt;
+ }
+
+ private function buildSimpleSelectAst() : ProtobufSelectStmt
+ {
+ $selectStmt = new ProtobufSelectStmt();
+
+ if ($this->with !== null) {
+ $withNode = $this->with->toAst();
+ $withClause = $withNode->getWithClause();
+
+ if ($withClause !== null) {
+ $selectStmt->setWithClause($withClause);
+ }
+ }
+
+ if ($this->distinct && $this->distinctOn !== []) {
+ $distinctClause = [];
+
+ foreach ($this->distinctOn as $expr) {
+ $distinctClause[] = $expr->toAst();
+ }
+
+ $selectStmt->setDistinctClause($distinctClause);
+ } elseif ($this->distinct) {
+ $selectStmt->setDistinctClause([new Node()]);
+ }
+
+ $targetList = [];
+
+ foreach ($this->selectList as $expr) {
+ if ($expr instanceof AliasedExpression) {
+ $targetList[] = $expr->toAst();
+ } else {
+ $resTarget = new ResTarget();
+ $resTarget->setVal($expr->toAst());
+ $node = new Node();
+ $node->setResTarget($resTarget);
+ $targetList[] = $node;
+ }
+ }
+
+ $selectStmt->setTargetList($targetList);
+
+ if ($this->from !== [] || $this->joins !== []) {
+ $fromClause = [];
+
+ if ($this->from !== []) {
+ if ($this->joins !== []) {
+ $base = $this->from[0];
+ $current = $base;
+
+ foreach ($this->joins as $join) {
+ $joined = new JoinedTable(
+ left: $current,
+ right: $join->right,
+ joinType: $join->joinType,
+ onCondition: $join->onCondition,
+ usingColumns: $join->usingColumns,
+ natural: $join->natural,
+ );
+ $current = $joined;
+ }
+
+ $fromClause[] = $current->toAst();
+
+ for ($i = 1; $i < \count($this->from); $i++) {
+ $fromClause[] = $this->from[$i]->toAst();
+ }
+ } else {
+ foreach ($this->from as $table) {
+ $fromClause[] = $table->toAst();
+ }
+ }
+ }
+
+ $selectStmt->setFromClause($fromClause);
+ }
+
+ if ($this->where !== null) {
+ $selectStmt->setWhereClause($this->where->toAst());
+ }
+
+ if ($this->groupBy !== []) {
+ $groupClause = [];
+
+ foreach ($this->groupBy as $expr) {
+ $groupClause[] = $expr->toAst();
+ }
+
+ $selectStmt->setGroupClause($groupClause);
+ }
+
+ if ($this->having !== null) {
+ $selectStmt->setHavingClause($this->having->toAst());
+ }
+
+ if ($this->windows !== []) {
+ $windowClause = [];
+
+ foreach ($this->windows as $window) {
+ $windowClause[] = $window->toAst();
+ }
+
+ $selectStmt->setWindowClause($windowClause);
+ }
+
+ if ($this->orderBy !== []) {
+ $sortClause = [];
+
+ foreach ($this->orderBy as $orderByItem) {
+ $sortBy = $orderByItem->toAst();
+ $node = new Node();
+ $node->setSortBy($sortBy);
+ $sortClause[] = $node;
+ }
+
+ $selectStmt->setSortClause($sortClause);
+ }
+
+ if ($this->limit !== null) {
+ $selectStmt->setLimitCount(Literal::int($this->limit)->toAst());
+ $selectStmt->setLimitOption(LimitOption::LIMIT_OPTION_COUNT);
+ }
+
+ if ($this->offset !== null) {
+ $selectStmt->setLimitOffset(Literal::int($this->offset)->toAst());
+ }
+
+ if ($this->locks !== []) {
+ $lockingClause = [];
+
+ foreach ($this->locks as $lock) {
+ $lockingClause[] = $lock->toAst();
+ }
+
+ $selectStmt->setLockingClause($lockingClause);
+ }
+
+ return $selectStmt;
+ }
+
+ /**
+ * @return array{base: null|TableReference, joins: array}
+ */
+ private static function flattenJoins(Node $joinNode) : array
+ {
+ $joined = JoinedTable::fromAst($joinNode);
+ $joins = [];
+ $base = null;
+
+ $current = $joined;
+
+ while ($current->left instanceof JoinedTable) {
+ $joins[] = $current;
+ $current = $current->left;
+ }
+
+ $base = $current->left;
+ $joins[] = $current;
+
+ $joins = \array_reverse($joins);
+
+ return [
+ 'base' => $base,
+ 'joins' => $joins,
+ ];
+ }
+
+ private static function fromSetOperation(ProtobufSelectStmt $selectStmt, ?WithClause $with) : static
+ {
+ $op = $selectStmt->getOp();
+ $all = $selectStmt->getAll();
+ $setOp = SetOperation::fromProtobuf($op, $all);
+
+ $larg = $selectStmt->getLarg();
+
+ if ($larg === null) {
+ throw InvalidAstException::missingRequiredField('larg', 'SelectStmt');
+ }
+
+ $largNode = new Node();
+ $largNode->setSelectStmt($larg);
+ $left = self::fromAst($largNode);
+
+ $rarg = $selectStmt->getRarg();
+
+ if ($rarg === null) {
+ throw InvalidAstException::missingRequiredField('rarg', 'SelectStmt');
+ }
+
+ $rargNode = new Node();
+ $rargNode->setSelectStmt($rarg);
+ $right = self::fromAst($rargNode);
+
+ $orderBy = [];
+ $sortClause = $selectStmt->getSortClause();
+
+ if ($sortClause !== null) {
+ foreach ($sortClause as $sortNode) {
+ $sortBy = $sortNode->getSortBy();
+
+ if ($sortBy !== null) {
+ $orderBy[] = OrderByItem::fromAst($sortBy);
+ }
+ }
+ }
+
+ $limit = null;
+ $limitCount = $selectStmt->getLimitCount();
+
+ if ($limitCount !== null) {
+ $limitExpr = ExpressionFactory::fromAst($limitCount);
+
+ if ($limitExpr instanceof Literal && $limitExpr->isInt()) {
+ $limitValue = $limitExpr->value();
+ $limit = \is_int($limitValue) ? $limitValue : null;
+ }
+ }
+
+ $offset = null;
+ $limitOffset = $selectStmt->getLimitOffset();
+
+ if ($limitOffset !== null) {
+ $offsetExpr = ExpressionFactory::fromAst($limitOffset);
+
+ if ($offsetExpr instanceof Literal && $offsetExpr->isInt()) {
+ $offsetValue = $offsetExpr->value();
+ $offset = \is_int($offsetValue) ? $offsetValue : null;
+ }
+ }
+
+ $locks = [];
+ $lockingClause = $selectStmt->getLockingClause();
+
+ if ($lockingClause !== null) {
+ foreach ($lockingClause as $lockNode) {
+ $locks[] = LockingClause::fromAst($lockNode);
+ }
+ }
+
+ return new self(
+ with: $with,
+ selectList: $left->selectList,
+ distinct: $left->distinct,
+ distinctOn: $left->distinctOn,
+ from: $left->from,
+ joins: $left->joins,
+ where: $left->where,
+ groupBy: $left->groupBy,
+ having: $left->having,
+ windows: $left->windows,
+ setOp: $setOp,
+ setOpRhs: $right,
+ orderBy: $orderBy,
+ limit: $limit,
+ offset: $offset,
+ locks: $locks,
+ );
+ }
+
+ private static function tableReferenceFromNode(Node $node) : TableReference
+ {
+ if ($node->hasRangeVar()) {
+ $rangeVar = $node->getRangeVar();
+
+ if ($rangeVar === null) {
+ throw InvalidAstException::missingRequiredField('range_var', 'Node');
+ }
+
+ return Table::fromAst($node);
+ }
+
+ if ($node->hasRangeSubselect()) {
+ return DerivedTable::fromAst($node);
+ }
+
+ if ($node->hasRangeFunction()) {
+ $rangeFunction = $node->getRangeFunction();
+ $tableFunction = TableFunction::fromAst($node);
+
+ if ($rangeFunction !== null) {
+ $alias = $rangeFunction->getAlias();
+
+ if ($alias !== null && $alias->getAliasname() !== '') {
+ $columnAliases = null;
+ $colnames = $alias->getColnames();
+
+ if ($colnames !== null && \count($colnames) > 0) {
+ $columnAliases = [];
+
+ foreach ($colnames as $colNode) {
+ $colString = $colNode->getString();
+
+ if ($colString !== null) {
+ $columnAliases[] = $colString->getSval();
+ }
+ }
+ }
+
+ return new AliasedTable($tableFunction, $alias->getAliasname(), $columnAliases);
+ }
+ }
+
+ return $tableFunction;
+ }
+
+ throw InvalidAstException::unexpectedNodeType('RangeVar, RangeSubselect or RangeFunction', 'unknown');
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Select/SelectFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Select/SelectFinalStep.php
new file mode 100644
index 000000000..2af83d755
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Select/SelectFinalStep.php
@@ -0,0 +1,24 @@
+ $distinctExpressions
+ * @param Expression ...$selectExpressions
+ */
+ public function selectDistinctOn(array $distinctExpressions, Expression ...$selectExpressions) : SelectFromStep;
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Select/SelectSetOperationStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Select/SelectSetOperationStep.php
new file mode 100644
index 000000000..8a9b7407b
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Select/SelectSetOperationStep.php
@@ -0,0 +1,20 @@
+ $all ? self::UNION_ALL : self::UNION,
+ ProtobufSetOperation::SETOP_INTERSECT => $all ? self::INTERSECT_ALL : self::INTERSECT,
+ ProtobufSetOperation::SETOP_EXCEPT => $all ? self::EXCEPT_ALL : self::EXCEPT,
+ default => self::UNION,
+ };
+ }
+
+ public function hasAll() : bool
+ {
+ return match ($this) {
+ self::UNION_ALL, self::INTERSECT_ALL, self::EXCEPT_ALL => true,
+ default => false,
+ };
+ }
+
+ public function toProtobuf() : int
+ {
+ return match ($this) {
+ self::UNION, self::UNION_ALL => ProtobufSetOperation::SETOP_UNION,
+ self::INTERSECT, self::INTERSECT_ALL => ProtobufSetOperation::SETOP_INTERSECT,
+ self::EXCEPT, self::EXCEPT_ALL => ProtobufSetOperation::SETOP_EXCEPT,
+ };
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Table/AliasedTable.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Table/AliasedTable.php
new file mode 100644
index 000000000..e9d104854
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Table/AliasedTable.php
@@ -0,0 +1,241 @@
+ $columnAliases
+ */
+ public function __construct(
+ public TableReference $table,
+ public string $alias,
+ public ?array $columnAliases = null,
+ ) {
+ }
+
+ public static function fromAst(Node $node) : static
+ {
+ $rangeVar = $node->getRangeVar();
+ $joinExpr = $node->getJoinExpr();
+ $rangeSubselect = $node->getRangeSubselect();
+ $rangeFunction = $node->getRangeFunction();
+
+ if ($rangeVar !== null) {
+ return self::fromRangeVar($rangeVar);
+ }
+
+ if ($joinExpr !== null) {
+ $joinAlias = $joinExpr->getAlias();
+
+ if ($joinAlias === null) {
+ throw InvalidAstException::missingRequiredField('alias', 'JoinExpr');
+ }
+
+ $joinedTable = JoinedTable::fromAst($node);
+
+ return new self(
+ $joinedTable,
+ $joinAlias->getAliasname(),
+ self::extractColumnAliases($joinAlias)
+ );
+ }
+
+ if ($rangeSubselect !== null) {
+ $alias = $rangeSubselect->getAlias();
+
+ if ($alias === null) {
+ throw InvalidAstException::missingRequiredField('alias', 'RangeSubselect');
+ }
+
+ $clonedRangeSubselect = clone $rangeSubselect;
+ $clonedRangeSubselect->clearAlias();
+
+ $nodeWithoutAlias = new Node();
+ $nodeWithoutAlias->setRangeSubselect($clonedRangeSubselect);
+
+ if ($rangeSubselect->getLateral()) {
+ $table = Lateral::fromAst($node);
+ } else {
+ $table = SubqueryReference::fromAst($nodeWithoutAlias);
+ }
+
+ return new self(
+ $table,
+ $alias->getAliasname(),
+ self::extractColumnAliases($alias)
+ );
+ }
+
+ if ($rangeFunction !== null) {
+ $alias = $rangeFunction->getAlias();
+
+ if ($alias === null) {
+ throw InvalidAstException::missingRequiredField('alias', 'RangeFunction');
+ }
+
+ $clonedRangeFunction = clone $rangeFunction;
+ $clonedRangeFunction->clearAlias();
+
+ $nodeWithoutAlias = new Node();
+ $nodeWithoutAlias->setRangeFunction($clonedRangeFunction);
+
+ if ($rangeFunction->getLateral()) {
+ $table = Lateral::fromAst($node);
+ } else {
+ $table = TableFunction::fromAst($nodeWithoutAlias);
+ }
+
+ return new self(
+ $table,
+ $alias->getAliasname(),
+ self::extractColumnAliases($alias)
+ );
+ }
+
+ throw InvalidAstException::unexpectedNodeType('RangeVar, JoinExpr, RangeSubselect, or RangeFunction', 'unknown');
+ }
+
+ public function as(string $alias, ?array $columnAliases = null) : self
+ {
+ return new self($this->table, $alias, $columnAliases);
+ }
+
+ public function toAst() : Node
+ {
+ $tableNode = $this->table->toAst();
+
+ if ($tableNode->hasRangeVar()) {
+ $rangeVar = $tableNode->getRangeVar();
+
+ if ($rangeVar === null) {
+ throw InvalidAstException::missingRequiredField('range_var', 'Node');
+ }
+
+ $rangeVar->setAlias($this->createAlias());
+
+ return new Node(['range_var' => $rangeVar]);
+ }
+
+ if ($tableNode->hasJoinExpr()) {
+ $joinExpr = $tableNode->getJoinExpr();
+
+ if ($joinExpr === null) {
+ throw InvalidAstException::missingRequiredField('join_expr', 'Node');
+ }
+
+ $joinExpr->setAlias($this->createAlias());
+
+ return new Node(['join_expr' => $joinExpr]);
+ }
+
+ if ($tableNode->hasRangeSubselect()) {
+ $rangeSubselect = $tableNode->getRangeSubselect();
+
+ if ($rangeSubselect === null) {
+ throw InvalidAstException::missingRequiredField('range_subselect', 'Node');
+ }
+
+ $rangeSubselect->setAlias($this->createAlias());
+
+ return new Node(['range_subselect' => $rangeSubselect]);
+ }
+
+ if ($tableNode->hasRangeFunction()) {
+ $rangeFunction = $tableNode->getRangeFunction();
+
+ if ($rangeFunction === null) {
+ throw InvalidAstException::missingRequiredField('range_function', 'Node');
+ }
+
+ $rangeFunction->setAlias($this->createAlias());
+
+ return new Node(['range_function' => $rangeFunction]);
+ }
+
+ throw InvalidAstException::unexpectedNodeType('RangeVar, JoinExpr, RangeSubselect, or RangeFunction', 'unknown');
+ }
+
+ private function createAlias() : Alias
+ {
+ $alias = new Alias([
+ 'aliasname' => $this->alias,
+ ]);
+
+ if ($this->columnAliases !== null) {
+ $colnames = [];
+
+ foreach ($this->columnAliases as $colname) {
+ $colnames[] = new Node(['string' => new PBString(['sval' => $colname])]);
+ }
+
+ $alias->setColnames($colnames);
+ }
+
+ return $alias;
+ }
+
+ /**
+ * @return null|array
+ */
+ private static function extractColumnAliases(Alias $alias) : ?array
+ {
+ $colnames = $alias->getColnames();
+
+ if (\count($colnames) === 0) {
+ return null;
+ }
+
+ $columnAliases = [];
+
+ foreach ($colnames as $colname) {
+ $string = $colname->getString();
+
+ if ($string === null) {
+ continue;
+ }
+
+ $columnAliases[] = $string->getSval();
+ }
+
+ return \count($columnAliases) > 0 ? $columnAliases : null;
+ }
+
+ private static function fromRangeVar(RangeVar $rangeVar) : self
+ {
+ $alias = $rangeVar->getAlias();
+
+ if ($alias === null) {
+ throw InvalidAstException::missingRequiredField('alias', 'RangeVar');
+ }
+
+ $relname = $rangeVar->getRelname();
+
+ if ($relname === '') {
+ throw InvalidAstException::missingRequiredField('relname', 'RangeVar');
+ }
+
+ $schemaname = $rangeVar->getSchemaname();
+ $inh = $rangeVar->getInh();
+
+ $table = new Table(
+ $relname,
+ $schemaname !== '' ? $schemaname : null,
+ $inh
+ );
+
+ return new self(
+ $table,
+ $alias->getAliasname(),
+ self::extractColumnAliases($alias)
+ );
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Table/DerivedTable.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Table/DerivedTable.php
new file mode 100644
index 000000000..554823132
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Table/DerivedTable.php
@@ -0,0 +1,111 @@
+ $columnAliases
+ */
+ public function __construct(
+ public Node $subquery,
+ public string $alias,
+ public ?array $columnAliases = null,
+ public bool $lateral = false,
+ ) {
+ }
+
+ public static function fromAst(Node $node) : static
+ {
+ $rangeSubselect = $node->getRangeSubselect();
+
+ if ($rangeSubselect === null) {
+ throw InvalidAstException::unexpectedNodeType('RangeSubselect', 'unknown');
+ }
+
+ $subquery = $rangeSubselect->getSubquery();
+
+ if ($subquery === null) {
+ throw InvalidAstException::missingRequiredField('subquery', 'RangeSubselect');
+ }
+
+ $alias = $rangeSubselect->getAlias();
+
+ if ($alias === null) {
+ throw InvalidAstException::missingRequiredField('alias', 'RangeSubselect');
+ }
+
+ $lateral = $rangeSubselect->getLateral();
+
+ return new self(
+ $subquery,
+ $alias->getAliasname(),
+ self::extractColumnAliases($alias),
+ $lateral
+ );
+ }
+
+ public function as(string $alias, ?array $columnAliases = null) : AliasedTable
+ {
+ return new AliasedTable($this, $alias, $columnAliases);
+ }
+
+ public function toAst() : Node
+ {
+ $alias = new Alias([
+ 'aliasname' => $this->alias,
+ ]);
+
+ if ($this->columnAliases !== null) {
+ $colnames = [];
+
+ foreach ($this->columnAliases as $colname) {
+ $colnames[] = new Node(['string' => new PBString(['sval' => $colname])]);
+ }
+
+ $alias->setColnames($colnames);
+ }
+
+ $rangeSubselect = new RangeSubselect([
+ 'subquery' => $this->subquery,
+ 'alias' => $alias,
+ 'lateral' => $this->lateral,
+ ]);
+
+ return new Node(['range_subselect' => $rangeSubselect]);
+ }
+
+ /**
+ * @return null|array
+ */
+ private static function extractColumnAliases(Alias $alias) : ?array
+ {
+ $colnames = $alias->getColnames();
+
+ if (\count($colnames) === 0) {
+ return null;
+ }
+
+ $columnAliases = [];
+
+ foreach ($colnames as $colname) {
+ $string = $colname->getString();
+
+ if ($string === null) {
+ continue;
+ }
+
+ $columnAliases[] = $string->getSval();
+ }
+
+ return \count($columnAliases) > 0 ? $columnAliases : null;
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Table/JoinType.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Table/JoinType.php
new file mode 100644
index 000000000..14d6b8aaf
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Table/JoinType.php
@@ -0,0 +1,44 @@
+ self::INNER,
+ ProtobufJoinType::JOIN_LEFT => self::LEFT,
+ ProtobufJoinType::JOIN_RIGHT => self::RIGHT,
+ ProtobufJoinType::JOIN_FULL => self::FULL,
+ default => self::INNER,
+ };
+ }
+
+ public function toProtobuf() : int
+ {
+ return match ($this) {
+ self::INNER => ProtobufJoinType::JOIN_INNER,
+ self::LEFT, self::LEFT_OUTER => ProtobufJoinType::JOIN_LEFT,
+ self::RIGHT, self::RIGHT_OUTER => ProtobufJoinType::JOIN_RIGHT,
+ self::FULL, self::FULL_OUTER => ProtobufJoinType::JOIN_FULL,
+ self::CROSS => ProtobufJoinType::JOIN_INNER, // Cross join is implemented as inner join with no condition
+ };
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Table/JoinedTable.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Table/JoinedTable.php
new file mode 100644
index 000000000..8054a5354
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Table/JoinedTable.php
@@ -0,0 +1,155 @@
+ $usingColumns
+ */
+ public function __construct(
+ public TableReference $left,
+ public TableReference $right,
+ public JoinType $joinType,
+ public ?Condition $onCondition = null,
+ public ?array $usingColumns = null,
+ public bool $natural = false,
+ ) {
+ }
+
+ public static function fromAst(Node $node) : static
+ {
+ $joinExpr = $node->getJoinExpr();
+
+ if ($joinExpr === null) {
+ throw InvalidAstException::unexpectedNodeType('JoinExpr', 'unknown');
+ }
+
+ $larg = $joinExpr->getLarg();
+
+ if ($larg === null) {
+ throw InvalidAstException::missingRequiredField('larg', 'JoinExpr');
+ }
+
+ $rarg = $joinExpr->getRarg();
+
+ if ($rarg === null) {
+ throw InvalidAstException::missingRequiredField('rarg', 'JoinExpr');
+ }
+
+ $left = self::tableReferenceFromNode($larg);
+ $right = self::tableReferenceFromNode($rarg);
+
+ $joinType = JoinType::fromProtobuf($joinExpr->getJointype());
+ $natural = $joinExpr->getIsNatural();
+
+ $onCondition = null;
+ $quals = $joinExpr->getQuals();
+
+ if ($quals !== null) {
+ $onCondition = ConditionFactory::fromAst($quals);
+ }
+
+ $usingColumns = null;
+ $usingClause = $joinExpr->getUsingClause();
+
+ if (\count($usingClause) > 0) {
+ $usingColumns = [];
+
+ foreach ($usingClause as $col) {
+ $string = $col->getString();
+
+ if ($string !== null) {
+ $usingColumns[] = $string->getSval();
+ }
+ }
+
+ if (\count($usingColumns) === 0) {
+ $usingColumns = null;
+ }
+ }
+
+ return new self($left, $right, $joinType, $onCondition, $usingColumns, $natural);
+ }
+
+ public function as(string $alias, ?array $columnAliases = null) : AliasedTable
+ {
+ return new AliasedTable($this, $alias, $columnAliases);
+ }
+
+ public function toAst() : Node
+ {
+ $joinExpr = new JoinExpr([
+ 'jointype' => $this->joinType->toProtobuf(),
+ 'larg' => $this->left->toAst(),
+ 'rarg' => $this->right->toAst(),
+ 'is_natural' => $this->natural,
+ ]);
+
+ if ($this->onCondition !== null) {
+ $joinExpr->setQuals($this->onCondition->toAst());
+ }
+
+ if ($this->usingColumns !== null) {
+ $usingClause = [];
+
+ foreach ($this->usingColumns as $col) {
+ $usingClause[] = new Node(['string' => new PBString(['sval' => $col])]);
+ }
+
+ $joinExpr->setUsingClause($usingClause);
+ }
+
+ return new Node(['join_expr' => $joinExpr]);
+ }
+
+ private static function tableReferenceFromNode(Node $node) : TableReference
+ {
+ if ($node->hasRangeVar()) {
+ $rangeVar = $node->getRangeVar();
+
+ if ($rangeVar === null) {
+ throw InvalidAstException::missingRequiredField('range_var', 'Node');
+ }
+
+ $alias = $rangeVar->getAlias();
+
+ if ($alias !== null) {
+ return AliasedTable::fromAst($node);
+ }
+
+ return Table::fromAst($node);
+ }
+
+ if ($node->hasJoinExpr()) {
+ $joinExpr = $node->getJoinExpr();
+
+ if ($joinExpr === null) {
+ throw InvalidAstException::missingRequiredField('join_expr', 'Node');
+ }
+
+ $alias = $joinExpr->getAlias();
+
+ if ($alias !== null) {
+ return AliasedTable::fromAst($node);
+ }
+
+ return self::fromAst($node);
+ }
+
+ if ($node->hasRangeSubselect()) {
+ return DerivedTable::fromAst($node);
+ }
+
+ throw InvalidAstException::unexpectedNodeType('RangeVar, JoinExpr or RangeSubselect', 'unknown');
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Table/Lateral.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Table/Lateral.php
new file mode 100644
index 000000000..cf57ae048
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Table/Lateral.php
@@ -0,0 +1,92 @@
+getRangeSubselect();
+ $rangeFunction = $node->getRangeFunction();
+
+ if ($rangeSubselect !== null) {
+ if (!$rangeSubselect->getLateral()) {
+ throw InvalidAstException::invalidFieldValue('lateral', 'RangeSubselect', 'expected true for LATERAL');
+ }
+
+ $subqueryNode = $rangeSubselect->getSubquery();
+
+ if ($subqueryNode === null) {
+ throw InvalidAstException::missingRequiredField('subquery', 'RangeSubselect');
+ }
+
+ return new self(new SubqueryReference($subqueryNode));
+ }
+
+ if ($rangeFunction !== null) {
+ if (!$rangeFunction->getLateral()) {
+ throw InvalidAstException::invalidFieldValue('lateral', 'RangeFunction', 'expected true for LATERAL');
+ }
+
+ $rangeFunctionWithoutLateral = clone $rangeFunction;
+ $rangeFunctionWithoutLateral->setLateral(false);
+
+ $functionNode = new Node();
+ $functionNode->setRangeFunction($rangeFunctionWithoutLateral);
+
+ return new self(TableFunction::fromAst($functionNode));
+ }
+
+ throw InvalidAstException::unexpectedNodeType('RangeSubselect or RangeFunction with lateral=true', 'unknown');
+ }
+
+ public function as(string $alias, ?array $columnAliases = null) : AliasedTable
+ {
+ return new AliasedTable($this, $alias, $columnAliases);
+ }
+
+ public function getReference() : TableReference
+ {
+ return $this->reference;
+ }
+
+ public function toAst() : Node
+ {
+ $referenceNode = $this->reference->toAst();
+
+ $rangeSubselect = $referenceNode->getRangeSubselect();
+
+ if ($rangeSubselect !== null) {
+ $rangeSubselect->setLateral(true);
+
+ return $referenceNode;
+ }
+
+ $rangeFunction = $referenceNode->getRangeFunction();
+
+ if ($rangeFunction !== null) {
+ $rangeFunction->setLateral(true);
+
+ return $referenceNode;
+ }
+
+ throw InvalidTableException::invalidType('SubqueryReference or TableFunction', \get_debug_type($this->reference));
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Table/SubqueryReference.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Table/SubqueryReference.php
new file mode 100644
index 000000000..8479728a0
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Table/SubqueryReference.php
@@ -0,0 +1,62 @@
+getRangeSubselect();
+
+ if ($rangeSubselect === null) {
+ throw InvalidAstException::unexpectedNodeType('RangeSubselect', 'unknown');
+ }
+
+ $subqueryNode = $rangeSubselect->getSubquery();
+
+ if ($subqueryNode === null) {
+ throw InvalidAstException::missingRequiredField('subquery', 'RangeSubselect');
+ }
+
+ return new self($subqueryNode);
+ }
+
+ public function as(string $alias, ?array $columnAliases = null) : AliasedTable
+ {
+ return new AliasedTable($this, $alias, $columnAliases);
+ }
+
+ public function getSubquery() : Node
+ {
+ return $this->subquery;
+ }
+
+ public function toAst() : Node
+ {
+ $rangeSubselect = new RangeSubselect();
+ $rangeSubselect->setSubquery($this->subquery);
+ $rangeSubselect->setLateral(false);
+
+ $node = new Node();
+ $node->setRangeSubselect($rangeSubselect);
+
+ return $node;
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Table/Table.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Table/Table.php
new file mode 100644
index 000000000..dd0deb97b
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Table/Table.php
@@ -0,0 +1,74 @@
+getRangeVar();
+
+ if ($rangeVar === null) {
+ throw InvalidAstException::unexpectedNodeType('RangeVar', 'unknown');
+ }
+
+ $relname = $rangeVar->getRelname();
+
+ if ($relname === '') {
+ throw InvalidAstException::missingRequiredField('relname', 'RangeVar');
+ }
+
+ $schemaname = $rangeVar->getSchemaname();
+ $inh = $rangeVar->getInh();
+
+ return new self(
+ $relname,
+ $schemaname !== '' ? $schemaname : null,
+ $inh
+ );
+ }
+
+ public function as(string $alias, ?array $columnAliases = null) : AliasedTable
+ {
+ return new AliasedTable($this, $alias, $columnAliases);
+ }
+
+ public function toAst() : Node
+ {
+ $rangeVar = new RangeVar([
+ 'relname' => $this->name,
+ 'inh' => $this->inherits,
+ ]);
+
+ if ($this->schema !== null) {
+ $rangeVar->setSchemaname($this->schema);
+ }
+
+ return new Node(['range_var' => $rangeVar]);
+ }
+
+ public function withName(string $name) : self
+ {
+ return new self($name, $this->schema, $this->inherits);
+ }
+
+ public function withSchema(?string $schema) : self
+ {
+ return new self($this->name, $schema, $this->inherits);
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Table/TableFunction.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Table/TableFunction.php
new file mode 100644
index 000000000..7de218bfa
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Table/TableFunction.php
@@ -0,0 +1,101 @@
+getRangeFunction();
+
+ if ($rangeFunction === null) {
+ throw InvalidAstException::unexpectedNodeType('RangeFunction', 'unknown');
+ }
+
+ $functions = $rangeFunction->getFunctions();
+
+ if ($functions === null || \count($functions) === 0) {
+ throw InvalidAstException::missingRequiredField('functions', 'RangeFunction');
+ }
+
+ $firstFunction = $functions[0];
+ $list = $firstFunction->getList();
+
+ if ($list === null) {
+ throw InvalidAstException::invalidFieldValue('functions', 'RangeFunction', 'expected List node');
+ }
+
+ $items = $list->getItems();
+
+ if ($items === null || \count($items) === 0) {
+ throw InvalidAstException::invalidFieldValue('functions', 'RangeFunction', 'List cannot be empty');
+ }
+
+ $functionNode = $items[0];
+ $function = FunctionCall::fromAst($functionNode);
+
+ $withOrdinality = $rangeFunction->getOrdinality();
+
+ return new self($function, $withOrdinality);
+ }
+
+ public function as(string $alias, ?array $columnAliases = null) : AliasedTable
+ {
+ return new AliasedTable($this, $alias, $columnAliases);
+ }
+
+ public function getFunction() : FunctionCall
+ {
+ return $this->function;
+ }
+
+ public function isWithOrdinality() : bool
+ {
+ return $this->withOrdinality;
+ }
+
+ public function toAst() : Node
+ {
+ $functionList = new PBList();
+ $functionList->setItems([$this->function->toAst()]);
+
+ $listNode = new Node();
+ $listNode->setList($functionList);
+
+ $rangeFunction = new RangeFunction();
+ $rangeFunction->setFunctions([$listNode]);
+ $rangeFunction->setOrdinality($this->withOrdinality);
+ $rangeFunction->setLateral(false);
+ $rangeFunction->setIsRowsfrom(false);
+
+ $node = new Node();
+ $node->setRangeFunction($rangeFunction);
+
+ return $node;
+ }
+
+ public function withOrdinality(bool $withOrdinality = true) : self
+ {
+ return new self($this->function, $withOrdinality);
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Table/TableReference.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Table/TableReference.php
new file mode 100644
index 000000000..c0cdccdb3
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Table/TableReference.php
@@ -0,0 +1,22 @@
+
+ */
+interface TableReference extends AstConvertible
+{
+ /**
+ * Create an aliased table reference: table AS alias (col1, col2).
+ *
+ * @param null|array $columnAliases
+ */
+ public function as(string $alias, ?array $columnAliases = null) : AliasedTable;
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/BeginBuilder.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/BeginBuilder.php
new file mode 100644
index 000000000..d7ab14b11
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/BeginBuilder.php
@@ -0,0 +1,147 @@
+isolationLevel,
+ $this->readOnly,
+ true,
+ );
+ }
+
+ public function isolationLevel(IsolationLevel $level) : BeginOptionsStep
+ {
+ return new self(
+ $level,
+ $this->readOnly,
+ $this->deferrable,
+ );
+ }
+
+ public function notDeferrable() : BeginOptionsStep
+ {
+ return new self(
+ $this->isolationLevel,
+ $this->readOnly,
+ false,
+ );
+ }
+
+ public function readOnly() : BeginOptionsStep
+ {
+ return new self(
+ $this->isolationLevel,
+ true,
+ $this->deferrable,
+ );
+ }
+
+ public function readWrite() : BeginOptionsStep
+ {
+ return new self(
+ $this->isolationLevel,
+ false,
+ $this->deferrable,
+ );
+ }
+
+ public function toAst() : TransactionStmt
+ {
+ $stmt = new TransactionStmt();
+ $stmt->setKind(TransactionStmtKind::TRANS_STMT_BEGIN);
+
+ $options = $this->buildOptions();
+
+ if ($options !== []) {
+ $stmt->setOptions($options);
+ }
+
+ return $stmt;
+ }
+
+ /**
+ * @return list
+ */
+ private function buildOptions() : array
+ {
+ $options = [];
+
+ if ($this->isolationLevel !== null) {
+ $options[] = $this->createIsolationLevelOption($this->isolationLevel);
+ }
+
+ if ($this->readOnly !== null) {
+ $options[] = $this->createBoolOption('transaction_read_only', $this->readOnly);
+ }
+
+ if ($this->deferrable !== null) {
+ $options[] = $this->createBoolOption('transaction_deferrable', $this->deferrable);
+ }
+
+ return $options;
+ }
+
+ private function createBoolOption(string $name, bool $value) : Node
+ {
+ $defElem = new DefElem();
+ $defElem->setDefname($name);
+
+ $aConst = new A_Const();
+ $ival = new Integer();
+ $ival->setIval($value ? 1 : 0);
+ /** @phpstan-ignore argument.type (protobuf PHPDoc says int but actually expects Integer) */
+ $aConst->setIval($ival);
+
+ $argNode = new Node();
+ $argNode->setAConst($aConst);
+ $defElem->setArg($argNode);
+
+ $node = new Node();
+ $node->setDefElem($defElem);
+
+ return $node;
+ }
+
+ private function createIsolationLevelOption(IsolationLevel $level) : Node
+ {
+ $defElem = new DefElem();
+ $defElem->setDefname('transaction_isolation');
+
+ $aConst = new A_Const();
+ $sval = new PBString();
+ $sval->setSval($level->value);
+ $aConst->setSval($sval);
+
+ $argNode = new Node();
+ $argNode->setAConst($aConst);
+ $defElem->setArg($argNode);
+
+ $node = new Node();
+ $node->setDefElem($defElem);
+
+ return $node;
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/BeginFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/BeginFinalStep.php
new file mode 100644
index 000000000..5de924ffa
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/BeginFinalStep.php
@@ -0,0 +1,14 @@
+setKind(TransactionStmtKind::TRANS_STMT_COMMIT);
+
+ if ($this->chain !== null) {
+ $stmt->setChain($this->chain);
+ }
+
+ return $stmt;
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/CommitFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/CommitFinalStep.php
new file mode 100644
index 000000000..299380084
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/CommitFinalStep.php
@@ -0,0 +1,14 @@
+setKind($this->kind);
+ $stmt->setGid($this->gid);
+
+ return $stmt;
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/PreparedTransactionFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/PreparedTransactionFinalStep.php
new file mode 100644
index 000000000..951a053ab
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/PreparedTransactionFinalStep.php
@@ -0,0 +1,14 @@
+savepointName,
+ true,
+ );
+ }
+
+ public function andNoChain() : RollbackFinalStep
+ {
+ return new self(
+ $this->savepointName,
+ false,
+ );
+ }
+
+ public function toAst() : TransactionStmt
+ {
+ $stmt = new TransactionStmt();
+
+ if ($this->savepointName !== null) {
+ $stmt->setKind(TransactionStmtKind::TRANS_STMT_ROLLBACK_TO);
+ $stmt->setSavepointName($this->savepointName);
+ } else {
+ $stmt->setKind(TransactionStmtKind::TRANS_STMT_ROLLBACK);
+ }
+
+ if ($this->chain !== null) {
+ $stmt->setChain($this->chain);
+ }
+
+ return $stmt;
+ }
+
+ public function toSavepoint(string $name) : RollbackFinalStep
+ {
+ return new self(
+ $name,
+ $this->chain,
+ );
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/RollbackFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/RollbackFinalStep.php
new file mode 100644
index 000000000..41be971b8
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/RollbackFinalStep.php
@@ -0,0 +1,14 @@
+isRelease) {
+ $stmt->setKind(TransactionStmtKind::TRANS_STMT_RELEASE);
+ } else {
+ $stmt->setKind(TransactionStmtKind::TRANS_STMT_SAVEPOINT);
+ }
+
+ $stmt->setSavepointName($this->name);
+
+ return $stmt;
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/SavepointFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/SavepointFinalStep.php
new file mode 100644
index 000000000..d9cd1d3c1
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/SavepointFinalStep.php
@@ -0,0 +1,14 @@
+isSession,
+ $this->snapshotId,
+ $this->isolationLevel,
+ $this->readOnly,
+ true,
+ );
+ }
+
+ public function isolationLevel(IsolationLevel $level) : SetTransactionOptionsStep
+ {
+ return new self(
+ $this->isSession,
+ $this->snapshotId,
+ $level,
+ $this->readOnly,
+ $this->deferrable,
+ );
+ }
+
+ public function notDeferrable() : SetTransactionOptionsStep
+ {
+ return new self(
+ $this->isSession,
+ $this->snapshotId,
+ $this->isolationLevel,
+ $this->readOnly,
+ false,
+ );
+ }
+
+ public function readOnly() : SetTransactionOptionsStep
+ {
+ return new self(
+ $this->isSession,
+ $this->snapshotId,
+ $this->isolationLevel,
+ true,
+ $this->deferrable,
+ );
+ }
+
+ public function readWrite() : SetTransactionOptionsStep
+ {
+ return new self(
+ $this->isSession,
+ $this->snapshotId,
+ $this->isolationLevel,
+ false,
+ $this->deferrable,
+ );
+ }
+
+ public function snapshot(string $snapshotId) : SetTransactionFinalStep
+ {
+ return new self(
+ $this->isSession,
+ $snapshotId,
+ $this->isolationLevel,
+ $this->readOnly,
+ $this->deferrable,
+ );
+ }
+
+ public function toAst() : VariableSetStmt
+ {
+ $stmt = new VariableSetStmt();
+ $stmt->setKind(VariableSetKind::VAR_SET_MULTI);
+
+ if ($this->snapshotId !== null) {
+ $stmt->setName('TRANSACTION SNAPSHOT');
+ $sval = new PBString();
+ $sval->setSval($this->snapshotId);
+ $aConst = new A_Const();
+ $aConst->setSval($sval);
+ $argNode = new Node();
+ $argNode->setAConst($aConst);
+ $stmt->setArgs([$argNode]);
+ } elseif ($this->isSession) {
+ $stmt->setName('SESSION CHARACTERISTICS');
+ $stmt->setArgs($this->buildOptions());
+ } else {
+ $stmt->setName('TRANSACTION');
+ $stmt->setArgs($this->buildOptions());
+ }
+
+ return $stmt;
+ }
+
+ /**
+ * @return list
+ */
+ private function buildOptions() : array
+ {
+ $options = [];
+
+ if ($this->isolationLevel !== null) {
+ $options[] = $this->createIsolationLevelOption($this->isolationLevel);
+ }
+
+ if ($this->readOnly !== null) {
+ $options[] = $this->createBoolOption('transaction_read_only', $this->readOnly);
+ }
+
+ if ($this->deferrable !== null) {
+ $options[] = $this->createBoolOption('transaction_deferrable', $this->deferrable);
+ }
+
+ return $options;
+ }
+
+ private function createBoolOption(string $name, bool $value) : Node
+ {
+ $defElem = new DefElem();
+ $defElem->setDefname($name);
+
+ $aConst = new A_Const();
+ $ival = new Integer();
+ $ival->setIval($value ? 1 : 0);
+ /** @phpstan-ignore argument.type (protobuf PHPDoc says int but actually expects Integer) */
+ $aConst->setIval($ival);
+
+ $argNode = new Node();
+ $argNode->setAConst($aConst);
+ $defElem->setArg($argNode);
+
+ $node = new Node();
+ $node->setDefElem($defElem);
+
+ return $node;
+ }
+
+ private function createIsolationLevelOption(IsolationLevel $level) : Node
+ {
+ $defElem = new DefElem();
+ $defElem->setDefname('transaction_isolation');
+
+ $aConst = new A_Const();
+ $sval = new PBString();
+ $sval->setSval($level->value);
+ $aConst->setSval($sval);
+
+ $argNode = new Node();
+ $argNode->setAConst($aConst);
+ $defElem->setArg($argNode);
+
+ $node = new Node();
+ $node->setDefElem($defElem);
+
+ return $node;
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/SetTransactionFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/SetTransactionFinalStep.php
new file mode 100644
index 000000000..0de026624
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Transaction/SetTransactionFinalStep.php
@@ -0,0 +1,14 @@
+ $assignments
+ * @param array $from
+ * @param array $returning
+ */
+ private function __construct(
+ private ?WithClause $with = null,
+ private ?string $table = null,
+ private ?string $alias = null,
+ private array $assignments = [],
+ private array $from = [],
+ private ?Condition $where = null,
+ private array $returning = [],
+ ) {
+ }
+
+ public static function create() : UpdateTableStep
+ {
+ return new self();
+ }
+
+ public static function fromAst(Node $node) : static
+ {
+ $updateStmt = $node->getUpdateStmt();
+
+ if ($updateStmt === null) {
+ throw InvalidAstException::unexpectedNodeType('UpdateStmt', 'unknown');
+ }
+
+ $with = null;
+
+ if ($updateStmt->hasWithClause()) {
+ $withClauseProto = $updateStmt->getWithClause();
+ \assert($withClauseProto !== null);
+ $withNode = new Node();
+ $withNode->setWithClause($withClauseProto);
+ $with = WithClause::fromAst($withNode);
+ }
+
+ $relation = $updateStmt->getRelation();
+
+ if ($relation === null) {
+ throw InvalidAstException::missingRequiredField('relation', 'UpdateStmt');
+ }
+
+ $table = $relation->getRelname();
+
+ if ($table === '') {
+ throw InvalidAstException::missingRequiredField('relname', 'RangeVar');
+ }
+
+ $alias = null;
+
+ if ($relation->hasAlias()) {
+ $aliasProto = $relation->getAlias();
+ \assert($aliasProto !== null);
+ $alias = $aliasProto->getAliasname();
+ }
+
+ $targetList = $updateStmt->getTargetList();
+
+ if ($targetList === null || \count($targetList) === 0) {
+ throw InvalidAstException::missingRequiredField('targetList', 'UpdateStmt');
+ }
+
+ $assignments = [];
+
+ foreach ($targetList as $targetNode) {
+ $resTarget = $targetNode->getResTarget();
+
+ if ($resTarget === null) {
+ throw InvalidAstException::unexpectedNodeType('ResTarget', 'unknown');
+ }
+
+ $columnName = $resTarget->getName();
+
+ if ($columnName === '') {
+ throw InvalidAstException::missingRequiredField('name', 'ResTarget');
+ }
+
+ if (!$resTarget->hasVal()) {
+ throw InvalidAstException::missingRequiredField('val', 'ResTarget');
+ }
+
+ $val = $resTarget->getVal();
+ \assert($val !== null);
+
+ $assignments[$columnName] = ExpressionFactory::fromAst($val);
+ }
+
+ $from = [];
+ $fromClause = $updateStmt->getFromClause();
+
+ if ($fromClause !== null && \count($fromClause) > 0) {
+ foreach ($fromClause as $fromNode) {
+ $from[] = self::tableReferenceFromAst($fromNode);
+ }
+ }
+
+ $where = null;
+
+ if ($updateStmt->hasWhereClause()) {
+ $whereNode = $updateStmt->getWhereClause();
+ \assert($whereNode !== null);
+ $where = ConditionFactory::fromAst($whereNode);
+ }
+
+ $returning = [];
+ $returningList = $updateStmt->getReturningList();
+
+ if ($returningList !== null && \count($returningList) > 0) {
+ foreach ($returningList as $returningNode) {
+ $returning[] = ExpressionFactory::fromAst($returningNode);
+ }
+ }
+
+ return new self($with, $table, $alias, $assignments, $from, $where, $returning);
+ }
+
+ public static function with(WithClause $with) : UpdateTableStep
+ {
+ return new self(with: $with);
+ }
+
+ public function from(TableReference ...$tables) : UpdateWhereStep
+ {
+ return new self(
+ with: $this->with,
+ table: $this->table,
+ alias: $this->alias,
+ assignments: $this->assignments,
+ from: $tables,
+ where: $this->where,
+ returning: $this->returning,
+ );
+ }
+
+ public function returning(Expression ...$expressions) : UpdateFinalStep
+ {
+ return new self(
+ with: $this->with,
+ table: $this->table,
+ alias: $this->alias,
+ assignments: $this->assignments,
+ from: $this->from,
+ where: $this->where,
+ returning: $expressions,
+ );
+ }
+
+ public function returningAll() : UpdateFinalStep
+ {
+ return $this->returning(Star::all());
+ }
+
+ public function set(string $column, Expression $value) : UpdateSetStep
+ {
+ return new self(
+ with: $this->with,
+ table: $this->table,
+ alias: $this->alias,
+ assignments: [...$this->assignments, $column => $value],
+ from: $this->from,
+ where: $this->where,
+ returning: $this->returning,
+ );
+ }
+
+ public function setAll(array $assignments) : UpdateFromStep
+ {
+ return new self(
+ with: $this->with,
+ table: $this->table,
+ alias: $this->alias,
+ assignments: [...$this->assignments, ...$assignments],
+ from: $this->from,
+ where: $this->where,
+ returning: $this->returning,
+ );
+ }
+
+ public function toAst() : UpdateStmt
+ {
+ if ($this->table === null || $this->table === '') {
+ throw InvalidExpressionException::invalidValue('table', 'null or empty');
+ }
+
+ if ($this->assignments === []) {
+ throw InvalidExpressionException::emptyArray('assignments');
+ }
+
+ $updateStmt = new UpdateStmt();
+
+ $rangeVar = new RangeVar(['relname' => $this->table, 'inh' => true]);
+
+ if ($this->alias !== null) {
+ $aliasProto = new Alias(['aliasname' => $this->alias]);
+ $rangeVar->setAlias($aliasProto);
+ }
+
+ $updateStmt->setRelation($rangeVar);
+
+ $targetList = [];
+
+ foreach ($this->assignments as $column => $value) {
+ $resTarget = new ResTarget([
+ 'name' => $column,
+ 'val' => $value->toAst(),
+ ]);
+
+ $node = new Node();
+ $node->setResTarget($resTarget);
+
+ $targetList[] = $node;
+ }
+
+ $updateStmt->setTargetList($targetList);
+
+ if ($this->from !== []) {
+ $fromClause = [];
+
+ foreach ($this->from as $table) {
+ $fromClause[] = $table->toAst();
+ }
+
+ $updateStmt->setFromClause($fromClause);
+ }
+
+ if ($this->where !== null) {
+ $updateStmt->setWhereClause($this->where->toAst());
+ }
+
+ if ($this->returning !== []) {
+ $returningList = [];
+
+ foreach ($this->returning as $expression) {
+ $resTarget = new ResTarget();
+ $resTarget->setVal($expression->toAst());
+
+ $node = new Node();
+ $node->setResTarget($resTarget);
+
+ $returningList[] = $node;
+ }
+
+ $updateStmt->setReturningList($returningList);
+ }
+
+ if ($this->with !== null) {
+ $withClauseNode = $this->with->toAst();
+ $withClauseProto = $withClauseNode->getWithClause();
+ \assert($withClauseProto !== null);
+ $updateStmt->setWithClause($withClauseProto);
+ }
+
+ return $updateStmt;
+ }
+
+ public function update(string $table, ?string $alias = null) : UpdateSetStep
+ {
+ return new self(
+ with: $this->with,
+ table: $table,
+ alias: $alias,
+ assignments: $this->assignments,
+ from: $this->from,
+ where: $this->where,
+ returning: $this->returning,
+ );
+ }
+
+ public function where(Condition $condition) : UpdateReturningStep
+ {
+ return new self(
+ with: $this->with,
+ table: $this->table,
+ alias: $this->alias,
+ assignments: $this->assignments,
+ from: $this->from,
+ where: $condition,
+ returning: $this->returning,
+ );
+ }
+
+ private static function tableReferenceFromAst(Node $node) : TableReference
+ {
+ if ($node->getRangeVar() !== null) {
+ return Table::fromAst($node);
+ }
+
+ if ($node->getJoinExpr() !== null) {
+ return JoinedTable::fromAst($node);
+ }
+
+ if ($node->getRangeSubselect() !== null) {
+ return SubqueryReference::fromAst($node);
+ }
+
+ if ($node->getRangeFunction() !== null) {
+ return TableFunction::fromAst($node);
+ }
+
+ throw InvalidAstException::unexpectedNodeType('table reference', 'unknown');
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Update/UpdateFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Update/UpdateFinalStep.php
new file mode 100644
index 000000000..838e9735c
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Update/UpdateFinalStep.php
@@ -0,0 +1,23 @@
+ $assignments Column => value assignments
+ */
+ public function setAll(array $assignments) : UpdateFromStep;
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Update/UpdateTableStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Update/UpdateTableStep.php
new file mode 100644
index 000000000..0d1e7d86c
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Update/UpdateTableStep.php
@@ -0,0 +1,19 @@
+ $relations
+ */
+ private function __construct(
+ private array $relations = [],
+ private bool $verbose = false,
+ private bool $skipLocked = false,
+ ) {
+ }
+
+ public static function create() : AnalyzeFinalStep
+ {
+ return new self();
+ }
+
+ public function skipLocked() : AnalyzeFinalStep
+ {
+ return new self(
+ $this->relations,
+ $this->verbose,
+ true,
+ );
+ }
+
+ public function table(string $table, string ...$columns) : AnalyzeFinalStep
+ {
+ return new self(
+ [...$this->relations, new VacuumRelation($table, $columns)],
+ $this->verbose,
+ $this->skipLocked,
+ );
+ }
+
+ public function tables(string ...$tables) : AnalyzeFinalStep
+ {
+ $relations = $this->relations;
+
+ foreach ($tables as $table) {
+ $relations[] = new VacuumRelation($table);
+ }
+
+ return new self(
+ $relations,
+ $this->verbose,
+ $this->skipLocked,
+ );
+ }
+
+ public function toAst() : VacuumStmt
+ {
+ $stmt = new VacuumStmt();
+ $stmt->setIsVacuumcmd(false);
+
+ $options = [];
+
+ if ($this->verbose) {
+ $options[] = $this->createDefElemBool('verbose');
+ }
+
+ if ($this->skipLocked) {
+ $options[] = $this->createDefElemBool('skip_locked');
+ }
+
+ if ($options !== []) {
+ $stmt->setOptions($options);
+ }
+
+ $rels = [];
+
+ foreach ($this->relations as $relation) {
+ $identifier = QualifiedIdentifier::parse($relation->table);
+ $rangeVar = new RangeVar();
+
+ $schema = $identifier->schema();
+
+ if ($schema !== null) {
+ $rangeVar->setSchemaname($schema);
+ }
+
+ $rangeVar->setRelname($identifier->name());
+ $rangeVar->setInh(true);
+ $rangeVar->setRelpersistence('p');
+
+ $vacuumRel = new VacuumRelationAST();
+ $vacuumRel->setRelation($rangeVar);
+
+ if ($relation->columns !== []) {
+ $cols = [];
+
+ foreach ($relation->columns as $column) {
+ $str = new PBString();
+ $str->setSval($column);
+ $colNode = new Node();
+ $colNode->setString($str);
+ $cols[] = $colNode;
+ }
+
+ $vacuumRel->setVaCols($cols);
+ }
+
+ $relNode = new Node();
+ $relNode->setVacuumRelation($vacuumRel);
+ $rels[] = $relNode;
+ }
+
+ if ($rels !== []) {
+ $stmt->setRels($rels);
+ }
+
+ return $stmt;
+ }
+
+ public function verbose() : AnalyzeFinalStep
+ {
+ return new self(
+ $this->relations,
+ true,
+ $this->skipLocked,
+ );
+ }
+
+ private function createDefElemBool(string $name) : Node
+ {
+ $defElem = new DefElem();
+ $defElem->setDefname($name);
+
+ $node = new Node();
+ $node->setDefElem($defElem);
+
+ return $node;
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/AnalyzeFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/AnalyzeFinalStep.php
new file mode 100644
index 000000000..3bf0dcddd
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/AnalyzeFinalStep.php
@@ -0,0 +1,22 @@
+index, $this->verbose);
+ }
+
+ public function toAst() : ClusterStmt
+ {
+ $stmt = new ClusterStmt();
+
+ if ($this->table !== null) {
+ $identifier = QualifiedIdentifier::parse($this->table);
+ $rangeVar = new RangeVar();
+
+ $schema = $identifier->schema();
+
+ if ($schema !== null) {
+ $rangeVar->setSchemaname($schema);
+ }
+
+ $rangeVar->setRelname($identifier->name());
+ $rangeVar->setInh(true);
+ $rangeVar->setRelpersistence('p');
+
+ $stmt->setRelation($rangeVar);
+ }
+
+ if ($this->index !== null) {
+ $stmt->setIndexname($this->index);
+ }
+
+ if ($this->verbose) {
+ $defElem = new DefElem();
+ $defElem->setDefname('verbose');
+
+ $node = new Node();
+ $node->setDefElem($defElem);
+
+ $stmt->setParams([$node]);
+ }
+
+ return $stmt;
+ }
+
+ public function using(string $index) : ClusterFinalStep
+ {
+ return new self($this->table, $index, $this->verbose);
+ }
+
+ public function verbose() : ClusterFinalStep
+ {
+ return new self($this->table, $this->index, true);
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/ClusterFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/ClusterFinalStep.php
new file mode 100644
index 000000000..c25da7fa2
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/ClusterFinalStep.php
@@ -0,0 +1,20 @@
+target, $this->name, $comment);
+ }
+
+ public function isNull() : CommentFinalStep
+ {
+ return new self($this->target, $this->name, null);
+ }
+
+ public function toAst() : CommentStmt
+ {
+ $stmt = new CommentStmt();
+ $stmt->setObjtype($this->target->value);
+
+ $objectNode = $this->buildObjectNode();
+ $stmt->setObject($objectNode);
+
+ if ($this->comment !== null) {
+ $stmt->setComment($this->comment);
+ }
+
+ return $stmt;
+ }
+
+ private function buildObjectNode() : Node
+ {
+ $node = new Node();
+
+ if ($this->target === CommentTarget::COLUMN) {
+ $identifier = QualifiedIdentifier::parse($this->name);
+ $list = new PBList();
+ $items = [];
+
+ foreach ($identifier->parts() as $part) {
+ $str = new PBString();
+ $str->setSval($part);
+ $strNode = new Node();
+ $strNode->setString($str);
+ $items[] = $strNode;
+ }
+
+ $list->setItems($items);
+ $node->setList($list);
+ } elseif (\in_array($this->target, [CommentTarget::FUNCTION, CommentTarget::PROCEDURE], true)) {
+ $identifier = QualifiedIdentifier::parse($this->name);
+ $list = new PBList();
+ $items = [];
+
+ foreach ($identifier->parts() as $part) {
+ $str = new PBString();
+ $str->setSval($part);
+ $strNode = new Node();
+ $strNode->setString($str);
+ $items[] = $strNode;
+ }
+
+ $list->setItems($items);
+ $node->setList($list);
+ } elseif (\in_array($this->target->value, [
+ ObjectType::OBJECT_TABLE,
+ ObjectType::OBJECT_INDEX,
+ ObjectType::OBJECT_SEQUENCE,
+ ObjectType::OBJECT_VIEW,
+ ObjectType::OBJECT_MATVIEW,
+ ObjectType::OBJECT_TRIGGER,
+ ObjectType::OBJECT_TYPE,
+ ], true)) {
+ $identifier = QualifiedIdentifier::parse($this->name);
+ $list = new PBList();
+ $items = [];
+
+ foreach ($identifier->parts() as $part) {
+ $str = new PBString();
+ $str->setSval($part);
+ $strNode = new Node();
+ $strNode->setString($str);
+ $items[] = $strNode;
+ }
+
+ $list->setItems($items);
+ $node->setList($list);
+ } else {
+ $str = new PBString();
+ $str->setSval($this->name);
+ $node->setString($str);
+ }
+
+ return $node;
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/CommentFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/CommentFinalStep.php
new file mode 100644
index 000000000..49ea4919f
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/CommentFinalStep.php
@@ -0,0 +1,18 @@
+setTarget($this->type->value);
+
+ return $stmt;
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/DiscardFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/DiscardFinalStep.php
new file mode 100644
index 000000000..b811aa0f5
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/DiscardFinalStep.php
@@ -0,0 +1,14 @@
+query,
+ true,
+ $this->verbose,
+ $this->costs,
+ $this->settings,
+ $this->buffers,
+ $this->wal,
+ $this->timing,
+ $this->summary,
+ $this->memory,
+ $this->format,
+ );
+ }
+
+ public function buffers(bool $enabled = true) : ExplainFinalStep
+ {
+ return new self(
+ $this->query,
+ $this->analyze,
+ $this->verbose,
+ $this->costs,
+ $this->settings,
+ $enabled,
+ $this->wal,
+ $this->timing,
+ $this->summary,
+ $this->memory,
+ $this->format,
+ );
+ }
+
+ public function costs(bool $enabled = true) : ExplainFinalStep
+ {
+ return new self(
+ $this->query,
+ $this->analyze,
+ $this->verbose,
+ $enabled,
+ $this->settings,
+ $this->buffers,
+ $this->wal,
+ $this->timing,
+ $this->summary,
+ $this->memory,
+ $this->format,
+ );
+ }
+
+ public function format(ExplainFormat $format) : ExplainFinalStep
+ {
+ return new self(
+ $this->query,
+ $this->analyze,
+ $this->verbose,
+ $this->costs,
+ $this->settings,
+ $this->buffers,
+ $this->wal,
+ $this->timing,
+ $this->summary,
+ $this->memory,
+ $format,
+ );
+ }
+
+ public function memory(bool $enabled = true) : ExplainFinalStep
+ {
+ return new self(
+ $this->query,
+ $this->analyze,
+ $this->verbose,
+ $this->costs,
+ $this->settings,
+ $this->buffers,
+ $this->wal,
+ $this->timing,
+ $this->summary,
+ $enabled,
+ $this->format,
+ );
+ }
+
+ public function settings(bool $enabled = true) : ExplainFinalStep
+ {
+ return new self(
+ $this->query,
+ $this->analyze,
+ $this->verbose,
+ $this->costs,
+ $enabled,
+ $this->buffers,
+ $this->wal,
+ $this->timing,
+ $this->summary,
+ $this->memory,
+ $this->format,
+ );
+ }
+
+ public function summary(bool $enabled = true) : ExplainFinalStep
+ {
+ return new self(
+ $this->query,
+ $this->analyze,
+ $this->verbose,
+ $this->costs,
+ $this->settings,
+ $this->buffers,
+ $this->wal,
+ $this->timing,
+ $enabled,
+ $this->memory,
+ $this->format,
+ );
+ }
+
+ public function timing(bool $enabled = true) : ExplainFinalStep
+ {
+ return new self(
+ $this->query,
+ $this->analyze,
+ $this->verbose,
+ $this->costs,
+ $this->settings,
+ $this->buffers,
+ $this->wal,
+ $enabled,
+ $this->summary,
+ $this->memory,
+ $this->format,
+ );
+ }
+
+ public function toAst() : ExplainStmt
+ {
+ $stmt = new ExplainStmt();
+
+ $queryNode = new Node();
+
+ if ($this->query instanceof SelectFinalStep) {
+ $queryNode->setSelectStmt($this->query->toAst());
+ } elseif ($this->query instanceof InsertFinalStep) {
+ $queryNode->setInsertStmt($this->query->toAst());
+ } elseif ($this->query instanceof UpdateFinalStep) {
+ $queryNode->setUpdateStmt($this->query->toAst());
+ } else {
+ $queryNode->setDeleteStmt($this->query->toAst());
+ }
+
+ $stmt->setQuery($queryNode);
+
+ $options = [];
+
+ if ($this->analyze) {
+ $options[] = $this->createDefElemBool('analyze');
+ }
+
+ if ($this->verbose) {
+ $options[] = $this->createDefElemBool('verbose');
+ }
+
+ if ($this->costs !== null) {
+ $options[] = $this->createDefElemInt('costs', $this->costs ? 1 : 0);
+ }
+
+ if ($this->settings !== null) {
+ $options[] = $this->createDefElemInt('settings', $this->settings ? 1 : 0);
+ }
+
+ if ($this->buffers !== null) {
+ $options[] = $this->createDefElemInt('buffers', $this->buffers ? 1 : 0);
+ }
+
+ if ($this->wal !== null) {
+ $options[] = $this->createDefElemInt('wal', $this->wal ? 1 : 0);
+ }
+
+ if ($this->timing !== null) {
+ $options[] = $this->createDefElemInt('timing', $this->timing ? 1 : 0);
+ }
+
+ if ($this->summary !== null) {
+ $options[] = $this->createDefElemInt('summary', $this->summary ? 1 : 0);
+ }
+
+ if ($this->memory !== null) {
+ $options[] = $this->createDefElemInt('memory', $this->memory ? 1 : 0);
+ }
+
+ if ($this->format !== null) {
+ $options[] = $this->createDefElemString('format', $this->format->value);
+ }
+
+ if ($options !== []) {
+ $stmt->setOptions($options);
+ }
+
+ return $stmt;
+ }
+
+ public function verbose() : ExplainFinalStep
+ {
+ return new self(
+ $this->query,
+ $this->analyze,
+ true,
+ $this->costs,
+ $this->settings,
+ $this->buffers,
+ $this->wal,
+ $this->timing,
+ $this->summary,
+ $this->memory,
+ $this->format,
+ );
+ }
+
+ public function wal(bool $enabled = true) : ExplainFinalStep
+ {
+ return new self(
+ $this->query,
+ $this->analyze,
+ $this->verbose,
+ $this->costs,
+ $this->settings,
+ $this->buffers,
+ $enabled,
+ $this->timing,
+ $this->summary,
+ $this->memory,
+ $this->format,
+ );
+ }
+
+ private function createDefElemBool(string $name) : Node
+ {
+ $defElem = new DefElem();
+ $defElem->setDefname($name);
+
+ $node = new Node();
+ $node->setDefElem($defElem);
+
+ return $node;
+ }
+
+ private function createDefElemInt(string $name, int $value) : Node
+ {
+ $defElem = new DefElem();
+ $defElem->setDefname($name);
+
+ $int = new Integer();
+ $int->setIval($value);
+
+ $intNode = new Node();
+ /** @phpstan-ignore argument.type (protobuf PHPDoc says int but actually expects Integer) */
+ $intNode->setInteger($int);
+ $defElem->setArg($intNode);
+
+ $node = new Node();
+ $node->setDefElem($defElem);
+
+ return $node;
+ }
+
+ private function createDefElemString(string $name, string $value) : Node
+ {
+ $defElem = new DefElem();
+ $defElem->setDefname($name);
+
+ $str = new PBString();
+ $str->setSval($value);
+
+ $strNode = new Node();
+ $strNode->setString($str);
+ $defElem->setArg($strNode);
+
+ $node = new Node();
+ $node->setDefElem($defElem);
+
+ return $node;
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/ExplainFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/ExplainFinalStep.php
new file mode 100644
index 000000000..3616b198d
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/ExplainFinalStep.php
@@ -0,0 +1,34 @@
+ $tables
+ */
+ private function __construct(
+ private array $tables,
+ private LockMode $mode = LockMode::ACCESS_EXCLUSIVE,
+ private bool $nowait = false,
+ ) {
+ }
+
+ public static function create(string ...$tables) : LockFinalStep
+ {
+ return new self($tables);
+ }
+
+ public function accessExclusive() : LockFinalStep
+ {
+ return new self($this->tables, LockMode::ACCESS_EXCLUSIVE, $this->nowait);
+ }
+
+ public function accessShare() : LockFinalStep
+ {
+ return new self($this->tables, LockMode::ACCESS_SHARE, $this->nowait);
+ }
+
+ public function exclusive() : LockFinalStep
+ {
+ return new self($this->tables, LockMode::EXCLUSIVE, $this->nowait);
+ }
+
+ public function inMode(LockMode $mode) : LockFinalStep
+ {
+ return new self($this->tables, $mode, $this->nowait);
+ }
+
+ public function nowait() : LockFinalStep
+ {
+ return new self($this->tables, $this->mode, true);
+ }
+
+ public function rowExclusive() : LockFinalStep
+ {
+ return new self($this->tables, LockMode::ROW_EXCLUSIVE, $this->nowait);
+ }
+
+ public function rowShare() : LockFinalStep
+ {
+ return new self($this->tables, LockMode::ROW_SHARE, $this->nowait);
+ }
+
+ public function share() : LockFinalStep
+ {
+ return new self($this->tables, LockMode::SHARE, $this->nowait);
+ }
+
+ public function shareRowExclusive() : LockFinalStep
+ {
+ return new self($this->tables, LockMode::SHARE_ROW_EXCLUSIVE, $this->nowait);
+ }
+
+ public function shareUpdateExclusive() : LockFinalStep
+ {
+ return new self($this->tables, LockMode::SHARE_UPDATE_EXCLUSIVE, $this->nowait);
+ }
+
+ public function toAst() : LockStmt
+ {
+ $stmt = new LockStmt();
+ $stmt->setMode($this->mode->value);
+ $stmt->setNowait($this->nowait);
+
+ $relations = [];
+
+ foreach ($this->tables as $table) {
+ $identifier = QualifiedIdentifier::parse($table);
+ $rangeVar = new RangeVar();
+
+ $schema = $identifier->schema();
+
+ if ($schema !== null) {
+ $rangeVar->setSchemaname($schema);
+ }
+
+ $rangeVar->setRelname($identifier->name());
+ $rangeVar->setInh(true);
+ $rangeVar->setRelpersistence('p');
+
+ $node = new Node();
+ $node->setRangeVar($rangeVar);
+ $relations[] = $node;
+ }
+
+ $stmt->setRelations($relations);
+
+ return $stmt;
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/LockFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/LockFinalStep.php
new file mode 100644
index 000000000..1005cf7ba
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/LockFinalStep.php
@@ -0,0 +1,34 @@
+ $relations
+ */
+ private function __construct(
+ private array $relations = [],
+ private bool $full = false,
+ private bool $freeze = false,
+ private bool $verbose = false,
+ private bool $analyze = false,
+ private bool $disablePageSkipping = false,
+ private bool $skipLocked = false,
+ private ?IndexCleanup $indexCleanup = null,
+ private ?bool $processMain = null,
+ private ?bool $processToast = null,
+ private ?bool $truncate = null,
+ private ?int $parallel = null,
+ ) {
+ }
+
+ public static function create() : VacuumFinalStep
+ {
+ return new self();
+ }
+
+ public function analyze() : VacuumFinalStep
+ {
+ return new self(
+ $this->relations,
+ $this->full,
+ $this->freeze,
+ $this->verbose,
+ true,
+ $this->disablePageSkipping,
+ $this->skipLocked,
+ $this->indexCleanup,
+ $this->processMain,
+ $this->processToast,
+ $this->truncate,
+ $this->parallel,
+ );
+ }
+
+ public function disablePageSkipping() : VacuumFinalStep
+ {
+ return new self(
+ $this->relations,
+ $this->full,
+ $this->freeze,
+ $this->verbose,
+ $this->analyze,
+ true,
+ $this->skipLocked,
+ $this->indexCleanup,
+ $this->processMain,
+ $this->processToast,
+ $this->truncate,
+ $this->parallel,
+ );
+ }
+
+ public function freeze() : VacuumFinalStep
+ {
+ return new self(
+ $this->relations,
+ $this->full,
+ true,
+ $this->verbose,
+ $this->analyze,
+ $this->disablePageSkipping,
+ $this->skipLocked,
+ $this->indexCleanup,
+ $this->processMain,
+ $this->processToast,
+ $this->truncate,
+ $this->parallel,
+ );
+ }
+
+ public function full() : VacuumFinalStep
+ {
+ return new self(
+ $this->relations,
+ true,
+ $this->freeze,
+ $this->verbose,
+ $this->analyze,
+ $this->disablePageSkipping,
+ $this->skipLocked,
+ $this->indexCleanup,
+ $this->processMain,
+ $this->processToast,
+ $this->truncate,
+ $this->parallel,
+ );
+ }
+
+ public function indexCleanup(IndexCleanup $cleanup) : VacuumFinalStep
+ {
+ return new self(
+ $this->relations,
+ $this->full,
+ $this->freeze,
+ $this->verbose,
+ $this->analyze,
+ $this->disablePageSkipping,
+ $this->skipLocked,
+ $cleanup,
+ $this->processMain,
+ $this->processToast,
+ $this->truncate,
+ $this->parallel,
+ );
+ }
+
+ public function parallel(int $workers) : VacuumFinalStep
+ {
+ return new self(
+ $this->relations,
+ $this->full,
+ $this->freeze,
+ $this->verbose,
+ $this->analyze,
+ $this->disablePageSkipping,
+ $this->skipLocked,
+ $this->indexCleanup,
+ $this->processMain,
+ $this->processToast,
+ $this->truncate,
+ $workers,
+ );
+ }
+
+ public function processMain(bool $enabled) : VacuumFinalStep
+ {
+ return new self(
+ $this->relations,
+ $this->full,
+ $this->freeze,
+ $this->verbose,
+ $this->analyze,
+ $this->disablePageSkipping,
+ $this->skipLocked,
+ $this->indexCleanup,
+ $enabled,
+ $this->processToast,
+ $this->truncate,
+ $this->parallel,
+ );
+ }
+
+ public function processToast(bool $enabled) : VacuumFinalStep
+ {
+ return new self(
+ $this->relations,
+ $this->full,
+ $this->freeze,
+ $this->verbose,
+ $this->analyze,
+ $this->disablePageSkipping,
+ $this->skipLocked,
+ $this->indexCleanup,
+ $this->processMain,
+ $enabled,
+ $this->truncate,
+ $this->parallel,
+ );
+ }
+
+ public function skipLocked() : VacuumFinalStep
+ {
+ return new self(
+ $this->relations,
+ $this->full,
+ $this->freeze,
+ $this->verbose,
+ $this->analyze,
+ $this->disablePageSkipping,
+ true,
+ $this->indexCleanup,
+ $this->processMain,
+ $this->processToast,
+ $this->truncate,
+ $this->parallel,
+ );
+ }
+
+ public function table(string $table, string ...$columns) : VacuumFinalStep
+ {
+ return new self(
+ [...$this->relations, new VacuumRelation($table, $columns)],
+ $this->full,
+ $this->freeze,
+ $this->verbose,
+ $this->analyze,
+ $this->disablePageSkipping,
+ $this->skipLocked,
+ $this->indexCleanup,
+ $this->processMain,
+ $this->processToast,
+ $this->truncate,
+ $this->parallel,
+ );
+ }
+
+ public function tables(string ...$tables) : VacuumFinalStep
+ {
+ $relations = $this->relations;
+
+ foreach ($tables as $table) {
+ $relations[] = new VacuumRelation($table);
+ }
+
+ return new self(
+ $relations,
+ $this->full,
+ $this->freeze,
+ $this->verbose,
+ $this->analyze,
+ $this->disablePageSkipping,
+ $this->skipLocked,
+ $this->indexCleanup,
+ $this->processMain,
+ $this->processToast,
+ $this->truncate,
+ $this->parallel,
+ );
+ }
+
+ public function toAst() : VacuumStmt
+ {
+ $stmt = new VacuumStmt();
+ $stmt->setIsVacuumcmd(true);
+
+ $options = [];
+
+ if ($this->full) {
+ $options[] = $this->createDefElemBool('full');
+ }
+
+ if ($this->freeze) {
+ $options[] = $this->createDefElemBool('freeze');
+ }
+
+ if ($this->verbose) {
+ $options[] = $this->createDefElemBool('verbose');
+ }
+
+ if ($this->analyze) {
+ $options[] = $this->createDefElemBool('analyze');
+ }
+
+ if ($this->disablePageSkipping) {
+ $options[] = $this->createDefElemBool('disable_page_skipping');
+ }
+
+ if ($this->skipLocked) {
+ $options[] = $this->createDefElemBool('skip_locked');
+ }
+
+ if ($this->indexCleanup !== null) {
+ $options[] = $this->createDefElemString('index_cleanup', $this->indexCleanup->value);
+ }
+
+ if ($this->processMain !== null) {
+ $options[] = $this->createDefElemInt('process_main', $this->processMain ? 1 : 0);
+ }
+
+ if ($this->processToast !== null) {
+ $options[] = $this->createDefElemInt('process_toast', $this->processToast ? 1 : 0);
+ }
+
+ if ($this->truncate !== null) {
+ $options[] = $this->createDefElemInt('truncate', $this->truncate ? 1 : 0);
+ }
+
+ if ($this->parallel !== null) {
+ $options[] = $this->createDefElemInt('parallel', $this->parallel);
+ }
+
+ if ($options !== []) {
+ $stmt->setOptions($options);
+ }
+
+ $rels = [];
+
+ foreach ($this->relations as $relation) {
+ $identifier = QualifiedIdentifier::parse($relation->table);
+ $rangeVar = new RangeVar();
+
+ $schema = $identifier->schema();
+
+ if ($schema !== null) {
+ $rangeVar->setSchemaname($schema);
+ }
+
+ $rangeVar->setRelname($identifier->name());
+ $rangeVar->setInh(true);
+ $rangeVar->setRelpersistence('p');
+
+ $vacuumRel = new VacuumRelationAST();
+ $vacuumRel->setRelation($rangeVar);
+
+ if ($relation->columns !== []) {
+ $cols = [];
+
+ foreach ($relation->columns as $column) {
+ $str = new PBString();
+ $str->setSval($column);
+ $colNode = new Node();
+ $colNode->setString($str);
+ $cols[] = $colNode;
+ }
+
+ $vacuumRel->setVaCols($cols);
+ }
+
+ $relNode = new Node();
+ $relNode->setVacuumRelation($vacuumRel);
+ $rels[] = $relNode;
+ }
+
+ if ($rels !== []) {
+ $stmt->setRels($rels);
+ }
+
+ return $stmt;
+ }
+
+ public function truncate(bool $enabled) : VacuumFinalStep
+ {
+ return new self(
+ $this->relations,
+ $this->full,
+ $this->freeze,
+ $this->verbose,
+ $this->analyze,
+ $this->disablePageSkipping,
+ $this->skipLocked,
+ $this->indexCleanup,
+ $this->processMain,
+ $this->processToast,
+ $enabled,
+ $this->parallel,
+ );
+ }
+
+ public function verbose() : VacuumFinalStep
+ {
+ return new self(
+ $this->relations,
+ $this->full,
+ $this->freeze,
+ true,
+ $this->analyze,
+ $this->disablePageSkipping,
+ $this->skipLocked,
+ $this->indexCleanup,
+ $this->processMain,
+ $this->processToast,
+ $this->truncate,
+ $this->parallel,
+ );
+ }
+
+ private function createDefElemBool(string $name) : Node
+ {
+ $defElem = new DefElem();
+ $defElem->setDefname($name);
+
+ $node = new Node();
+ $node->setDefElem($defElem);
+
+ return $node;
+ }
+
+ private function createDefElemInt(string $name, int $value) : Node
+ {
+ $defElem = new DefElem();
+ $defElem->setDefname($name);
+
+ $int = new Integer();
+ $int->setIval($value);
+
+ $intNode = new Node();
+ /** @phpstan-ignore argument.type (protobuf PHPDoc says int but actually expects Integer) */
+ $intNode->setInteger($int);
+ $defElem->setArg($intNode);
+
+ $node = new Node();
+ $node->setDefElem($defElem);
+
+ return $node;
+ }
+
+ private function createDefElemString(string $name, string $value) : Node
+ {
+ $defElem = new DefElem();
+ $defElem->setDefname($name);
+
+ $str = new PBString();
+ $str->setSval($value);
+
+ $strNode = new Node();
+ $strNode->setString($str);
+ $defElem->setArg($strNode);
+
+ $node = new Node();
+ $node->setDefElem($defElem);
+
+ return $node;
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/VacuumFinalStep.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/VacuumFinalStep.php
new file mode 100644
index 000000000..fc59e5129
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/Utility/VacuumFinalStep.php
@@ -0,0 +1,40 @@
+ $columns
+ */
+ public function __construct(
+ public string $table,
+ public array $columns = [],
+ ) {
+ }
+}
diff --git a/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/With/WithBuilder.php b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/With/WithBuilder.php
new file mode 100644
index 000000000..7420d374c
--- /dev/null
+++ b/src/lib/postgresql/src/Flow/PostgreSql/QueryBuilder/With/WithBuilder.php
@@ -0,0 +1,75 @@
+withClause);
+ }
+
+ /**
+ * Start an INSERT query with this WITH clause.
+ */
+ public function insert() : InsertIntoStep
+ {
+ return InsertBuilder::with($this->withClause);
+ }
+
+ /**
+ * Start a MERGE query with this WITH clause.
+ */
+ public function merge(string $table, ?string $alias = null) : MergeUsingStep
+ {
+ return MergeBuilder::with($this->withClause)->into($table, $alias);
+ }
+
+ /**
+ * Mark this WITH clause as recursive.
+ */
+ public function recursive() : self
+ {
+ return new self(new WithClause($this->withClause->ctes(), true));
+ }
+
+ /**
+ * Start a SELECT query with this WITH clause.
+ */
+ public function select(Expression ...$expressions) : SelectFromStep|SelectSelectStep
+ {
+ $builder = SelectBuilder::with($this->withClause);
+
+ if ($expressions !== []) {
+ return $builder->select(...$expressions);
+ }
+
+ return $builder;
+ }
+
+ /**
+ * Start an UPDATE query with this WITH clause.
+ */
+ public function update() : UpdateTableStep
+ {
+ return UpdateBuilder::with($this->withClause);
+ }
+}
diff --git a/src/lib/pg-query/src/stubs.php b/src/lib/postgresql/src/stubs.php
similarity index 100%
rename from src/lib/pg-query/src/stubs.php
rename to src/lib/postgresql/src/stubs.php
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
new file mode 100644
index 000000000..bc79d879a
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Assertions/QueryBuilderAssertions.php
@@ -0,0 +1,1002 @@
+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);
+
+ $rebuilt = DeleteBuilder::fromAst($rebuiltStmt);
+ $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);
+
+ $rebuilt = InsertBuilder::fromAst($rebuiltStmt);
+ $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);
+
+ $rebuilt = SelectBuilder::fromAst($rebuiltStmt);
+ $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);
+
+ $rebuilt = UpdateBuilder::fromAst($rebuiltStmt);
+ $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/CopyBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/CopyBuilderTest.php
new file mode 100644
index 000000000..4b27d1e03
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/CopyBuilderTest.php
@@ -0,0 +1,291 @@
+from('users')
+ ->file('/tmp/users.csv');
+
+ $this->assertCopyFromQueryEquals(
+ $query,
+ "COPY users FROM '/tmp/users.csv'"
+ );
+ }
+
+ public function test_copy_from_csv_with_header() : void
+ {
+ $query = copy()
+ ->from('users')
+ ->file('/tmp/users.csv')
+ ->format(CopyFormat::CSV)
+ ->withHeader();
+
+ $this->assertCopyFromQueryEquals(
+ $query,
+ "COPY users FROM '/tmp/users.csv' WITH (FORMAT CSV, HEADER true)"
+ );
+ }
+
+ public function test_copy_from_program() : void
+ {
+ $query = copy()
+ ->from('logs')
+ ->program('gunzip -c /var/log/app.log.gz');
+
+ $this->assertCopyFromQueryEquals(
+ $query,
+ "COPY logs FROM PROGRAM 'gunzip -c /var/log/app.log.gz'"
+ );
+ }
+
+ public function test_copy_from_stdin() : void
+ {
+ $query = copy()
+ ->from('users')
+ ->stdin()
+ ->format(CopyFormat::CSV);
+
+ $this->assertCopyFromQueryEquals(
+ $query,
+ 'COPY users FROM STDIN CSV'
+ );
+ }
+
+ public function test_copy_from_with_all_csv_options() : void
+ {
+ $query = copy()
+ ->from('data')
+ ->file('/tmp/data.csv')
+ ->format(CopyFormat::CSV)
+ ->withHeader()
+ ->delimiter(';')
+ ->nullAs('NULL')
+ ->quote("'")
+ ->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')"
+ );
+ }
+
+ public function test_copy_from_with_columns() : void
+ {
+ $query = copy()
+ ->from('users')
+ ->columns('id', 'name', 'email')
+ ->file('/tmp/users.csv');
+
+ $this->assertCopyFromQueryEquals(
+ $query,
+ "COPY users(id, name, email) FROM '/tmp/users.csv'"
+ );
+ }
+
+ public function test_copy_from_with_force_not_null() : void
+ {
+ $query = copy()
+ ->from('users')
+ ->file('/tmp/users.csv')
+ ->format(CopyFormat::CSV)
+ ->forceNotNull('name', 'email');
+
+ $this->assertCopyFromQueryEquals(
+ $query,
+ "COPY users FROM '/tmp/users.csv' WITH (FORMAT CSV, FORCE_NOT_NULL (name, email))"
+ );
+ }
+
+ public function test_copy_from_with_on_error_ignore() : void
+ {
+ $query = copy()
+ ->from('events')
+ ->file('/tmp/events.csv')
+ ->onError(CopyOnError::IGNORE);
+
+ $this->assertCopyFromQueryEquals(
+ $query,
+ "COPY events FROM '/tmp/events.csv' WITH (on_error ignore)"
+ );
+ }
+
+ public function test_copy_to_basic() : void
+ {
+ $query = copy()
+ ->to('users')
+ ->file('/tmp/users.csv');
+
+ $this->assertCopyToQueryEquals(
+ $query,
+ "COPY users TO '/tmp/users.csv'"
+ );
+ }
+
+ public function test_copy_to_binary_format() : void
+ {
+ $query = copy()
+ ->to('data')
+ ->file('/tmp/data.bin')
+ ->format(CopyFormat::BINARY);
+
+ $this->assertCopyToQueryEquals(
+ $query,
+ "COPY data TO '/tmp/data.bin' WITH (FORMAT BINARY)"
+ );
+ }
+
+ public function test_copy_to_csv_with_header() : void
+ {
+ $query = copy()
+ ->to('users')
+ ->file('/tmp/users.csv')
+ ->format(CopyFormat::CSV)
+ ->withHeader();
+
+ $this->assertCopyToQueryEquals(
+ $query,
+ "COPY users TO '/tmp/users.csv' WITH (FORMAT CSV, HEADER true)"
+ );
+ }
+
+ public function test_copy_to_program() : void
+ {
+ $query = copy()
+ ->to('logs')
+ ->program('gzip > /tmp/logs.csv.gz');
+
+ $this->assertCopyToQueryEquals(
+ $query,
+ "COPY logs TO PROGRAM 'gzip > /tmp/logs.csv.gz'"
+ );
+ }
+
+ public function test_copy_to_stdout() : void
+ {
+ $query = copy()
+ ->to('users')
+ ->stdout()
+ ->format(CopyFormat::CSV);
+
+ $this->assertCopyToQueryEquals(
+ $query,
+ 'COPY users TO STDOUT CSV'
+ );
+ }
+
+ public function test_copy_to_with_columns() : void
+ {
+ $query = copy()
+ ->to('users')
+ ->columns('id', 'name', 'email')
+ ->file('/tmp/users.csv');
+
+ $this->assertCopyToQueryEquals(
+ $query,
+ "COPY users(id, name, email) TO '/tmp/users.csv'"
+ );
+ }
+
+ public function test_copy_to_with_force_quote_all() : void
+ {
+ $query = copy()
+ ->to('products')
+ ->file('/tmp/products.csv')
+ ->format(CopyFormat::CSV)
+ ->forceQuoteAll();
+
+ $this->assertCopyToQueryEquals(
+ $query,
+ "COPY products TO '/tmp/products.csv' WITH (FORMAT CSV, FORCE_QUOTE *)"
+ );
+ }
+
+ public function test_copy_to_with_force_quote_columns() : void
+ {
+ $query = copy()
+ ->to('products')
+ ->file('/tmp/products.csv')
+ ->format(CopyFormat::CSV)
+ ->forceQuote('name', 'description');
+
+ $this->assertCopyToQueryEquals(
+ $query,
+ "COPY products TO '/tmp/products.csv' CSV FORCE QUOTE name, description"
+ );
+ }
+
+ public function test_copy_to_with_query() : void
+ {
+ $selectQuery = select()
+ ->select(col('id'), col('name'))
+ ->from(new Table('users'));
+
+ $query = copy()
+ ->toQuery($selectQuery)
+ ->file('/tmp/active_users.csv')
+ ->format(CopyFormat::CSV);
+
+ $this->assertCopyToQueryEquals(
+ $query,
+ "COPY (SELECT id, name FROM users) TO '/tmp/active_users.csv' CSV"
+ );
+ }
+
+ public function test_copy_to_with_schema() : void
+ {
+ $query = copy()
+ ->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();
+ }
+}
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
new file mode 100644
index 000000000..df7d8dd9a
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/DatabaseTestCase.php
@@ -0,0 +1,134 @@
+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
new file mode 100644
index 000000000..7caee4eed
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/DeleteDatabaseTest.php
@@ -0,0 +1,200 @@
+execute(
+ create()->table(self::TABLE_LOGS)
+ ->column(column('id', sql_type_serial()))
+ ->column(column('level', sql_type_varchar(20))->notNull())
+ ->column(column('message', sql_type_text()))
+ ->column(column('created_at', sql_type_timestamp()))
+ ->constraint(primary_key('id'))
+ ->toSql()
+ );
+
+ $this->execute(
+ create()->table(self::TABLE_ARCHIVE)
+ ->column(column('id', sql_type_serial()))
+ ->column(column('log_id', sql_type_integer())->notNull())
+ ->constraint(primary_key('id'))
+ ->toSql()
+ );
+
+ $this->execute(
+ insert()
+ ->into(self::TABLE_LOGS)
+ ->columns('level', 'message')
+ ->values(literal('INFO'), literal('Application started'))
+ ->values(literal('DEBUG'), literal('Debug message 1'))
+ ->values(literal('DEBUG'), literal('Debug message 2'))
+ ->values(literal('WARNING'), literal('Warning message'))
+ ->values(literal('ERROR'), literal('Error occurred'))
+ ->toSql()
+ );
+
+ $this->execute(
+ insert()
+ ->into(self::TABLE_ARCHIVE)
+ ->columns('log_id')
+ ->values(literal(1))
+ ->values(literal(2))
+ ->toSql()
+ );
+ }
+
+ protected function tearDown() : void
+ {
+ $this->dropTableIfExists(self::TABLE_ARCHIVE);
+ $this->dropTableIfExists(self::TABLE_LOGS);
+
+ parent::tearDown();
+ }
+
+ public function test_delete_all() : void
+ {
+ $query = delete()
+ ->from(self::TABLE_ARCHIVE);
+
+ $result = $this->execute($query->toSql());
+
+ self::assertNotFalse($result);
+ self::assertSame(2, $this->affectedRows($result));
+
+ $check = $this->execute(
+ select(agg_count(star())->as('cnt'))
+ ->from(table(self::TABLE_ARCHIVE))
+ ->toSql()
+ );
+ $row = $this->fetchOne($check);
+ self::assertSame('0', $row['cnt']);
+ }
+
+ public function test_delete_with_multiple_conditions() : void
+ {
+ $query = delete()
+ ->from(self::TABLE_LOGS)
+ ->where(
+ cond_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));
+ }
+
+ public function test_delete_with_returning() : void
+ {
+ $query = delete()
+ ->from(self::TABLE_LOGS)
+ ->where(eq(col('level'), literal('ERROR')))
+ ->returning(col('id'), col('level'), col('message'));
+
+ $result = $this->execute($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(
+ insert()
+ ->into(self::TABLE_LOGS)
+ ->columns('level', 'message')
+ ->values(literal('TRACE'), literal('Trace message'))
+ ->toSql()
+ );
+
+ $query = delete()
+ ->from(self::TABLE_LOGS)
+ ->where(eq(col('level'), literal('TRACE')))
+ ->returningAll();
+
+ $result = $this->execute($query->toSql());
+
+ self::assertNotFalse($result);
+ $row = $this->fetchOne($result);
+ self::assertArrayHasKey('id', $row);
+ self::assertArrayHasKey('level', $row);
+ self::assertArrayHasKey('message', $row);
+ self::assertArrayHasKey('created_at', $row);
+ }
+
+ public function test_delete_with_using() : void
+ {
+ $query = delete()
+ ->from(self::TABLE_LOGS)
+ ->using(table(self::TABLE_ARCHIVE))
+ ->where(
+ eq(
+ col('id', self::TABLE_LOGS),
+ col('log_id', self::TABLE_ARCHIVE)
+ )
+ );
+
+ $result = $this->execute($query->toSql());
+
+ self::assertNotFalse($result);
+ self::assertSame(2, $this->affectedRows($result));
+ }
+
+ public function test_delete_with_where() : void
+ {
+ $query = delete()
+ ->from(self::TABLE_LOGS)
+ ->where(eq(col('level'), literal('DEBUG')));
+
+ $result = $this->execute($query->toSql());
+
+ self::assertNotFalse($result);
+ self::assertSame(2, $this->affectedRows($result));
+
+ $check = $this->execute(
+ 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']);
+ }
+}
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
new file mode 100644
index 000000000..67e76ad5c
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/DomainDatabaseTest.php
@@ -0,0 +1,304 @@
+dropTableIfExists(self::TABLE_NAME);
+ $this->dropDomainIfExists(self::DOMAIN_NAME);
+ $this->dropDomainIfExists(self::DOMAIN_NAME_2);
+
+ parent::tearDown();
+ }
+
+ public function test_alter_domain_add_constraint() : void
+ {
+ $this->execute(
+ create()->domain(self::DOMAIN_NAME_2)
+ ->as(DataType::integer())
+ ->toSql()
+ );
+
+ $result = $this->execute(
+ alter()->domain(self::DOMAIN_NAME_2)
+ ->addConstraint('positive_check', 'VALUE > 0')
+ ->toSql()
+ );
+
+ self::assertNotFalse($result);
+ }
+
+ public function test_alter_domain_drop_constraint() : void
+ {
+ $this->execute(
+ create()->domain(self::DOMAIN_NAME_2)
+ ->as(DataType::integer())
+ ->constraint('positive_check')
+ ->check('VALUE > 0')
+ ->toSql()
+ );
+
+ $result = $this->execute(
+ alter()->domain(self::DOMAIN_NAME_2)
+ ->dropConstraint('positive_check')
+ ->toSql()
+ );
+
+ self::assertNotFalse($result);
+ }
+
+ public function test_alter_domain_drop_default() : void
+ {
+ $this->execute(
+ create()->domain(self::DOMAIN_NAME_2)
+ ->as(DataType::integer())
+ ->default('0')
+ ->toSql()
+ );
+
+ $result = $this->execute(
+ alter()->domain(self::DOMAIN_NAME_2)
+ ->dropDefault()
+ ->toSql()
+ );
+
+ self::assertNotFalse($result);
+ }
+
+ public function test_alter_domain_drop_not_null() : void
+ {
+ $this->execute(
+ create()->domain(self::DOMAIN_NAME_2)
+ ->as(DataType::integer())
+ ->notNull()
+ ->toSql()
+ );
+
+ $result = $this->execute(
+ alter()->domain(self::DOMAIN_NAME_2)
+ ->dropNotNull()
+ ->toSql()
+ );
+
+ self::assertNotFalse($result);
+ }
+
+ public function test_alter_domain_set_default() : void
+ {
+ $this->execute(
+ create()->domain(self::DOMAIN_NAME_2)
+ ->as(DataType::integer())
+ ->toSql()
+ );
+
+ $result = $this->execute(
+ alter()->domain(self::DOMAIN_NAME_2)
+ ->setDefault('100')
+ ->toSql()
+ );
+
+ self::assertNotFalse($result);
+ }
+
+ public function test_alter_domain_set_not_null() : void
+ {
+ $this->execute(
+ create()->domain(self::DOMAIN_NAME_2)
+ ->as(DataType::integer())
+ ->toSql()
+ );
+
+ $result = $this->execute(
+ alter()->domain(self::DOMAIN_NAME_2)
+ ->setNotNull()
+ ->toSql()
+ );
+
+ self::assertNotFalse($result);
+ }
+
+ public function test_create_domain() : void
+ {
+ $result = $this->execute(
+ create()->domain(self::DOMAIN_NAME)
+ ->as(DataType::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(
+ create()->domain(self::DOMAIN_NAME)
+ ->as(DataType::varchar(255))
+ ->constraint('valid_email')
+ ->check("VALUE ~ '^[^@]+@[^@]+\\.[^@]+$'")
+ ->toSql()
+ );
+
+ $this->execute(
+ create()->table(self::TABLE_NAME)
+ ->column(column('id', sql_type_serial()))
+ ->column(column('email', DataType::custom(self::DOMAIN_NAME))->notNull())
+ ->constraint(primary_key('id'))
+ ->toSql()
+ );
+
+ $this->execute(
+ insert()
+ ->into(self::TABLE_NAME)
+ ->columns('email')
+ ->values(literal('test@example.com'))
+ ->toSql()
+ );
+
+ $row = $this->fetchOne(
+ $this->execute(
+ select(star())->from(table(self::TABLE_NAME))->toSql()
+ )
+ );
+
+ self::assertSame('test@example.com', $row['email']);
+ }
+
+ public function test_create_domain_with_check_constraint() : void
+ {
+ $result = $this->execute(
+ create()->domain(self::DOMAIN_NAME)
+ ->as(DataType::varchar(255))
+ ->constraint('valid_email')
+ ->check("VALUE ~ '^[^@]+@[^@]+\\.[^@]+$'")
+ ->toSql()
+ );
+
+ self::assertNotFalse($result);
+ self::assertTrue($this->domainExists(self::DOMAIN_NAME));
+ }
+
+ public function test_create_domain_with_default() : void
+ {
+ $result = $this->execute(
+ create()->domain(self::DOMAIN_NAME_2)
+ ->as(DataType::integer())
+ ->default('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(
+ create()->domain(self::DOMAIN_NAME)
+ ->as(DataType::varchar(255))
+ ->notNull()
+ ->toSql()
+ );
+
+ self::assertNotFalse($result);
+ self::assertTrue($this->domainExists(self::DOMAIN_NAME));
+ }
+
+ public function test_drop_domain() : void
+ {
+ $this->execute(
+ create()->domain(self::DOMAIN_NAME)
+ ->as(DataType::varchar(255))
+ ->toSql()
+ );
+
+ self::assertTrue($this->domainExists(self::DOMAIN_NAME));
+
+ $result = $this->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(
+ create()->domain(self::DOMAIN_NAME)
+ ->as(DataType::varchar(255))
+ ->toSql()
+ );
+
+ $this->execute(
+ create()->table(self::TABLE_NAME)
+ ->column(column('id', sql_type_serial()))
+ ->column(column('email', DataType::custom(self::DOMAIN_NAME)))
+ ->constraint(primary_key('id'))
+ ->toSql()
+ );
+
+ $result = $this->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(
+ drop()->domain(self::DOMAIN_NAME)->ifExists()->toSql()
+ );
+
+ self::assertNotFalse($result);
+ }
+
+ protected function domainExists(string $name) : bool
+ {
+ $row = $this->fetchOne(
+ $this->execute(
+ "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");
+ }
+}
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
new file mode 100644
index 000000000..e5620ba96
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/FunctionDatabaseTest.php
@@ -0,0 +1,281 @@
+dropFunctionIfExists(self::FUNCTION_NAME);
+ $this->dropFunctionIfExists(self::FUNCTION_NAME_2);
+ $this->dropFunctionIfExists(self::FUNCTION_NAME_RENAMED);
+
+ parent::tearDown();
+ }
+
+ public function test_alter_function_rename() : void
+ {
+ $this->execute(
+ create()->function(self::FUNCTION_NAME)
+ ->arguments()
+ ->returns(sql_type_integer())
+ ->language('sql')
+ ->as('SELECT 42')
+ ->toSql()
+ );
+
+ $result = $this->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(
+ create()->function(self::FUNCTION_NAME)
+ ->arguments()
+ ->returns(sql_type_integer())
+ ->language('sql')
+ ->as('SELECT 42')
+ ->toSql()
+ );
+
+ $result = $this->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(
+ create()->function(self::FUNCTION_NAME)
+ ->arguments()
+ ->returnsVoid()
+ ->language('sql')
+ ->as('SELECT 1')
+ ->toSql()
+ );
+
+ self::assertNotFalse($result);
+ self::assertTrue($this->functionExists(self::FUNCTION_NAME));
+ }
+
+ public function test_create_function_with_arguments() : void
+ {
+ $result = $this->execute(
+ create()->function(self::FUNCTION_NAME)
+ ->arguments(
+ func_arg(sql_type_integer())->named('a'),
+ func_arg(sql_type_integer())->named('b')
+ )
+ ->returns(sql_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']);
+ }
+
+ public function test_create_function_with_default_argument() : void
+ {
+ $result = $this->execute(
+ create()->function(self::FUNCTION_NAME)
+ ->arguments(
+ func_arg(sql_type_integer())->named('a'),
+ func_arg(sql_type_integer())->named('b')->default('10')
+ )
+ ->returns(sql_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->fetchOne($this->execute('SELECT ' . self::FUNCTION_NAME . '(5, 3) AS result'));
+ self::assertSame('8', $row['result']);
+ }
+
+ public function test_create_function_with_parallel_safety() : void
+ {
+ $result = $this->execute(
+ create()->function(self::FUNCTION_NAME)
+ ->arguments()
+ ->returns(sql_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(
+ create()->function(self::FUNCTION_NAME)
+ ->arguments()
+ ->returns(sql_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(
+ create()->function(self::FUNCTION_NAME)
+ ->arguments()
+ ->returns(sql_type_integer())
+ ->language('sql')
+ ->as('SELECT 1')
+ ->toSql()
+ );
+
+ $row = $this->fetchOne($this->execute('SELECT ' . self::FUNCTION_NAME . '() AS result'));
+ self::assertSame('1', $row['result']);
+
+ $result = $this->execute(
+ create()->function(self::FUNCTION_NAME)
+ ->orReplace()
+ ->arguments()
+ ->returns(sql_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']);
+ }
+
+ public function test_create_simple_function() : void
+ {
+ $result = $this->execute(
+ create()->function(self::FUNCTION_NAME)
+ ->arguments()
+ ->returns(sql_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']);
+ }
+
+ public function test_drop_function() : void
+ {
+ $this->execute(
+ create()->function(self::FUNCTION_NAME)
+ ->arguments()
+ ->returns(sql_type_integer())
+ ->language('sql')
+ ->as('SELECT 42')
+ ->toSql()
+ );
+
+ self::assertTrue($this->functionExists(self::FUNCTION_NAME));
+
+ $result = $this->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(
+ drop()->function(self::FUNCTION_NAME)->ifExists()->toSql()
+ );
+
+ self::assertNotFalse($result);
+ }
+
+ public function test_drop_function_with_arguments() : void
+ {
+ $this->execute(
+ create()->function(self::FUNCTION_NAME)
+ ->arguments(func_arg(sql_type_integer())->named('a'))
+ ->returns(sql_type_integer())
+ ->language('sql')
+ ->as('SELECT a * 2')
+ ->toSql()
+ );
+
+ $result = $this->execute(
+ drop()->function(self::FUNCTION_NAME)
+ ->arguments(func_arg(sql_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")
+ );
+
+ return $row['func_exists'] === 't';
+ }
+}
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
new file mode 100644
index 000000000..cd665f40b
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/IndexDatabaseTest.php
@@ -0,0 +1,181 @@
+table(self::TABLE_INDEXED)
+ ->column(column('id', sql_type_serial()))
+ ->column(column('name', sql_type_varchar(100)))
+ ->column(column('email', sql_type_varchar(255)))
+ ->column(column('age', sql_type_integer()));
+
+ $this->execute($query->toSql());
+
+ $this->execute(
+ insert()
+ ->into(self::TABLE_INDEXED)
+ ->columns('name', 'email', 'age')
+ ->values(literal('Test'), literal('test@example.com'), literal(30))
+ ->toSql()
+ );
+ }
+
+ protected function tearDown() : void
+ {
+ $this->dropIndexIfExists(self::INDEX_NAME);
+ $this->dropIndexIfExists(self::INDEX_EMAIL);
+ $this->dropIndexIfExists(self::INDEX_COMPOSITE);
+ $this->dropTableIfExists(self::TABLE_INDEXED);
+
+ parent::tearDown();
+ }
+
+ public function test_create_composite_index() : void
+ {
+ $query = create()->index(self::INDEX_COMPOSITE)
+ ->on(self::TABLE_INDEXED)
+ ->columns(index_col('name'), index_col('email'));
+
+ $result = $this->execute($query->toSql());
+
+ self::assertNotFalse($result);
+ }
+
+ public function test_create_index() : void
+ {
+ $query = create()->index(self::INDEX_NAME)
+ ->on(self::TABLE_INDEXED)
+ ->columns(index_col('name'));
+
+ $result = $this->execute($query->toSql());
+
+ self::assertNotFalse($result);
+
+ $check = $this->execute(
+ select(agg_count(star())->as('cnt'))
+ ->from(table('pg_indexes'))
+ ->where(
+ eq(col('tablename'), literal(self::TABLE_INDEXED))
+ )
+ ->toSql()
+ );
+ $row = $this->fetchOne($check);
+ self::assertGreaterThanOrEqual(1, (int) $row['cnt']);
+ }
+
+ public function test_create_index_if_not_exists() : void
+ {
+ $query = create()->index(self::INDEX_NAME)
+ ->ifNotExists()
+ ->on(self::TABLE_INDEXED)
+ ->columns(index_col('name'));
+
+ $this->execute($query->toSql());
+ $result = $this->execute($query->toSql());
+
+ self::assertNotFalse($result);
+ }
+
+ public function test_create_index_with_btree_method() : void
+ {
+ $query = create()->index(self::INDEX_NAME)
+ ->on(self::TABLE_INDEXED)
+ ->using(index_method_btree())
+ ->columns(index_col('name'));
+
+ $result = $this->execute($query->toSql());
+
+ self::assertNotFalse($result);
+ }
+
+ public function test_create_index_with_hash_method() : void
+ {
+ $query = create()->index(self::INDEX_NAME)
+ ->on(self::TABLE_INDEXED)
+ ->using(index_method_hash())
+ ->columns(index_col('name'));
+
+ $result = $this->execute($query->toSql());
+
+ self::assertNotFalse($result);
+ }
+
+ public function test_create_unique_index() : void
+ {
+ $query = create()->index(self::INDEX_EMAIL)
+ ->unique()
+ ->on(self::TABLE_INDEXED)
+ ->columns(index_col('email'));
+
+ $result = $this->execute($query->toSql());
+
+ self::assertNotFalse($result);
+
+ $duplicateResult = @$this->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
+ {
+ $createQuery = create()->index(self::INDEX_NAME)
+ ->on(self::TABLE_INDEXED)
+ ->columns(index_col('name'));
+ $this->execute($createQuery->toSql());
+
+ $dropQuery = drop()->index(self::INDEX_NAME);
+
+ $result = $this->execute($dropQuery->toSql());
+
+ self::assertNotFalse($result);
+ }
+
+ public function test_drop_index_if_exists() : void
+ {
+ $dropQuery = drop()->index(self::INDEX_NAME)->ifExists();
+
+ $result = $this->execute($dropQuery->toSql());
+
+ self::assertNotFalse($result);
+ }
+}
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
new file mode 100644
index 000000000..0e6f8cc55
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/InsertDatabaseTest.php
@@ -0,0 +1,192 @@
+execute(
+ create()->table(self::TABLE_PRODUCTS)
+ ->column(column('id', sql_type_serial()))
+ ->column(column('sku', sql_type_varchar(50))->notNull())
+ ->column(column('name', sql_type_varchar(100))->notNull())
+ ->column(column('price', sql_type_decimal(10, 2))->default(0))
+ ->column(column('stock', sql_type_integer())->default(0))
+ ->constraint(primary_key('id'))
+ ->constraint(unique_constraint('sku'))
+ ->toSql()
+ );
+ }
+
+ protected function tearDown() : void
+ {
+ $this->dropTableIfExists(self::TABLE_PRODUCTS);
+
+ parent::tearDown();
+ }
+
+ public function test_basic_insert() : void
+ {
+ $query = insert()
+ ->into(self::TABLE_PRODUCTS)
+ ->columns('sku', 'name', 'price')
+ ->values(literal('SKU001'), literal('Product A'), literal(100));
+
+ $result = $this->execute($query->toSql());
+
+ self::assertNotFalse($result);
+ self::assertSame(1, $this->affectedRows($result));
+
+ $check = $this->execute(
+ 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']);
+ }
+
+ public function test_insert_multiple_rows() : void
+ {
+ $query = insert()
+ ->into(self::TABLE_PRODUCTS)
+ ->columns('sku', 'name', 'price')
+ ->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));
+ }
+
+ public function test_insert_on_conflict_do_nothing() : void
+ {
+ $this->execute(
+ insert()
+ ->into(self::TABLE_PRODUCTS)
+ ->columns('sku', 'name')
+ ->values(literal('SKU006'), literal('Original'))
+ ->toSql()
+ );
+
+ $query = insert()
+ ->into(self::TABLE_PRODUCTS)
+ ->columns('sku', 'name')
+ ->values(literal('SKU006'), literal('Duplicate'))
+ ->onConflict(on_conflict_nothing(conflict_columns(['sku'])));
+
+ $result = $this->execute($query->toSql());
+
+ self::assertNotFalse($result);
+
+ $check = $this->execute(
+ 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(
+ insert()
+ ->into(self::TABLE_PRODUCTS)
+ ->columns('sku', 'name', 'price')
+ ->values(literal('SKU007'), literal('Original'), literal(100))
+ ->toSql()
+ );
+
+ $query = insert()
+ ->into(self::TABLE_PRODUCTS)
+ ->columns('sku', 'name', 'price')
+ ->values(literal('SKU007'), literal('Updated'), literal(999))
+ ->onConflict(
+ on_conflict_update(
+ conflict_columns(['sku']),
+ ['name' => literal('Updated'), 'price' => literal(999)]
+ )
+ );
+
+ $result = $this->execute($query->toSql());
+
+ self::assertNotFalse($result);
+
+ $check = $this->execute(
+ 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']);
+ }
+
+ public function test_insert_with_returning() : void
+ {
+ $query = insert()
+ ->into(self::TABLE_PRODUCTS)
+ ->columns('sku', 'name', 'price')
+ ->values(literal('SKU004'), literal('Product D'), literal(400))
+ ->returning(col('id'), col('sku'));
+
+ $result = $this->execute($query->toSql());
+
+ self::assertNotFalse($result);
+ $row = $this->fetchOne($result);
+ self::assertArrayHasKey('id', $row);
+ self::assertArrayHasKey('sku', $row);
+ self::assertSame('SKU004', $row['sku']);
+ }
+
+ public function test_insert_with_returning_all() : void
+ {
+ $query = insert()
+ ->into(self::TABLE_PRODUCTS)
+ ->columns('sku', 'name', 'price')
+ ->values(literal('SKU005'), literal('Product E'), literal(500))
+ ->returningAll();
+
+ $result = $this->execute($query->toSql());
+
+ self::assertNotFalse($result);
+ $row = $this->fetchOne($result);
+ self::assertArrayHasKey('id', $row);
+ self::assertArrayHasKey('sku', $row);
+ self::assertArrayHasKey('name', $row);
+ self::assertArrayHasKey('price', $row);
+ self::assertArrayHasKey('stock', $row);
+ }
+}
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
new file mode 100644
index 000000000..0808aea5b
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/MergeDatabaseTest.php
@@ -0,0 +1,275 @@
+execute(
+ create()->table(self::TABLE_TARGET)
+ ->column(column('id', sql_type_serial()))
+ ->column(column('name', sql_type_varchar(100))->notNull())
+ ->column(column('value', sql_type_integer())->default(0))
+ ->constraint(primary_key('id'))
+ ->toSql()
+ );
+
+ $this->execute(
+ create()->table(self::TABLE_SOURCE)
+ ->column(column('id', sql_type_integer())->notNull())
+ ->column(column('name', sql_type_varchar(100))->notNull())
+ ->column(column('value', sql_type_integer())->default(0))
+ ->constraint(primary_key('id'))
+ ->toSql()
+ );
+
+ $this->execute(
+ insert()
+ ->into(self::TABLE_TARGET)
+ ->columns('name', 'value')
+ ->values(literal('Alice'), literal(100))
+ ->values(literal('Bob'), literal(200))
+ ->toSql()
+ );
+
+ $this->execute(
+ insert()
+ ->into(self::TABLE_SOURCE)
+ ->columns('id', 'name', 'value')
+ ->values(literal(1), literal('Alice Updated'), literal(150))
+ ->values(literal(2), literal('Bob Updated'), literal(250))
+ ->values(literal(3), literal('Charlie'), literal(300))
+ ->toSql()
+ );
+ }
+
+ protected function tearDown() : void
+ {
+ $this->dropTableIfExists(self::TABLE_SOURCE);
+ $this->dropTableIfExists(self::TABLE_TARGET);
+
+ parent::tearDown();
+ }
+
+ public function test_merge_delete_matched() : void
+ {
+ $query = merge(self::TABLE_TARGET, 't')
+ ->using(self::TABLE_SOURCE, 's')
+ ->on(eq(col('t.id'), col('s.id')))
+ ->whenMatched()
+ ->thenDelete();
+
+ $result = $this->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()
+ )
+ );
+
+ self::assertCount(0, $rows);
+ }
+
+ public function test_merge_do_nothing() : void
+ {
+ $query = merge(self::TABLE_TARGET, 't')
+ ->using(self::TABLE_SOURCE, 's')
+ ->on(eq(col('t.id'), col('s.id')))
+ ->whenMatched()
+ ->thenDoNothing();
+
+ $result = $this->execute($query->toSql());
+
+ self::assertNotFalse($result);
+
+ $rows = $this->fetchAll(
+ $this->execute(
+ select(star())->from(table(self::TABLE_TARGET))->orderBy(order_by(col('id')))->toSql()
+ )
+ );
+
+ self::assertCount(2, $rows);
+ self::assertSame('Alice', $rows[0]['name']);
+ self::assertSame('Bob', $rows[1]['name']);
+ }
+
+ public function test_merge_insert_not_matched() : void
+ {
+ $query = merge(self::TABLE_TARGET, 't')
+ ->using(self::TABLE_SOURCE, 's')
+ ->on(eq(col('t.id'), col('s.id')))
+ ->whenNotMatched()
+ ->thenInsertValues([
+ 'name' => col('s.name'),
+ 'value' => col('s.value'),
+ ]);
+
+ $result = $this->execute($query->toSql());
+
+ self::assertNotFalse($result);
+ self::assertSame(1, $this->affectedRows($result));
+
+ $rows = $this->fetchAll(
+ $this->execute(
+ 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']);
+ }
+
+ public function test_merge_update_and_insert() : void
+ {
+ $query = merge(self::TABLE_TARGET, 't')
+ ->using(self::TABLE_SOURCE, 's')
+ ->on(eq(col('t.id'), col('s.id')))
+ ->whenMatched()
+ ->thenUpdate([
+ 'name' => col('s.name'),
+ 'value' => col('s.value'),
+ ])
+ ->whenNotMatched()
+ ->thenInsertValues([
+ 'name' => col('s.name'),
+ 'value' => col('s.value'),
+ ]);
+
+ $result = $this->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()
+ )
+ );
+
+ self::assertCount(3, $rows);
+ self::assertSame('Alice Updated', $rows[0]['name']);
+ self::assertSame('Bob Updated', $rows[1]['name']);
+ self::assertSame('Charlie', $rows[2]['name']);
+ }
+
+ public function test_merge_update_matched() : void
+ {
+ $query = merge(self::TABLE_TARGET, 't')
+ ->using(self::TABLE_SOURCE, 's')
+ ->on(eq(col('t.id'), col('s.id')))
+ ->whenMatched()
+ ->thenUpdate([
+ 'name' => col('s.name'),
+ 'value' => col('s.value'),
+ ]);
+
+ $result = $this->execute($query->toSql());
+
+ self::assertNotFalse($result);
+ self::assertSame(2, $this->affectedRows($result));
+
+ $rows = $this->fetchAll(
+ $this->execute(
+ 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('Bob Updated', $rows[1]['name']);
+ self::assertSame('250', $rows[1]['value']);
+ }
+
+ public function test_merge_using_subquery() : void
+ {
+ $sourceQuery = select(col('id'), col('name'), col('value'))
+ ->from(table(self::TABLE_SOURCE))
+ ->where(gt(col('value'), literal(200)));
+
+ $query = merge(self::TABLE_TARGET, 't')
+ ->using($sourceQuery, 's')
+ ->on(eq(col('t.id'), col('s.id')))
+ ->whenMatched()
+ ->thenUpdate([
+ 'value' => col('s.value'),
+ ])
+ ->whenNotMatched()
+ ->thenInsertValues([
+ 'name' => col('s.name'),
+ 'value' => col('s.value'),
+ ]);
+
+ $result = $this->execute($query->toSql());
+
+ self::assertNotFalse($result);
+
+ $rows = $this->fetchAll(
+ $this->execute(
+ 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('Charlie', $rows[2]['name']);
+ }
+
+ public function test_merge_with_condition() : void
+ {
+ $query = merge(self::TABLE_TARGET, 't')
+ ->using(self::TABLE_SOURCE, 's')
+ ->on(eq(col('t.id'), col('s.id')))
+ ->whenMatchedAnd(gt(col('s.value'), literal(200)))
+ ->thenUpdate([
+ 'value' => col('s.value'),
+ ]);
+
+ $result = $this->execute($query->toSql());
+
+ self::assertNotFalse($result);
+ self::assertSame(1, $this->affectedRows($result));
+
+ $rows = $this->fetchAll(
+ $this->execute(
+ 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']);
+ }
+}
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
new file mode 100644
index 000000000..a69c71509
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/SchemaDatabaseTest.php
@@ -0,0 +1,229 @@
+dropSchemaIfExists(self::SCHEMA_NAME);
+ $this->dropSchemaIfExists(self::SCHEMA_NAME_RENAMED);
+ }
+
+ protected function tearDown() : void
+ {
+ $this->dropSchemaIfExists(self::SCHEMA_NAME);
+ $this->dropSchemaIfExists(self::SCHEMA_NAME_RENAMED);
+
+ parent::tearDown();
+ }
+
+ public function test_alter_schema_owner() : void
+ {
+ $this->execute(
+ create()->schema(self::SCHEMA_NAME)->toSql()
+ );
+
+ $currentUser = $this->fetchOne($this->execute('SELECT current_user AS username'));
+ self::assertIsString($currentUser['username']);
+
+ $result = $this->execute(
+ alter()->schema(self::SCHEMA_NAME)
+ ->ownerTo($currentUser['username'])
+ ->toSql()
+ );
+
+ self::assertNotFalse($result);
+ }
+
+ public function test_alter_schema_rename() : void
+ {
+ $this->execute(
+ create()->schema(self::SCHEMA_NAME)->toSql()
+ );
+
+ $result = $this->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(
+ 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(
+ create()->schema(self::SCHEMA_NAME)->toSql()
+ );
+
+ $result = $this->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'));
+ self::assertIsString($currentUser['username']);
+
+ $result = $this->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(
+ create()->schema(self::SCHEMA_NAME)->toSql()
+ );
+
+ $result = $this->execute(
+ create()->table(self::TABLE_NAME, self::SCHEMA_NAME)
+ ->column(column('id', sql_type_serial()))
+ ->column(column('name', sql_type_varchar(100))->notNull())
+ ->constraint(primary_key('id'))
+ ->toSql()
+ );
+
+ self::assertNotFalse($result);
+
+ $this->execute(
+ insert()
+ ->into(self::SCHEMA_NAME . '.' . self::TABLE_NAME)
+ ->columns('name')
+ ->values(literal('Test'))
+ ->toSql()
+ );
+
+ $row = $this->fetchOne(
+ $this->execute(
+ select(star())->from(table(self::TABLE_NAME, self::SCHEMA_NAME))->toSql()
+ )
+ );
+
+ self::assertSame('Test', $row['name']);
+ }
+
+ public function test_drop_multiple_schemas() : void
+ {
+ $this->execute(create()->schema(self::SCHEMA_NAME)->toSql());
+ $this->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(
+ 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(
+ create()->schema(self::SCHEMA_NAME)->toSql()
+ );
+
+ self::assertTrue($this->schemaExists(self::SCHEMA_NAME));
+
+ $result = $this->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(
+ create()->schema(self::SCHEMA_NAME)->toSql()
+ );
+
+ $this->execute(
+ create()->table(self::TABLE_NAME, self::SCHEMA_NAME)
+ ->column(column('id', sql_type_serial()))
+ ->constraint(primary_key('id'))
+ ->toSql()
+ );
+
+ $result = $this->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(
+ 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")
+ );
+
+ return $row['schema_exists'] === 't';
+ }
+}
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
new file mode 100644
index 000000000..a1f37f0fa
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/SelectDatabaseTest.php
@@ -0,0 +1,224 @@
+execute(
+ create()->table(self::TABLE_USERS)
+ ->column(column('id', sql_type_serial()))
+ ->column(column('name', sql_type_varchar(100))->notNull())
+ ->column(column('email', sql_type_varchar(255)))
+ ->column(column('age', sql_type_integer())->default(0))
+ ->constraint(primary_key('id'))
+ ->toSql()
+ );
+
+ $this->execute(
+ create()->table(self::TABLE_ORDERS)
+ ->column(column('id', sql_type_serial()))
+ ->column(column('user_id', sql_type_integer()))
+ ->column(column('amount', sql_type_decimal(10, 2))->notNull())
+ ->column(column('status', sql_type_varchar(50))->default('pending'))
+ ->constraint(primary_key('id'))
+ ->toSql()
+ );
+
+ $this->execute(
+ insert()
+ ->into(self::TABLE_USERS)
+ ->columns('name', 'email', 'age')
+ ->values(literal('John Doe'), literal('john@example.com'), literal(30))
+ ->values(literal('Jane Smith'), literal('jane@example.com'), literal(25))
+ ->values(literal('Bob Wilson'), literal('bob@example.com'), literal(35))
+ ->toSql()
+ );
+
+ $this->execute(
+ insert()
+ ->into(self::TABLE_ORDERS)
+ ->columns('user_id', 'amount', 'status')
+ ->values(literal(1), literal(100), literal('completed'))
+ ->values(literal(1), literal(200), literal('pending'))
+ ->values(literal(2), literal(150), literal('completed'))
+ ->values(literal(3), literal(300), literal('completed'))
+ ->toSql()
+ );
+ }
+
+ protected function tearDown() : void
+ {
+ $this->dropTableIfExists(self::TABLE_ORDERS);
+ $this->dropTableIfExists(self::TABLE_USERS);
+
+ parent::tearDown();
+ }
+
+ public function test_basic_select_all() : void
+ {
+ $query = select(star())->from(table(self::TABLE_USERS));
+
+ $result = $this->execute($query->toSql());
+
+ self::assertNotFalse($result);
+ $rows = $this->fetchAll($result);
+ self::assertCount(3, $rows);
+ }
+
+ public function test_select_distinct() : void
+ {
+ $query = select()
+ ->selectDistinct(col('status'))
+ ->from(table(self::TABLE_ORDERS));
+
+ $result = $this->execute($query->toSql());
+
+ self::assertNotFalse($result);
+ $rows = $this->fetchAll($result);
+ self::assertCount(2, $rows);
+ }
+
+ public function test_select_specific_columns() : void
+ {
+ $query = select(col('name'), col('email'))
+ ->from(table(self::TABLE_USERS));
+
+ $result = $this->execute($query->toSql());
+
+ self::assertNotFalse($result);
+ $rows = $this->fetchAll($result);
+ self::assertCount(3, $rows);
+ self::assertArrayHasKey('name', $rows[0]);
+ self::assertArrayHasKey('email', $rows[0]);
+ self::assertArrayNotHasKey('id', $rows[0]);
+ }
+
+ public function test_select_with_cte() : void
+ {
+ $cteQuery = select(col('user_id'), agg_sum(col('amount'))->as('total'))
+ ->from(table(self::TABLE_ORDERS))
+ ->groupBy(col('user_id'));
+
+ /** @phpstan-ignore method.notFound (WithBuilder::select return type issue - same as existing SelectBuilderTest) */
+ $query = with(cte('order_totals', $cteQuery))
+ ->select(star())
+ ->from(table('order_totals'))
+ ->where(gt(col('total'), literal(200)));
+
+ $result = $this->execute($query->toSql());
+
+ self::assertNotFalse($result);
+ $rows = $this->fetchAll($result);
+ self::assertGreaterThanOrEqual(1, \count($rows));
+ }
+
+ public function test_select_with_group_by_and_aggregate() : void
+ {
+ $query = select(col('user_id'), agg_sum(col('amount'))->as('total'))
+ ->from(table(self::TABLE_ORDERS))
+ ->groupBy(col('user_id'));
+
+ $result = $this->execute($query->toSql());
+
+ self::assertNotFalse($result);
+ $rows = $this->fetchAll($result);
+ self::assertCount(3, $rows);
+ }
+
+ public function test_select_with_join() : void
+ {
+ $query = select(col('name', self::TABLE_USERS), col('amount', self::TABLE_ORDERS))
+ ->from(table(self::TABLE_USERS))
+ ->join(
+ table(self::TABLE_ORDERS),
+ eq(col('id', self::TABLE_USERS), col('user_id', self::TABLE_ORDERS))
+ );
+
+ $result = $this->execute($query->toSql());
+
+ self::assertNotFalse($result);
+ $rows = $this->fetchAll($result);
+ self::assertCount(4, $rows);
+ }
+
+ public function test_select_with_multiple_conditions() : void
+ {
+ $query = select(star())
+ ->from(table(self::TABLE_USERS))
+ ->where(
+ cond_and(
+ gt(col('age'), literal(20)),
+ gt(col('age'), literal(25))
+ )
+ );
+
+ $result = $this->execute($query->toSql());
+
+ self::assertNotFalse($result);
+ $rows = $this->fetchAll($result);
+ self::assertCount(2, $rows);
+ }
+
+ public function test_select_with_order_by_and_limit() : void
+ {
+ $query = select(star())
+ ->from(table(self::TABLE_USERS))
+ ->orderBy(desc(col('age')))
+ ->limit(2);
+
+ $result = $this->execute($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']);
+ }
+
+ public function test_select_with_where() : void
+ {
+ $query = select(star())
+ ->from(table(self::TABLE_USERS))
+ ->where(eq(col('name'), literal('John Doe')));
+
+ $result = $this->execute($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
new file mode 100644
index 000000000..8da77bc51
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/SequenceDatabaseTest.php
@@ -0,0 +1,206 @@
+dropSequenceIfExists(self::SEQUENCE_TEST);
+ $this->dropSequenceIfExists(self::SEQUENCE_COUNTER);
+
+ parent::tearDown();
+ }
+
+ public function test_alter_sequence_increment() : void
+ {
+ $createQuery = create()->sequence(self::SEQUENCE_TEST)->startWith(1);
+ $this->execute($createQuery->toSql());
+
+ $alterQuery = alter()->sequence(self::SEQUENCE_TEST)
+ ->incrementBy(10);
+
+ $result = $this->execute($alterQuery->toSql());
+
+ self::assertNotFalse($result);
+
+ $this->execute(
+ select(func('nextval', [literal(self::SEQUENCE_TEST)]))->toSql()
+ );
+ $secondVal = $this->execute(
+ select(func('nextval', [literal(self::SEQUENCE_TEST)])->as('val'))->toSql()
+ );
+ $row = $this->fetchOne($secondVal);
+ 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->execute(
+ select(func('nextval', [literal(self::SEQUENCE_TEST)]))->toSql()
+ );
+ $this->execute(
+ select(func('nextval', [literal(self::SEQUENCE_TEST)]))->toSql()
+ );
+
+ $alterQuery = alter()->sequence(self::SEQUENCE_TEST)
+ ->restartWith(1);
+
+ $result = $this->execute($alterQuery->toSql());
+
+ self::assertNotFalse($result);
+
+ $nextVal = $this->execute(
+ select(func('nextval', [literal(self::SEQUENCE_TEST)])->as('val'))->toSql()
+ );
+ $row = $this->fetchOne($nextVal);
+ 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);
+
+ $check = $this->execute(
+ select(col('sequencename'))
+ ->from(table('pg_sequences'))
+ ->where(eq(col('sequencename'), literal(self::SEQUENCE_TEST)))
+ ->toSql()
+ );
+ $sequences = $this->fetchAll($check);
+ self::assertCount(1, $sequences);
+ }
+
+ public function test_create_sequence_with_increment() : void
+ {
+ $query = create()->sequence(self::SEQUENCE_TEST)
+ ->incrementBy(5)
+ ->startWith(10);
+
+ $result = $this->execute($query->toSql());
+
+ self::assertNotFalse($result);
+
+ $this->execute(
+ select(func('nextval', [literal(self::SEQUENCE_TEST)]))->toSql()
+ );
+ $secondVal = $this->execute(
+ select(func('nextval', [literal(self::SEQUENCE_TEST)])->as('val'))->toSql()
+ );
+ $row = $this->fetchOne($secondVal);
+ self::assertSame('15', $row['val']);
+ }
+
+ public function test_create_sequence_with_min_max() : void
+ {
+ $query = create()->sequence(self::SEQUENCE_TEST)
+ ->minValue(1)
+ ->maxValue(1000)
+ ->startWith(1);
+
+ $result = $this->execute($query->toSql());
+
+ self::assertNotFalse($result);
+
+ $check = $this->execute(
+ 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']);
+ }
+
+ 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);
+
+ $nextVal = $this->execute(
+ select(func('nextval', [literal(self::SEQUENCE_TEST)])->as('val'))->toSql()
+ );
+ $row = $this->fetchOne($nextVal);
+ self::assertSame('100', $row['val']);
+ }
+
+ public function test_drop_sequence() : void
+ {
+ $createQuery = create()->sequence(self::SEQUENCE_TEST);
+ $this->execute($createQuery->toSql());
+
+ $dropQuery = drop()->sequence(self::SEQUENCE_TEST);
+
+ $result = $this->execute($dropQuery->toSql());
+
+ self::assertNotFalse($result);
+
+ $check = $this->execute(
+ 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();
+
+ $result = $this->execute($dropQuery->toSql());
+
+ self::assertNotFalse($result);
+ }
+
+ public function test_sequence_usage_with_nextval() : void
+ {
+ $createQuery = create()->sequence(self::SEQUENCE_COUNTER)->startWith(1);
+ $this->execute($createQuery->toSql());
+
+ $val1 = $this->fetchOne($this->execute(
+ select(func('nextval', [literal(self::SEQUENCE_COUNTER)])->as('val'))->toSql()
+ ));
+ $val2 = $this->fetchOne($this->execute(
+ select(func('nextval', [literal(self::SEQUENCE_COUNTER)])->as('val'))->toSql()
+ ));
+ $val3 = $this->fetchOne($this->execute(
+ 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']);
+ }
+}
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
new file mode 100644
index 000000000..d01daedba
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/TableDatabaseTest.php
@@ -0,0 +1,234 @@
+dropTableIfExists(self::TABLE_CHILD);
+ $this->dropTableIfExists(self::TABLE_TEST);
+ $this->dropTableIfExists(self::TABLE_PARENT);
+
+ parent::tearDown();
+ }
+
+ public function test_alter_table_add_column() : void
+ {
+ $createQuery = create()->table(self::TABLE_TEST)
+ ->column(column('id', sql_type_serial()))
+ ->column(column('name', sql_type_varchar(100)));
+ $this->execute($createQuery->toSql());
+
+ $alterQuery = alter()->table(self::TABLE_TEST)
+ ->addColumn(column('email', sql_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);
+ self::assertCount(1, $columns);
+ }
+
+ public function test_alter_table_drop_column() : void
+ {
+ $createQuery = create()->table(self::TABLE_TEST)
+ ->column(column('id', sql_type_serial()))
+ ->column(column('name', sql_type_varchar(100)))
+ ->column(column('to_drop', sql_type_text()));
+ $this->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);
+ self::assertCount(0, $columns);
+ }
+
+ public function test_create_table_with_check_constraint() : void
+ {
+ $query = create()->table(self::TABLE_TEST)
+ ->column(column('id', sql_type_serial()))
+ ->column(column('age', sql_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);
+ self::assertGreaterThanOrEqual(1, \count($constraints));
+
+ $hasAgeConstraint = false;
+
+ foreach ($constraints as $constraint) {
+ if ($constraint['def'] !== null && \str_contains($constraint['def'], 'age')) {
+ $hasAgeConstraint = true;
+
+ break;
+ }
+ }
+ self::assertTrue($hasAgeConstraint, 'Should have a CHECK constraint on age column');
+ }
+
+ public function test_create_table_with_columns() : void
+ {
+ $query = create()->table(self::TABLE_TEST)
+ ->column(column('id', sql_type_serial()))
+ ->column(column('name', sql_type_varchar(100))->notNull())
+ ->column(column('description', sql_type_text()));
+
+ $result = $this->execute($query->toSql());
+
+ self::assertNotFalse($result);
+
+ $check = $this->execute("SELECT column_name FROM information_schema.columns WHERE table_name = '" . self::TABLE_TEST . "' ORDER BY ordinal_position");
+ $columns = $this->fetchAll($check);
+
+ self::assertCount(3, $columns);
+ self::assertSame('id', $columns[0]['column_name']);
+ self::assertSame('name', $columns[1]['column_name']);
+ self::assertSame('description', $columns[2]['column_name']);
+ }
+
+ public function test_create_table_with_foreign_key() : void
+ {
+ $parentQuery = create()->table(self::TABLE_PARENT)
+ ->column(column('id', sql_type_serial()))
+ ->column(column('name', sql_type_varchar(100)))
+ ->constraint(primary_key('id'));
+ $this->execute($parentQuery->toSql());
+
+ $childQuery = create()->table(self::TABLE_CHILD)
+ ->column(column('id', sql_type_serial()))
+ ->column(column('parent_id', sql_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);
+ self::assertCount(1, $constraints);
+ self::assertSame(self::TABLE_PARENT, $constraints[0]['foreign_table_name']);
+ }
+
+ public function test_create_table_with_primary_key() : void
+ {
+ $query = create()->table(self::TABLE_TEST)
+ ->column(column('id', sql_type_integer())->notNull())
+ ->column(column('name', sql_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);
+ self::assertCount(1, $constraints);
+ }
+
+ public function test_create_table_with_unique_constraint() : void
+ {
+ $query = create()->table(self::TABLE_TEST)
+ ->column(column('id', sql_type_serial()))
+ ->column(column('email', sql_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);
+ self::assertCount(1, $constraints);
+ }
+
+ public function test_drop_table() : void
+ {
+ $createQuery = create()->table(self::TABLE_TEST)
+ ->column(column('id', sql_type_serial()));
+ $this->execute($createQuery->toSql());
+
+ $dropQuery = drop()->table(self::TABLE_TEST);
+
+ $result = $this->execute($dropQuery->toSql());
+
+ self::assertNotFalse($result);
+
+ $check = $this->execute("SELECT table_name FROM information_schema.tables WHERE table_name = '" . self::TABLE_TEST . "'");
+ $tables = $this->fetchAll($check);
+ self::assertCount(0, $tables);
+ }
+
+ public function test_truncate_table() : void
+ {
+ $createQuery = create()->table(self::TABLE_TEST)
+ ->column(column('id', sql_type_serial()))
+ ->column(column('name', sql_type_varchar(100)));
+ $this->execute($createQuery->toSql());
+
+ $this->execute('INSERT INTO ' . self::TABLE_TEST . " (name) VALUES ('test1'), ('test2')");
+
+ $truncateQuery = truncate_table(self::TABLE_TEST);
+
+ $result = $this->execute($truncateQuery->toSql());
+
+ self::assertNotFalse($result);
+
+ $check = $this->execute('SELECT COUNT(*) as cnt FROM ' . self::TABLE_TEST);
+ $row = $this->fetchOne($check);
+ 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
new file mode 100644
index 000000000..4efbe1c3c
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/TransactionDatabaseTest.php
@@ -0,0 +1,219 @@
+execute(
+ create()->table(self::TABLE_ACCOUNTS)
+ ->column(column('id', sql_type_serial()))
+ ->column(column('name', sql_type_varchar(100))->notNull())
+ ->column(column('balance', sql_type_decimal(10, 2))->default(0))
+ ->constraint(primary_key('id'))
+ ->toSql()
+ );
+
+ $this->execute(
+ insert()
+ ->into(self::TABLE_ACCOUNTS)
+ ->columns('name', 'balance')
+ ->values(literal('Account A'), literal(1000))
+ ->values(literal('Account B'), literal(500))
+ ->toSql()
+ );
+ }
+
+ protected function tearDown() : void
+ {
+ $this->execute(rollback()->toSql());
+ $this->dropTableIfExists(self::TABLE_ACCOUNTS);
+
+ parent::tearDown();
+ }
+
+ public function test_begin_and_commit() : void
+ {
+ $this->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->execute(commit()->toSql());
+
+ $check = $this->execute(
+ 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(
+ 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());
+
+ $updateQuery = update()
+ ->update(self::TABLE_ACCOUNTS)
+ ->set('balance', literal(9999))
+ ->where(eq(col('name'), literal('Account A')));
+
+ $this->execute($updateQuery->toSql());
+
+ $this->execute(rollback()->toSql());
+
+ $check = $this->execute(
+ 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());
+
+ $selectQuery = select(star())->from(table(self::TABLE_ACCOUNTS));
+ $result = $this->execute($selectQuery->toSql());
+
+ self::assertNotFalse($result);
+ $rows = $this->fetchAll($result);
+ self::assertCount(2, $rows);
+
+ $this->execute(commit()->toSql());
+ }
+
+ public function test_begin_with_read_only() : void
+ {
+ $this->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));
+
+ $this->execute(commit()->toSql());
+ }
+
+ public function test_rollback_to_savepoint() : void
+ {
+ $this->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->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->execute(rollback()->toSavepoint('sp_rollback')->toSql());
+
+ $check = $this->execute(
+ 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());
+ }
+
+ public function test_savepoint_and_release() : void
+ {
+ $this->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->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->execute(release_savepoint('sp1')->toSql());
+ $this->execute(commit()->toSql());
+
+ $checkA = $this->execute(
+ 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(
+ 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
new file mode 100644
index 000000000..c1e8ff3c6
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/TriggerDatabaseTest.php
@@ -0,0 +1,318 @@
+execute(
+ create()->table(self::TABLE_NAME)
+ ->column(column('id', sql_type_serial()))
+ ->column(column('name', sql_type_varchar(100))->notNull())
+ ->column(column('value', sql_type_integer())->default(0))
+ ->constraint(primary_key('id'))
+ ->toSql()
+ );
+
+ $this->execute(
+ create()->table(self::TABLE_LOG)
+ ->column(column('id', sql_type_serial()))
+ ->column(column('action', sql_type_varchar(50))->notNull())
+ ->constraint(primary_key('id'))
+ ->toSql()
+ );
+
+ $this->execute(
+ create()->function(self::FUNCTION_NAME)
+ ->arguments()
+ ->returns(DataType::custom('trigger'))
+ ->language('plpgsql')
+ ->as('BEGIN INSERT INTO ' . self::TABLE_LOG . ' (action) VALUES (TG_OP); RETURN NEW; END;')
+ ->toSql()
+ );
+ }
+
+ 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);
+
+ parent::tearDown();
+ }
+
+ public function test_alter_trigger_rename() : void
+ {
+ $this->execute(
+ create()->trigger(self::TRIGGER_NAME)
+ ->before(TriggerEvent::INSERT)
+ ->on(self::TABLE_NAME)
+ ->forEachRow()
+ ->execute(self::FUNCTION_NAME)
+ ->toSql()
+ );
+
+ $result = $this->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(
+ create()->trigger(self::TRIGGER_NAME)
+ ->before(TriggerEvent::INSERT)
+ ->on(self::TABLE_NAME)
+ ->forEachRow()
+ ->execute(self::FUNCTION_NAME)
+ ->toSql()
+ );
+
+ $result = $this->execute(
+ create()->trigger(self::TRIGGER_NAME)
+ ->orReplace()
+ ->after(TriggerEvent::INSERT)
+ ->on(self::TABLE_NAME)
+ ->forEachRow()
+ ->execute(self::FUNCTION_NAME)
+ ->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(
+ create()->trigger(self::TRIGGER_NAME)
+ ->after(TriggerEvent::INSERT)
+ ->on(self::TABLE_NAME)
+ ->forEachRow()
+ ->execute(self::FUNCTION_NAME)
+ ->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(
+ create()->trigger(self::TRIGGER_NAME)
+ ->after(TriggerEvent::INSERT, TriggerEvent::UPDATE)
+ ->on(self::TABLE_NAME)
+ ->forEachRow()
+ ->execute(self::FUNCTION_NAME)
+ ->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(
+ create()->trigger(self::TRIGGER_NAME)
+ ->before(TriggerEvent::INSERT)
+ ->on(self::TABLE_NAME)
+ ->forEachRow()
+ ->execute(self::FUNCTION_NAME)
+ ->toSql()
+ );
+
+ self::assertNotFalse($result);
+ self::assertTrue($this->triggerExists(self::TRIGGER_NAME, self::TABLE_NAME));
+
+ $this->execute(
+ insert()
+ ->into(self::TABLE_NAME)
+ ->columns('name')
+ ->values(literal('Test'))
+ ->toSql()
+ );
+
+ $logs = $this->fetchAll(
+ $this->execute(
+ select(star())->from(table(self::TABLE_LOG))
+ ->toSql()
+ )
+ );
+
+ self::assertCount(1, $logs);
+ self::assertSame('INSERT', $logs[0]['action']);
+ }
+
+ public function test_create_trigger_with_when_condition() : void
+ {
+ $result = $this->execute(
+ create()->trigger(self::TRIGGER_NAME)
+ ->before(TriggerEvent::INSERT)
+ ->on(self::TABLE_NAME)
+ ->forEachRow()
+ ->when(raw_cond('NEW.value <> 0'))
+ ->execute(self::FUNCTION_NAME)
+ ->toSql()
+ );
+
+ self::assertNotFalse($result);
+ self::assertTrue($this->triggerExists(self::TRIGGER_NAME, self::TABLE_NAME));
+
+ $this->execute(
+ insert()
+ ->into(self::TABLE_NAME)
+ ->columns('name', 'value')
+ ->values(literal('Zero'), literal(0))
+ ->toSql()
+ );
+
+ $logs = $this->fetchAll(
+ $this->execute(
+ select(star())->from(table(self::TABLE_LOG))
+ ->toSql()
+ )
+ );
+ self::assertCount(0, $logs);
+
+ $this->execute(
+ insert()
+ ->into(self::TABLE_NAME)
+ ->columns('name', 'value')
+ ->values(literal('NonZero'), literal(5))
+ ->toSql()
+ );
+
+ $logs = $this->fetchAll(
+ $this->execute(
+ select(star())->from(table(self::TABLE_LOG))
+ ->toSql()
+ )
+ );
+ self::assertCount(1, $logs);
+ }
+
+ public function test_drop_trigger() : void
+ {
+ $this->execute(
+ create()->trigger(self::TRIGGER_NAME)
+ ->before(TriggerEvent::INSERT)
+ ->on(self::TABLE_NAME)
+ ->forEachRow()
+ ->execute(self::FUNCTION_NAME)
+ ->toSql()
+ );
+
+ self::assertTrue($this->triggerExists(self::TRIGGER_NAME, self::TABLE_NAME));
+
+ $result = $this->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(
+ create()->trigger(self::TRIGGER_NAME)
+ ->before(TriggerEvent::INSERT)
+ ->on(self::TABLE_NAME)
+ ->forEachRow()
+ ->execute(self::FUNCTION_NAME)
+ ->toSql()
+ );
+
+ $result = $this->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(
+ 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(
+ 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';
+ }
+}
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
new file mode 100644
index 000000000..96fc9d4c5
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/TruncateDatabaseTest.php
@@ -0,0 +1,243 @@
+execute(
+ create()->table(self::TABLE_ONE)
+ ->column(column('id', sql_type_serial()))
+ ->column(column('name', sql_type_varchar(100))->notNull())
+ ->constraint(primary_key('id'))
+ ->toSql()
+ );
+
+ $this->execute(
+ create()->table(self::TABLE_TWO)
+ ->column(column('id', sql_type_serial()))
+ ->column(column('name', sql_type_varchar(100))->notNull())
+ ->constraint(primary_key('id'))
+ ->toSql()
+ );
+
+ $this->execute(
+ insert()
+ ->into(self::TABLE_ONE)
+ ->columns('name')
+ ->values(literal('Alice'))
+ ->values(literal('Bob'))
+ ->values(literal('Charlie'))
+ ->toSql()
+ );
+
+ $this->execute(
+ insert()
+ ->into(self::TABLE_TWO)
+ ->columns('name')
+ ->values(literal('Dave'))
+ ->values(literal('Eve'))
+ ->toSql()
+ );
+ }
+
+ protected function tearDown() : void
+ {
+ $this->dropTableIfExists(self::TABLE_TWO);
+ $this->dropTableIfExists(self::TABLE_ONE);
+
+ parent::tearDown();
+ }
+
+ public function test_truncate_cascade() : void
+ {
+ $result = $this->execute(
+ truncate_table(self::TABLE_ONE)->cascade()->toSql()
+ );
+
+ self::assertNotFalse($result);
+
+ $rows = $this->fetchAll(
+ $this->execute(
+ 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()
+ )
+ );
+ $lastId = (int) $lastRow['id'];
+
+ $this->execute(
+ truncate_table(self::TABLE_ONE)->continueIdentity()->toSql()
+ );
+
+ $this->execute(
+ insert()
+ ->into(self::TABLE_ONE)
+ ->columns('name')
+ ->values(literal('NewRow'))
+ ->toSql()
+ );
+
+ $row = $this->fetchOne(
+ $this->execute(
+ select(star())->from(table(self::TABLE_ONE))->toSql()
+ )
+ );
+
+ self::assertSame((string) ($lastId + 1), $row['id']);
+ }
+
+ public function test_truncate_multiple_tables() : void
+ {
+ $result = $this->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()
+ )
+ );
+ self::assertCount(0, $rowsOne);
+
+ $rowsTwo = $this->fetchAll(
+ $this->execute(
+ select(star())->from(table(self::TABLE_TWO))->toSql()
+ )
+ );
+ self::assertCount(0, $rowsTwo);
+ }
+
+ public function test_truncate_restart_identity() : void
+ {
+ $this->execute(
+ truncate_table(self::TABLE_ONE)->restartIdentity()->toSql()
+ );
+
+ $this->execute(
+ insert()
+ ->into(self::TABLE_ONE)
+ ->columns('name')
+ ->values(literal('NewRow'))
+ ->toSql()
+ );
+
+ $row = $this->fetchOne(
+ $this->execute(
+ select(star())->from(table(self::TABLE_ONE))->toSql()
+ )
+ );
+
+ self::assertSame('1', $row['id']);
+ self::assertSame('NewRow', $row['name']);
+ }
+
+ public function test_truncate_restrict() : void
+ {
+ $result = $this->execute(
+ truncate_table(self::TABLE_ONE)->restrict()->toSql()
+ );
+
+ self::assertNotFalse($result);
+
+ $rows = $this->fetchAll(
+ $this->execute(
+ 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()
+ )
+ );
+ self::assertCount(3, $rows);
+
+ $result = $this->execute(
+ truncate_table(self::TABLE_ONE)->toSql()
+ );
+
+ self::assertNotFalse($result);
+
+ $rows = $this->fetchAll(
+ $this->execute(
+ 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()
+ )
+ );
+ self::assertCount(2, $rowsTwo);
+ }
+
+ public function test_truncate_with_restart_identity_and_cascade() : void
+ {
+ $result = $this->execute(
+ truncate_table(self::TABLE_ONE, self::TABLE_TWO)
+ ->restartIdentity()
+ ->cascade()
+ ->toSql()
+ );
+
+ self::assertNotFalse($result);
+
+ $this->execute(
+ insert()
+ ->into(self::TABLE_ONE)
+ ->columns('name')
+ ->values(literal('AfterTruncate'))
+ ->toSql()
+ );
+
+ $row = $this->fetchOne(
+ $this->execute(
+ select(star())->from(table(self::TABLE_ONE))->toSql()
+ )
+ );
+
+ self::assertSame('1', $row['id']);
+ }
+}
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
new file mode 100644
index 000000000..6f5f9f0a7
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/TypeDatabaseTest.php
@@ -0,0 +1,334 @@
+dropTableIfExists(self::TABLE_NAME);
+ $this->dropTypeIfExists(self::ENUM_TYPE);
+ $this->dropTypeIfExists(self::COMPOSITE_TYPE);
+ $this->dropTypeIfExists(self::RANGE_TYPE);
+
+ parent::tearDown();
+ }
+
+ public function test_alter_enum_add_value() : void
+ {
+ $this->execute(
+ create()->enumType(self::ENUM_TYPE)
+ ->labels('pending', 'active')
+ ->toSql()
+ );
+
+ $result = $this->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')
+ );
+
+ $enumValues = \array_column($values, 'val');
+ self::assertContains('completed', $enumValues);
+ }
+
+ public function test_alter_enum_add_value_after() : void
+ {
+ $this->execute(
+ create()->enumType(self::ENUM_TYPE)
+ ->labels('first', 'last')
+ ->toSql()
+ );
+
+ $result = $this->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')
+ );
+
+ self::assertSame('first', $values[0]['val']);
+ self::assertSame('middle', $values[1]['val']);
+ self::assertSame('last', $values[2]['val']);
+ }
+
+ public function test_alter_enum_add_value_before() : void
+ {
+ $this->execute(
+ create()->enumType(self::ENUM_TYPE)
+ ->labels('first', 'last')
+ ->toSql()
+ );
+
+ $result = $this->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')
+ );
+
+ self::assertSame('first', $values[0]['val']);
+ self::assertSame('middle', $values[1]['val']);
+ self::assertSame('last', $values[2]['val']);
+ }
+
+ public function test_alter_enum_add_value_if_not_exists() : void
+ {
+ $this->execute(
+ create()->enumType(self::ENUM_TYPE)
+ ->labels('pending', 'active')
+ ->toSql()
+ );
+
+ $result = $this->execute(
+ alter()->enumType(self::ENUM_TYPE)
+ ->addValue('active')
+ ->ifNotExists()
+ ->toSql()
+ );
+
+ self::assertNotFalse($result);
+ }
+
+ public function test_alter_enum_rename_value() : void
+ {
+ $this->execute(
+ create()->enumType(self::ENUM_TYPE)
+ ->labels('old_name', 'other')
+ ->toSql()
+ );
+
+ $result = $this->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')
+ );
+
+ $enumValues = \array_column($values, 'val');
+ self::assertNotContains('old_name', $enumValues);
+ self::assertContains('new_name', $enumValues);
+ }
+
+ public function test_create_composite_type() : void
+ {
+ $result = $this->execute(
+ create()->compositeType(self::COMPOSITE_TYPE)
+ ->attributes(
+ TypeAttribute::of('street', sql_type_varchar(100)),
+ TypeAttribute::of('city', sql_type_varchar(50)),
+ TypeAttribute::of('postal_code', sql_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(
+ create()->compositeType(self::COMPOSITE_TYPE)
+ ->attributes(
+ TypeAttribute::of('street', sql_type_varchar(100)),
+ TypeAttribute::of('city', sql_type_varchar(50))
+ )
+ ->toSql()
+ );
+
+ $this->execute(
+ create()->table(self::TABLE_NAME)
+ ->column(column('id', sql_type_serial()))
+ ->column(column('name', sql_type_varchar(100)))
+ ->column(column('address', DataType::custom(self::COMPOSITE_TYPE)))
+ ->constraint(primary_key('id'))
+ ->toSql()
+ );
+
+ $this->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
+ )
+ );
+
+ self::assertSame('John', $row['name']);
+ self::assertSame('123 Main St', $row['street']);
+ self::assertSame('NYC', $row['city']);
+ }
+
+ public function test_create_enum_type() : void
+ {
+ $result = $this->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(
+ create()->enumType(self::ENUM_TYPE)
+ ->labels('pending', 'active', 'completed')
+ ->toSql()
+ );
+
+ $this->execute(
+ create()->table(self::TABLE_NAME)
+ ->column(column('id', sql_type_serial()))
+ ->column(column('status', DataType::custom(self::ENUM_TYPE))->notNull())
+ ->constraint(primary_key('id'))
+ ->toSql()
+ );
+
+ $this->execute(
+ insert()
+ ->into(self::TABLE_NAME)
+ ->columns('status')
+ ->values(literal('active'))
+ ->toSql()
+ );
+
+ $row = $this->fetchOne(
+ $this->execute(
+ select(star())->from(table(self::TABLE_NAME))->toSql()
+ )
+ );
+
+ self::assertSame('active', $row['status']);
+ }
+
+ public function test_create_range_type() : void
+ {
+ $result = $this->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(
+ create()->enumType(self::ENUM_TYPE)
+ ->labels('a', 'b')
+ ->toSql()
+ );
+
+ self::assertTrue($this->typeExists(self::ENUM_TYPE));
+
+ $result = $this->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(
+ create()->enumType(self::ENUM_TYPE)
+ ->labels('a', 'b')
+ ->toSql()
+ );
+
+ $this->execute(
+ create()->table(self::TABLE_NAME)
+ ->column(column('id', sql_type_serial()))
+ ->column(column('status', DataType::custom(self::ENUM_TYPE)))
+ ->constraint(primary_key('id'))
+ ->toSql()
+ );
+
+ $result = $this->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(
+ 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")
+ );
+
+ return $row['type_exists'] === 't';
+ }
+}
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
new file mode 100644
index 000000000..952f00452
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/UpdateDatabaseTest.php
@@ -0,0 +1,211 @@
+execute(
+ create()->table(self::TABLE_DEPARTMENTS)
+ ->column(column('id', sql_type_serial()))
+ ->column(column('name', sql_type_varchar(100))->notNull())
+ ->column(column('bonus_rate', sql_type_decimal(3, 2))->default(1))
+ ->constraint(primary_key('id'))
+ ->toSql()
+ );
+
+ $this->execute(
+ create()->table(self::TABLE_EMPLOYEES)
+ ->column(column('id', sql_type_serial()))
+ ->column(column('name', sql_type_varchar(100))->notNull())
+ ->column(column('salary', sql_type_decimal(10, 2))->default(0))
+ ->column(column('department_id', sql_type_integer()))
+ ->column(column('status', sql_type_varchar(50))->default('active'))
+ ->constraint(primary_key('id'))
+ ->toSql()
+ );
+
+ $this->execute(
+ insert()
+ ->into(self::TABLE_DEPARTMENTS)
+ ->columns('name', 'bonus_rate')
+ ->values(literal('Engineering'), literal(1))
+ ->values(literal('Sales'), literal(1))
+ ->values(literal('HR'), literal(1))
+ ->toSql()
+ );
+
+ $this->execute(
+ insert()
+ ->into(self::TABLE_EMPLOYEES)
+ ->columns('name', 'salary', 'department_id', 'status')
+ ->values(literal('Alice'), literal(50000), literal(1), literal('active'))
+ ->values(literal('Bob'), literal(60000), literal(1), literal('active'))
+ ->values(literal('Charlie'), literal(55000), literal(2), literal('active'))
+ ->values(literal('Diana'), literal(45000), literal(3), literal('inactive'))
+ ->toSql()
+ );
+ }
+
+ protected function tearDown() : void
+ {
+ $this->dropTableIfExists(self::TABLE_EMPLOYEES);
+ $this->dropTableIfExists(self::TABLE_DEPARTMENTS);
+
+ parent::tearDown();
+ }
+
+ public function test_basic_update() : void
+ {
+ $query = update()
+ ->update(self::TABLE_EMPLOYEES)
+ ->set('status', literal('updated'));
+
+ $result = $this->execute($query->toSql());
+
+ self::assertNotFalse($result);
+ self::assertSame(4, $this->affectedRows($result));
+
+ $check = $this->execute(
+ 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']);
+ }
+
+ public function test_update_multiple_columns() : void
+ {
+ $query = update()
+ ->update(self::TABLE_EMPLOYEES)
+ ->set('salary', literal(75000))
+ ->set('status', literal('promoted'))
+ ->where(eq(col('name'), literal('Bob')));
+
+ $result = $this->execute($query->toSql());
+
+ self::assertNotFalse($result);
+
+ $check = $this->execute(
+ 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']);
+ }
+
+ public function test_update_with_from_clause() : void
+ {
+ $query = update()
+ ->update(self::TABLE_EMPLOYEES)
+ ->set('status', literal('bonus_applied'))
+ ->from(table(self::TABLE_DEPARTMENTS))
+ ->where(
+ cond_and(
+ eq(
+ col('department_id', self::TABLE_EMPLOYEES),
+ col('id', self::TABLE_DEPARTMENTS)
+ ),
+ gt(col('bonus_rate', self::TABLE_DEPARTMENTS), literal(0))
+ )
+ );
+
+ $result = $this->execute($query->toSql());
+
+ self::assertNotFalse($result);
+ self::assertGreaterThanOrEqual(1, $this->affectedRows($result));
+ }
+
+ public function test_update_with_returning() : void
+ {
+ $query = update()
+ ->update(self::TABLE_EMPLOYEES)
+ ->set('salary', literal(80000))
+ ->where(eq(col('name'), literal('Charlie')))
+ ->returning(col('id'), col('name'), col('salary'));
+
+ $result = $this->execute($query->toSql());
+
+ self::assertNotFalse($result);
+ $row = $this->fetchOne($result);
+ self::assertSame('Charlie', $row['name']);
+ self::assertSame('80000.00', $row['salary']);
+ }
+
+ public function test_update_with_returning_all() : void
+ {
+ $query = update()
+ ->update(self::TABLE_EMPLOYEES)
+ ->set('status', literal('reviewed'))
+ ->where(eq(col('name'), literal('Diana')))
+ ->returningAll();
+
+ $result = $this->execute($query->toSql());
+
+ self::assertNotFalse($result);
+ $row = $this->fetchOne($result);
+ self::assertArrayHasKey('id', $row);
+ self::assertArrayHasKey('name', $row);
+ self::assertArrayHasKey('salary', $row);
+ self::assertArrayHasKey('department_id', $row);
+ self::assertArrayHasKey('status', $row);
+ self::assertSame('reviewed', $row['status']);
+ }
+
+ public function test_update_with_where() : void
+ {
+ $query = update()
+ ->update(self::TABLE_EMPLOYEES)
+ ->set('salary', literal(70000))
+ ->where(eq(col('name'), literal('Alice')));
+
+ $result = $this->execute($query->toSql());
+
+ self::assertNotFalse($result);
+ self::assertSame(1, $this->affectedRows($result));
+
+ $check = $this->execute(
+ 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
new file mode 100644
index 000000000..116d6137e
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/UtilityDatabaseTest.php
@@ -0,0 +1,306 @@
+execute(
+ create()->table(self::TABLE_NAME)
+ ->column(column('id', sql_type_serial()))
+ ->column(column('name', sql_type_varchar(100))->notNull())
+ ->column(column('value', sql_type_integer())->default(0))
+ ->constraint(primary_key('id'))
+ ->toSql()
+ );
+
+ $this->execute(
+ insert()
+ ->into(self::TABLE_NAME)
+ ->columns('name', 'value')
+ ->values(literal('Alice'), literal(100))
+ ->values(literal('Bob'), literal(200))
+ ->toSql()
+ );
+ }
+
+ protected function tearDown() : void
+ {
+ $this->dropIndexIfExists(self::INDEX_NAME);
+ $this->dropTableIfExists(self::TABLE_NAME);
+
+ parent::tearDown();
+ }
+
+ public function test_analyze_specific_columns() : void
+ {
+ $result = $this->execute(
+ analyze()->table(self::TABLE_NAME, 'name', 'value')
+ ->toSql()
+ );
+
+ self::assertNotFalse($result);
+ }
+
+ public function test_analyze_table() : void
+ {
+ $result = $this->execute(
+ analyze()->tables(self::TABLE_NAME)
+ ->toSql()
+ );
+
+ self::assertNotFalse($result);
+ }
+
+ public function test_analyze_verbose() : void
+ {
+ $result = $this->execute(
+ analyze()->verbose()->tables(self::TABLE_NAME)
+ ->toSql()
+ );
+
+ self::assertNotFalse($result);
+ }
+
+ public function test_cluster_table_on_index() : void
+ {
+ $this->execute(
+ create()->index(self::INDEX_NAME)
+ ->on(self::TABLE_NAME)
+ ->columns('name')
+ ->toSql()
+ );
+
+ $result = $this->execute(
+ cluster()->table(self::TABLE_NAME)->using(self::INDEX_NAME)
+ ->toSql()
+ );
+
+ self::assertNotFalse($result);
+ }
+
+ public function test_cluster_verbose() : void
+ {
+ $this->execute(
+ create()->index(self::INDEX_NAME)
+ ->on(self::TABLE_NAME)
+ ->columns('name')
+ ->toSql()
+ );
+
+ $this->execute(
+ cluster()->table(self::TABLE_NAME)->using(self::INDEX_NAME)
+ ->toSql()
+ );
+
+ $result = $this->execute(
+ cluster()->verbose()->table(self::TABLE_NAME)
+ ->toSql()
+ );
+
+ self::assertNotFalse($result);
+ }
+
+ public function test_comment_on_column() : void
+ {
+ $result = $this->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(
+ 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"
+ )
+ );
+
+ self::assertSame('This is a test table for utility tests', $row['comment']);
+ }
+
+ public function test_comment_remove() : void
+ {
+ $this->execute(
+ comment(CommentTarget::TABLE, self::TABLE_NAME)
+ ->is('Some comment')
+ ->toSql()
+ );
+
+ $result = $this->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"
+ )
+ );
+
+ self::assertNull($row['comment']);
+ }
+
+ public function test_explain_analyze() : void
+ {
+ $selectQuery = select(star())->from(table(self::TABLE_NAME));
+
+ $result = $this->execute(
+ explain($selectQuery)->analyze()
+ ->toSql()
+ );
+
+ self::assertNotFalse($result);
+
+ $rows = $this->fetchAll($result);
+ self::assertNotEmpty($rows);
+ }
+
+ public function test_explain_select() : void
+ {
+ $selectQuery = select(star())->from(table(self::TABLE_NAME));
+
+ $result = $this->execute(
+ explain($selectQuery)
+ ->toSql()
+ );
+
+ self::assertNotFalse($result);
+
+ $rows = $this->fetchAll($result);
+ self::assertNotEmpty($rows);
+ self::assertArrayHasKey('QUERY PLAN', $rows[0]);
+ }
+
+ public function test_explain_verbose() : void
+ {
+ $selectQuery = select(star())->from(table(self::TABLE_NAME));
+
+ $result = $this->execute(
+ explain($selectQuery)->verbose()
+ ->toSql()
+ );
+
+ self::assertNotFalse($result);
+
+ $rows = $this->fetchAll($result);
+ self::assertNotEmpty($rows);
+ }
+
+ public function test_lock_table() : void
+ {
+ $this->execute('BEGIN');
+
+ $result = $this->execute(
+ lock_table(self::TABLE_NAME)
+ ->toSql()
+ );
+
+ self::assertNotFalse($result);
+
+ $this->execute('COMMIT');
+ }
+
+ public function test_lock_table_nowait() : void
+ {
+ $this->execute('BEGIN');
+
+ $result = $this->execute(
+ lock_table(self::TABLE_NAME)->noWait()
+ ->toSql()
+ );
+
+ self::assertNotFalse($result);
+
+ $this->execute('COMMIT');
+ }
+
+ public function test_lock_table_with_mode() : void
+ {
+ $this->execute('BEGIN');
+
+ $result = $this->execute(
+ lock_table(self::TABLE_NAME)->inMode(LockMode::SHARE)
+ ->toSql()
+ );
+
+ self::assertNotFalse($result);
+
+ $this->execute('COMMIT');
+ }
+
+ public function test_vacuum_analyze_table() : void
+ {
+ $result = $this->execute(
+ vacuum()->analyze()->tables(self::TABLE_NAME)
+ ->toSql()
+ );
+
+ self::assertNotFalse($result);
+ }
+
+ public function test_vacuum_full() : void
+ {
+ $result = $this->execute(
+ vacuum()->full()->tables(self::TABLE_NAME)
+ ->toSql()
+ );
+
+ self::assertNotFalse($result);
+ }
+
+ public function test_vacuum_table() : void
+ {
+ $result = $this->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
new file mode 100644
index 000000000..dd2893f09
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/Database/ViewDatabaseTest.php
@@ -0,0 +1,241 @@
+table(self::TABLE_SOURCE)
+ ->column(column('id', sql_type_serial()))
+ ->column(column('name', sql_type_varchar(100)))
+ ->column(column('value', sql_type_integer()));
+
+ $this->execute($query->toSql());
+
+ $this->execute(
+ insert()
+ ->into(self::TABLE_SOURCE)
+ ->columns('name', 'value')
+ ->values(literal('Item A'), literal(100))
+ ->values(literal('Item B'), literal(200))
+ ->values(literal('Item C'), literal(50))
+ ->values(literal('Item D'), literal(300))
+ ->toSql()
+ );
+ }
+
+ protected function tearDown() : void
+ {
+ $this->dropViewIfExists(self::VIEW_SIMPLE);
+ $this->dropViewIfExists(self::VIEW_FILTERED);
+ $this->dropMaterializedViewIfExists(self::MATVIEW_SIMPLE);
+ $this->dropTableIfExists(self::TABLE_SOURCE);
+
+ parent::tearDown();
+ }
+
+ public function test_create_materialized_view() : void
+ {
+ $selectQuery = select(star())->from(table(self::TABLE_SOURCE));
+
+ $query = create()->materializedView(self::MATVIEW_SIMPLE)
+ ->as($selectQuery);
+
+ $result = $this->execute($query->toSql());
+
+ self::assertNotFalse($result);
+
+ $check = $this->execute("SELECT matviewname FROM pg_matviews WHERE matviewname = '" . self::MATVIEW_SIMPLE . "'");
+ $views = $this->fetchAll($check);
+ self::assertCount(1, $views);
+ }
+
+ 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());
+
+ $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);
+
+ $check = $this->execute('SELECT * FROM ' . self::VIEW_SIMPLE);
+ $row = $this->fetchOne($check);
+ self::assertArrayHasKey('id', $row);
+ self::assertArrayHasKey('name', $row);
+ self::assertArrayHasKey('value', $row);
+ }
+
+ public function test_create_view() : void
+ {
+ $selectQuery = select(star())->from(table(self::TABLE_SOURCE));
+
+ $query = create()->view(self::VIEW_SIMPLE)
+ ->as($selectQuery);
+
+ $result = $this->execute($query->toSql());
+
+ self::assertNotFalse($result);
+
+ $check = $this->execute(
+ 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);
+ }
+
+ public function test_create_view_with_filter() : void
+ {
+ $selectQuery = select(star())
+ ->from(table(self::TABLE_SOURCE))
+ ->where(gt(col('value'), literal(100)));
+
+ $query = create()->view(self::VIEW_FILTERED)
+ ->as($selectQuery);
+
+ $this->execute($query->toSql());
+
+ $result = $this->execute('SELECT * FROM ' . self::VIEW_FILTERED);
+
+ self::assertNotFalse($result);
+ $rows = $this->fetchAll($result);
+ self::assertCount(2, $rows);
+ }
+
+ 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());
+
+ $dropQuery = drop()->materializedView(self::MATVIEW_SIMPLE);
+
+ $result = $this->execute($dropQuery->toSql());
+
+ self::assertNotFalse($result);
+
+ $check = $this->execute("SELECT matviewname FROM pg_matviews WHERE matviewname = '" . self::MATVIEW_SIMPLE . "'");
+ $views = $this->fetchAll($check);
+ self::assertCount(0, $views);
+ }
+
+ 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());
+
+ $dropQuery = drop()->view(self::VIEW_SIMPLE);
+
+ $result = $this->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);
+ self::assertCount(0, $views);
+ }
+
+ public function test_drop_view_if_exists() : void
+ {
+ $dropQuery = drop()->view(self::VIEW_SIMPLE)->ifExists();
+
+ $result = $this->execute($dropQuery->toSql());
+
+ self::assertNotFalse($result);
+ }
+
+ public function test_materialized_view_returns_data() : void
+ {
+ $selectQuery = select(star())->from(table(self::TABLE_SOURCE));
+
+ $createQuery = create()->materializedView(self::MATVIEW_SIMPLE)
+ ->as($selectQuery);
+ $this->execute($createQuery->toSql());
+
+ $result = $this->execute('SELECT * FROM ' . self::MATVIEW_SIMPLE);
+
+ self::assertNotFalse($result);
+ $rows = $this->fetchAll($result);
+ self::assertCount(4, $rows);
+ }
+
+ public function test_refresh_materialized_view() : void
+ {
+ $selectQuery = select(star())->from(table(self::TABLE_SOURCE));
+
+ $createQuery = create()->materializedView(self::MATVIEW_SIMPLE)
+ ->as($selectQuery);
+ $this->execute($createQuery->toSql());
+
+ $this->execute('INSERT INTO ' . self::TABLE_SOURCE . " (name, value) VALUES ('Item E', 500)");
+
+ $beforeRefresh = $this->execute('SELECT COUNT(*) as cnt FROM ' . self::MATVIEW_SIMPLE);
+ $beforeRow = $this->fetchOne($beforeRefresh);
+ self::assertSame('4', $beforeRow['cnt']);
+
+ $refreshQuery = refresh_materialized_view(self::MATVIEW_SIMPLE);
+ $this->execute($refreshQuery->toSql());
+
+ $afterRefresh = $this->execute('SELECT COUNT(*) as cnt FROM ' . self::MATVIEW_SIMPLE);
+ $afterRow = $this->fetchOne($afterRefresh);
+ self::assertSame('5', $afterRow['cnt']);
+ }
+
+ public function test_view_returns_data() : void
+ {
+ $selectQuery = select(star())->from(table(self::TABLE_SOURCE));
+
+ $createQuery = create()->view(self::VIEW_SIMPLE)
+ ->as($selectQuery);
+ $this->execute($createQuery->toSql());
+
+ $result = $this->execute(
+ 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
new file mode 100644
index 000000000..3f4fbd6a8
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/DeleteBuilderTest.php
@@ -0,0 +1,103 @@
+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
new file mode 100644
index 000000000..48b093172
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/DomainBuilderTest.php
@@ -0,0 +1,274 @@
+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
new file mode 100644
index 000000000..724effa09
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/ExtensionBuilderTest.php
@@ -0,0 +1,209 @@
+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/FunctionBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/FunctionBuilderTest.php
new file mode 100644
index 000000000..0b56d2497
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/FunctionBuilderTest.php
@@ -0,0 +1,207 @@
+function('my_func')
+ ->arguments(func_arg(sql_type_integer()))
+ ->immutable();
+
+ $this->assertAlterFunctionQuery($builder, 'ALTER FUNCTION my_func(int) IMMUTABLE');
+ }
+
+ public function test_alter_function_parallel_safe() : void
+ {
+ $builder = alter()->function('my_func')
+ ->arguments(func_arg(sql_type_integer()))
+ ->parallel(ParallelSafety::SAFE);
+
+ $this->assertAlterFunctionQuery($builder, 'ALTER FUNCTION my_func(int) PARALLEL safe');
+ }
+
+ public function test_alter_function_rename() : void
+ {
+ $builder = alter()->function('old_name')
+ ->arguments(func_arg(sql_type_text()))
+ ->renameTo('new_name');
+
+ $this->assertAlterFunctionRenameQuery($builder, 'ALTER FUNCTION old_name(pg_catalog.text) RENAME TO new_name');
+ }
+
+ public function test_alter_procedure_rename() : void
+ {
+ $builder = alter()->procedure('old_proc')
+ ->arguments(func_arg(sql_type_integer()))
+ ->renameTo('new_proc');
+
+ $this->assertAlterProcedureRenameQuery($builder, 'ALTER PROCEDURE old_proc(int) RENAME TO new_proc');
+ }
+
+ public function test_call_procedure() : void
+ {
+ $builder = call('update_stats');
+
+ $this->assertCallQuery($builder, 'CALL update_stats()');
+ }
+
+ public function test_call_procedure_with_args() : void
+ {
+ $builder = call('update_stats')->with(123, 'test');
+
+ $this->assertCallQuery($builder, "CALL update_stats(123, 'test')");
+ }
+
+ public function test_create_function_plpgsql() : void
+ {
+ $builder = create()->function('increment')
+ ->arguments(func_arg(sql_type_integer())->named('val'))
+ ->returns(sql_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;$$'
+ );
+ }
+
+ public function test_create_function_returns_table() : void
+ {
+ $builder = create()->function('get_users')
+ ->returnsTable(['id' => sql_type_integer(), 'name' => sql_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$$'
+ );
+ }
+
+ public function test_create_function_simple() : void
+ {
+ $builder = create()->function('add_numbers')
+ ->arguments(func_arg(sql_type_integer())->named('a'), func_arg(sql_type_integer())->named('b'))
+ ->returns(sql_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$$'
+ );
+ }
+
+ public function test_create_function_with_options() : void
+ {
+ $builder = create()->function('compute')
+ ->arguments(func_arg(sql_type_integer())->named('x'))
+ ->returns(sql_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$$'
+ );
+ }
+
+ public function test_create_function_with_or_replace() : void
+ {
+ $builder = create()->function('my_func')
+ ->orReplace()
+ ->returns(sql_type_integer())
+ ->language('sql')
+ ->as('SELECT 1');
+
+ $this->assertCreateFunctionQuery(
+ $builder,
+ 'CREATE OR REPLACE FUNCTION my_func() RETURNS int LANGUAGE sql AS $$SELECT 1$$'
+ );
+ }
+
+ public function test_create_procedure() : void
+ {
+ $builder = create()->procedure('update_stats')
+ ->arguments(func_arg(sql_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;$$'
+ );
+ }
+
+ public function test_create_procedure_with_or_replace() : void
+ {
+ $builder = create()->procedure('my_proc')
+ ->orReplace()
+ ->language('sql')
+ ->as('SELECT 1');
+
+ $this->assertCreateProcedureQuery(
+ $builder,
+ 'CREATE OR REPLACE PROCEDURE my_proc() LANGUAGE sql AS $$SELECT 1$$'
+ );
+ }
+
+ 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');
+ }
+
+ public function test_do_block_with_language() : void
+ {
+ $builder = do_block('SELECT 1')->language('sql');
+
+ $this->assertDoQuery($builder, 'DO $$SELECT 1$$ LANGUAGE sql');
+ }
+
+ public function test_drop_function() : void
+ {
+ $builder = drop()->function('my_func');
+
+ $this->assertDropFunctionQuery($builder, 'DROP FUNCTION my_func');
+ }
+
+ public function test_drop_function_if_exists_cascade() : void
+ {
+ $builder = drop()->function('my_func')
+ ->ifExists()
+ ->arguments(func_arg(sql_type_integer()), func_arg(sql_type_text()))
+ ->cascade();
+
+ $this->assertDropFunctionQuery($builder, 'DROP FUNCTION IF EXISTS my_func(int, pg_catalog.text) CASCADE');
+ }
+
+ public function test_drop_procedure() : void
+ {
+ $builder = drop()->procedure('my_proc');
+
+ $this->assertDropProcedureQuery($builder, 'DROP PROCEDURE my_proc');
+ }
+
+ public function test_drop_procedure_if_exists() : void
+ {
+ $builder = drop()->procedure('my_proc')
+ ->ifExists()
+ ->arguments(func_arg(sql_type_integer()))
+ ->cascade();
+
+ $this->assertDropProcedureQuery($builder, 'DROP PROCEDURE IF EXISTS my_proc(int) CASCADE');
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/IndexBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/IndexBuilderTest.php
new file mode 100644
index 000000000..ced07255b
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/IndexBuilderTest.php
@@ -0,0 +1,490 @@
+index('idx_old')
+ ->renameTo('idx_new');
+
+ $this->assertAlterIndexRenameQuery(
+ $builder,
+ 'ALTER INDEX idx_old RENAME TO idx_new'
+ );
+ }
+
+ public function test_alter_index_rename_if_exists() : void
+ {
+ $builder = alter()->index('idx_old')
+ ->ifExists()
+ ->renameTo('idx_new');
+
+ $this->assertAlterIndexRenameQuery(
+ $builder,
+ 'ALTER INDEX IF EXISTS idx_old RENAME TO idx_new'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ public function test_alter_index_set_tablespace_if_exists() : void
+ {
+ $builder = alter()->index('idx_users_email')
+ ->ifExists()
+ ->setTablespace('fast_storage');
+
+ $this->assertAlterIndexTablespaceQuery(
+ $builder,
+ 'ALTER INDEX IF EXISTS idx_users_email SET TABLESPACE fast_storage'
+ );
+ }
+
+ public function test_create_index_concurrently() : void
+ {
+ $builder = create()->index('idx_users_email')
+ ->concurrently()
+ ->on('users')
+ ->columns('email');
+
+ $this->assertCreateIndexQuery(
+ $builder,
+ 'CREATE INDEX CONCURRENTLY idx_users_email ON users (email)'
+ );
+ }
+
+ public function test_create_index_if_not_exists() : void
+ {
+ $builder = create()->index('idx_users_email')
+ ->ifNotExists()
+ ->on('users')
+ ->columns('email');
+
+ $this->assertCreateIndexQuery(
+ $builder,
+ 'CREATE INDEX IF NOT EXISTS idx_users_email ON users (email)'
+ );
+ }
+
+ public function test_create_index_simple() : void
+ {
+ $builder = create()->index('idx_users_email')
+ ->on('users')
+ ->columns('email');
+
+ $this->assertCreateIndexQuery(
+ $builder,
+ 'CREATE INDEX idx_users_email ON users (email)'
+ );
+ }
+
+ public function test_create_index_unique() : void
+ {
+ $builder = create()->index('idx_users_email')
+ ->unique()
+ ->on('users')
+ ->columns('email');
+
+ $this->assertCreateIndexQuery(
+ $builder,
+ 'CREATE UNIQUE INDEX idx_users_email ON users (email)'
+ );
+ }
+
+ public function test_create_index_unique_concurrently_if_not_exists() : void
+ {
+ $builder = create()->index('idx_users_email')
+ ->unique()
+ ->concurrently()
+ ->ifNotExists()
+ ->on('users')
+ ->columns('email');
+
+ $this->assertCreateIndexQuery(
+ $builder,
+ 'CREATE UNIQUE INDEX CONCURRENTLY IF NOT EXISTS idx_users_email ON users (email)'
+ );
+ }
+
+ public function test_create_index_with_btree_method() : void
+ {
+ $builder = create()->index('idx_users_email')
+ ->on('users')
+ ->using(index_method_btree())
+ ->columns('email');
+
+ $this->assertCreateIndexQuery(
+ $builder,
+ 'CREATE INDEX idx_users_email ON users USING btree (email)'
+ );
+ }
+
+ public function test_create_index_with_desc_order() : void
+ {
+ $builder = create()->index('idx_users_created_at')
+ ->on('users')
+ ->columns(index_col('created_at')->desc());
+
+ $this->assertCreateIndexQuery(
+ $builder,
+ 'CREATE INDEX idx_users_created_at ON users (created_at DESC)'
+ );
+ }
+
+ public function test_create_index_with_gin_method() : void
+ {
+ $builder = create()->index('idx_documents_content')
+ ->on('documents')
+ ->using(index_method_gin())
+ ->columns('content');
+
+ $this->assertCreateIndexQuery(
+ $builder,
+ 'CREATE INDEX idx_documents_content ON documents USING gin (content)'
+ );
+ }
+
+ public function test_create_index_with_hash_method() : void
+ {
+ $builder = create()->index('idx_users_email')
+ ->on('users')
+ ->using(index_method_hash())
+ ->columns('email');
+
+ $this->assertCreateIndexQuery(
+ $builder,
+ 'CREATE INDEX idx_users_email ON users USING hash (email)'
+ );
+ }
+
+ public function test_create_index_with_include() : void
+ {
+ $builder = create()->index('idx_users_email')
+ ->on('users')
+ ->columns('email')
+ ->include('name', 'created_at');
+
+ $this->assertCreateIndexQuery(
+ $builder,
+ 'CREATE INDEX idx_users_email ON users (email) INCLUDE (name, created_at)'
+ );
+ }
+
+ public function test_create_index_with_multiple_columns() : void
+ {
+ $builder = create()->index('idx_users_name_email')
+ ->on('users')
+ ->columns('name', 'email');
+
+ $this->assertCreateIndexQuery(
+ $builder,
+ 'CREATE INDEX idx_users_name_email ON users (name, email)'
+ );
+ }
+
+ public function test_create_index_with_nulls_first() : void
+ {
+ $builder = create()->index('idx_users_created_at')
+ ->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)'
+ );
+ }
+
+ public function test_create_index_with_nulls_last() : void
+ {
+ $builder = create()->index('idx_users_created_at')
+ ->on('users')
+ ->columns(index_col('created_at')->nullsLast());
+
+ $this->assertCreateIndexQuery(
+ $builder,
+ 'CREATE INDEX idx_users_created_at ON users (created_at NULLS LAST)'
+ );
+ }
+
+ public function test_create_index_with_nulls_not_distinct() : void
+ {
+ $builder = create()->index('idx_users_email')
+ ->unique()
+ ->on('users')
+ ->columns('email')
+ ->nullsNotDistinct();
+
+ $this->assertCreateIndexQuery(
+ $builder,
+ 'CREATE UNIQUE INDEX idx_users_email ON users (email) NULLS NOT DISTINCT'
+ );
+ }
+
+ public function test_create_index_with_on_only() : void
+ {
+ $builder = create()->index('idx_users_email')
+ ->onOnly('users')
+ ->columns('email');
+
+ $this->assertCreateIndexQuery(
+ $builder,
+ 'CREATE INDEX idx_users_email ON ONLY users (email)'
+ );
+ }
+
+ public function test_create_index_with_schema() : void
+ {
+ $builder = create()->index('idx_users_email')
+ ->on('users', 'public')
+ ->columns('email');
+
+ $this->assertCreateIndexQuery(
+ $builder,
+ 'CREATE INDEX idx_users_email ON public.users (email)'
+ );
+ }
+
+ public function test_create_index_with_tablespace() : void
+ {
+ $builder = create()->index('idx_users_email')
+ ->on('users')
+ ->columns('email')
+ ->tablespace('fast_storage');
+
+ $this->assertCreateIndexQuery(
+ $builder,
+ 'CREATE INDEX idx_users_email ON users (email) TABLESPACE fast_storage'
+ );
+ }
+
+ public function test_create_partial_index() : void
+ {
+ $builder = create()->index('idx_users_active_email')
+ ->on('users')
+ ->columns('email')
+ ->where(eq(col('active'), literal(true)));
+
+ $this->assertCreateIndexQuery(
+ $builder,
+ 'CREATE INDEX idx_users_active_email ON users (email) WHERE active = true'
+ );
+ }
+
+ public function test_drop_index_cascade() : void
+ {
+ $builder = drop()->index('idx_users_email')
+ ->cascade();
+
+ $this->assertDropIndexQuery(
+ $builder,
+ 'DROP INDEX idx_users_email CASCADE'
+ );
+ }
+
+ public function test_drop_index_concurrently() : void
+ {
+ $builder = drop()->index('idx_users_email')
+ ->concurrently();
+
+ $this->assertDropIndexQuery(
+ $builder,
+ 'DROP INDEX CONCURRENTLY idx_users_email'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ public function test_drop_index_if_exists_cascade() : void
+ {
+ $builder = drop()->index('idx_users_email')
+ ->ifExists()
+ ->cascade();
+
+ $this->assertDropIndexQuery(
+ $builder,
+ 'DROP INDEX IF EXISTS idx_users_email CASCADE'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ public function test_drop_index_restrict() : void
+ {
+ $builder = drop()->index('idx_users_email')
+ ->restrict();
+
+ $this->assertDropIndexQuery(
+ $builder,
+ 'DROP INDEX idx_users_email'
+ );
+ }
+
+ public function test_drop_index_simple() : void
+ {
+ $builder = drop()->index('idx_users_email');
+
+ $this->assertDropIndexQuery(
+ $builder,
+ 'DROP INDEX idx_users_email'
+ );
+ }
+
+ public function test_drop_index_with_schema() : void
+ {
+ $builder = drop()->index('public.idx_users_email');
+
+ $this->assertDropIndexQuery(
+ $builder,
+ 'DROP INDEX public.idx_users_email'
+ );
+ }
+
+ public function test_reindex_database() : void
+ {
+ $builder = reindex_database('mydb');
+
+ $this->assertReindexQuery(
+ $builder,
+ 'REINDEX DATABASE mydb'
+ );
+ }
+
+ public function test_reindex_index() : void
+ {
+ $builder = reindex_index('idx_users_email');
+
+ $this->assertReindexQuery(
+ $builder,
+ 'REINDEX INDEX idx_users_email'
+ );
+ }
+
+ public function test_reindex_index_concurrently() : void
+ {
+ $builder = reindex_index('idx_users_email')
+ ->concurrently();
+
+ $this->assertReindexQuery(
+ $builder,
+ 'REINDEX (CONCURRENTLY) INDEX idx_users_email'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ public function test_reindex_schema() : void
+ {
+ $builder = reindex_schema('public');
+
+ $this->assertReindexQuery(
+ $builder,
+ 'REINDEX SCHEMA public'
+ );
+ }
+
+ public function test_reindex_table() : void
+ {
+ $builder = reindex_table('users');
+
+ $this->assertReindexQuery(
+ $builder,
+ 'REINDEX TABLE users'
+ );
+ }
+
+ public function test_reindex_table_concurrently() : void
+ {
+ $builder = reindex_table('users')
+ ->concurrently();
+
+ $this->assertReindexQuery(
+ $builder,
+ 'REINDEX (CONCURRENTLY) TABLE users'
+ );
+ }
+
+ public function test_reindex_table_verbose() : void
+ {
+ $builder = reindex_table('users')
+ ->verbose();
+
+ $this->assertReindexQuery(
+ $builder,
+ 'REINDEX (VERBOSE) TABLE users'
+ );
+ }
+
+ public function test_reindex_table_with_schema() : void
+ {
+ $builder = reindex_table('public.users');
+
+ $this->assertReindexQuery(
+ $builder,
+ 'REINDEX TABLE public.users'
+ );
+ }
+}
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
new file mode 100644
index 000000000..f6b613f0a
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/InsertBuilderTest.php
@@ -0,0 +1,207 @@
+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
new file mode 100644
index 000000000..446dc01c2
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/MergeBuilderTest.php
@@ -0,0 +1,234 @@
+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/OperatorConditionTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/OperatorConditionTest.php
new file mode 100644
index 000000000..a49c6da35
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/OperatorConditionTest.php
@@ -0,0 +1,251 @@
+select(star())
+ ->from(table('products'))
+ ->where(array_contained_by(col('tags'), raw_expr("ARRAY['sale', 'featured', 'new']")));
+
+ $this->assertSelectQueryRoundTrip(
+ $query,
+ "SELECT * FROM products WHERE tags <@ ARRAY['sale', 'featured', 'new']"
+ );
+ }
+
+ public function test_array_contains() : void
+ {
+ $query = select()
+ ->select(star())
+ ->from(table('products'))
+ ->where(array_contains(col('tags'), raw_expr("ARRAY['sale']")));
+
+ $this->assertSelectQueryRoundTrip(
+ $query,
+ "SELECT * FROM products WHERE tags @> ARRAY['sale']"
+ );
+ }
+
+ public function test_array_overlap() : void
+ {
+ $query = select()
+ ->select(star())
+ ->from(table('products'))
+ ->where(array_overlap(col('tags'), raw_expr("ARRAY['sale', 'featured']")));
+
+ $this->assertSelectQueryRoundTrip(
+ $query,
+ "SELECT * FROM products WHERE tags && ARRAY['sale', 'featured']"
+ );
+ }
+
+ public function test_json_contained_by() : void
+ {
+ $query = select()
+ ->select(star())
+ ->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}\''
+ );
+ }
+
+ public function test_json_contains() : void
+ {
+ $query = select()
+ ->select(star())
+ ->from(table('products'))
+ ->where(json_contains(col('metadata'), literal('{"category": "electronics"}')));
+
+ $this->assertSelectQueryRoundTrip(
+ $query,
+ 'SELECT * FROM products WHERE metadata @> \'{"category": "electronics"}\''
+ );
+ }
+
+ public function test_json_exists() : void
+ {
+ $query = select()
+ ->select(star())
+ ->from(table('products'))
+ ->where(json_exists(col('metadata'), literal('category')));
+
+ $this->assertSelectQueryRoundTrip(
+ $query,
+ "SELECT * FROM products WHERE metadata ? 'category'"
+ );
+ }
+
+ 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']")));
+
+ $this->assertSelectQueryRoundTrip(
+ $query,
+ "SELECT * FROM products WHERE metadata ?& ARRAY['category', 'name']"
+ );
+ }
+
+ 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']")));
+
+ $this->assertSelectQueryRoundTrip(
+ $query,
+ "SELECT * FROM products WHERE metadata ?| ARRAY['category', 'name']"
+ );
+ }
+
+ public function test_json_get() : void
+ {
+ $query = select()
+ ->select(json_get(col('metadata'), literal('category'))->as('category'))
+ ->from(table('products'));
+
+ $this->assertSelectQueryRoundTrip(
+ $query,
+ "SELECT metadata -> 'category' AS category FROM products"
+ );
+ }
+
+ public function test_json_get_text() : void
+ {
+ $query = select()
+ ->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"
+ );
+ }
+
+ public function test_json_path() : void
+ {
+ $query = select()
+ ->select(json_path(col('metadata'), literal('{category,name}'))->as('nested'))
+ ->from(table('products'));
+
+ $this->assertSelectQueryRoundTrip(
+ $query,
+ "SELECT metadata #> '{category,name}' AS nested FROM products"
+ );
+ }
+
+ public function test_json_path_text() : void
+ {
+ $query = select()
+ ->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"
+ );
+ }
+
+ public function test_not_regex_imatch() : void
+ {
+ $query = select()
+ ->select(star())
+ ->from(table('users'))
+ ->where(not_regex_imatch(col('email'), literal('.*@spam\\.com')));
+
+ $this->assertSelectQueryRoundTrip(
+ $query,
+ "SELECT * FROM users WHERE email !~* E'.*@spam\\\\.com'"
+ );
+ }
+
+ public function test_not_regex_match() : void
+ {
+ $query = select()
+ ->select(star())
+ ->from(table('users'))
+ ->where(not_regex_match(col('email'), literal('.*@spam\\.com')));
+
+ $this->assertSelectQueryRoundTrip(
+ $query,
+ "SELECT * FROM users WHERE email !~ E'.*@spam\\\\.com'"
+ );
+ }
+
+ public function test_regex_imatch() : void
+ {
+ $query = select()
+ ->select(star())
+ ->from(table('users'))
+ ->where(regex_imatch(col('email'), literal('.*@gmail\\.com')));
+
+ $this->assertSelectQueryRoundTrip(
+ $query,
+ "SELECT * FROM users WHERE email ~* E'.*@gmail\\\\.com'"
+ );
+ }
+
+ public function test_regex_match() : void
+ {
+ $query = select()
+ ->select(star())
+ ->from(table('users'))
+ ->where(regex_match(col('email'), literal('.*@gmail\\.com')));
+
+ $this->assertSelectQueryRoundTrip(
+ $query,
+ "SELECT * FROM users WHERE email ~ E'.*@gmail\\\\.com'"
+ );
+ }
+
+ 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')")));
+
+ $this->assertSelectQueryRoundTrip(
+ $query,
+ "SELECT * FROM documents WHERE content @@ to_tsquery('english', 'hello & world')"
+ );
+ }
+}
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
new file mode 100644
index 000000000..f7c7d72ba
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/PGQueryTestCase.php
@@ -0,0 +1,20 @@
+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/RuleBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/RuleBuilderTest.php
new file mode 100644
index 000000000..973aa6097
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/RuleBuilderTest.php
@@ -0,0 +1,131 @@
+rule('audit_insert')
+ ->asOnInsert()
+ ->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')");
+ }
+
+ public function test_create_rule_do_instead_delete() : void
+ {
+ $builder = create()->rule('soft_delete')
+ ->asOnDelete()
+ ->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');
+ }
+
+ public function test_create_rule_do_nothing() : void
+ {
+ $builder = create()->rule('prevent_delete')
+ ->asOnDelete()
+ ->to('users')
+ ->doNothing();
+
+ $this->assertCreateRuleQuery($builder, 'CREATE RULE prevent_delete AS ON DELETE TO users DO NOTHING');
+ }
+
+ public function test_create_rule_on_select() : void
+ {
+ $builder = create()->rule('redirect_select')
+ ->asOnSelect()
+ ->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');
+ }
+
+ public function test_create_rule_on_update() : void
+ {
+ $builder = create()->rule('track_update')
+ ->asOnUpdate()
+ ->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')");
+ }
+
+ public function test_create_rule_or_replace() : void
+ {
+ $builder = create()->rule('prevent_delete')
+ ->orReplace()
+ ->asOnDelete()
+ ->to('users')
+ ->doNothing();
+
+ $this->assertCreateRuleQuery($builder, 'CREATE OR REPLACE RULE prevent_delete AS ON DELETE TO users DO NOTHING');
+ }
+
+ public function test_create_rule_with_schema() : void
+ {
+ $builder = create()->rule('prevent_delete')
+ ->asOnDelete()
+ ->to('public.users')
+ ->doNothing();
+
+ $this->assertCreateRuleQuery($builder, 'CREATE RULE prevent_delete AS ON DELETE TO public.users DO NOTHING');
+ }
+
+ public function test_create_rule_with_where_condition() : void
+ {
+ $builder = create()->rule('protect_admin')
+ ->asOnDelete()
+ ->to('users')
+ ->where('OLD.role = \'admin\'')
+ ->doNothing();
+
+ $this->assertCreateRuleQuery($builder, "CREATE RULE protect_admin AS ON DELETE TO users WHERE old.role = 'admin' DO NOTHING");
+ }
+
+ public function test_drop_rule() : void
+ {
+ $builder = drop()->rule('prevent_delete')
+ ->on('users');
+
+ $this->assertDropRuleQuery($builder, 'DROP RULE prevent_delete ON users');
+ }
+
+ public function test_drop_rule_cascade() : void
+ {
+ $builder = drop()->rule('prevent_delete')
+ ->on('users')
+ ->cascade();
+
+ $this->assertDropRuleQuery($builder, 'DROP RULE prevent_delete ON users CASCADE');
+ }
+
+ public function test_drop_rule_if_exists() : void
+ {
+ $builder = drop()->rule('prevent_delete')
+ ->ifExists()
+ ->on('users');
+
+ $this->assertDropRuleQuery($builder, 'DROP RULE IF EXISTS prevent_delete ON users');
+ }
+
+ public function test_drop_rule_with_schema() : void
+ {
+ $builder = drop()->rule('prevent_delete')
+ ->on('public.users')
+ ->restrict();
+
+ $this->assertDropRuleQuery($builder, 'DROP RULE prevent_delete ON public.users');
+ }
+}
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
new file mode 100644
index 000000000..974ec2e41
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/SchemaBuilderTest.php
@@ -0,0 +1,141 @@
+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
new file mode 100644
index 000000000..84fbdd446
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/SelectBuilderTest.php
@@ -0,0 +1,1226 @@
+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_selects(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'), '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::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'), 'integer')->as('price_int')
+ )
+ ->from(table('products'));
+
+ $this->assertSelectQueryRoundTrip(
+ $query,
+ 'SELECT id, price::"integer" 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'
+ );
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/SequenceBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/SequenceBuilderTest.php
new file mode 100644
index 000000000..4c9325075
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/SequenceBuilderTest.php
@@ -0,0 +1,603 @@
+sequence('user_id_seq')
+ ->asType('smallint');
+
+ $this->assertAlterSequenceQuery(
+ $builder,
+ 'ALTER SEQUENCE user_id_seq AS smallint'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ public function test_alter_sequence_cycle() : void
+ {
+ $builder = alter()->sequence('user_id_seq')
+ ->cycle();
+
+ $this->assertAlterSequenceQuery(
+ $builder,
+ 'ALTER SEQUENCE user_id_seq CYCLE'
+ );
+ }
+
+ public function test_alter_sequence_if_exists() : void
+ {
+ $builder = alter()->sequence('user_id_seq')
+ ->withIfExists()
+ ->incrementBy(10);
+
+ $this->assertAlterSequenceQuery(
+ $builder,
+ 'ALTER SEQUENCE IF EXISTS user_id_seq INCREMENT 10'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ public function test_alter_sequence_multiple_options() : void
+ {
+ $builder = alter()->sequence('user_id_seq')
+ ->incrementBy(10)
+ ->minValue(1)
+ ->maxValue(1000000)
+ ->cache(5);
+
+ $this->assertAlterSequenceQuery(
+ $builder,
+ 'ALTER SEQUENCE user_id_seq INCREMENT 10 MINVALUE 1 MAXVALUE 1000000 CACHE 5'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ 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"'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ public function test_alter_sequence_owner_to_if_exists() : void
+ {
+ $builder = alter()->sequence('user_id_seq')
+ ->withIfExists()
+ ->ownerTo('new_owner');
+
+ $this->assertAlterSequenceOwnerQuery(
+ $builder,
+ 'ALTER SEQUENCE IF EXISTS user_id_seq OWNER TO new_owner'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ public function test_alter_sequence_rename_to_if_exists() : void
+ {
+ $builder = alter()->sequence('old_seq')
+ ->withIfExists()
+ ->renameTo('new_seq');
+
+ $this->assertAlterSequenceRenameQuery(
+ $builder,
+ 'ALTER SEQUENCE IF EXISTS old_seq RENAME TO new_seq'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ public function test_alter_sequence_restart() : void
+ {
+ $builder = alter()->sequence('user_id_seq')
+ ->restart();
+
+ $this->assertAlterSequenceQuery(
+ $builder,
+ 'ALTER SEQUENCE user_id_seq RESTART'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ public function test_alter_sequence_set_logged_if_exists() : void
+ {
+ $builder = alter()->sequence('user_id_seq')
+ ->withIfExists()
+ ->setLogged();
+
+ $this->assertAlterSequenceLoggingQuery(
+ $builder,
+ 'ALTER SEQUENCE IF EXISTS user_id_seq SET LOGGED'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ public function test_alter_sequence_set_schema_if_exists() : void
+ {
+ $builder = alter()->sequence('user_id_seq')
+ ->withIfExists()
+ ->setSchema('new_schema');
+
+ $this->assertAlterSequenceSchemaQuery(
+ $builder,
+ 'ALTER SEQUENCE IF EXISTS user_id_seq SET SCHEMA new_schema'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ public function test_create_sequence_simple() : void
+ {
+ $builder = create()->sequence('user_id_seq');
+
+ $this->assertCreateSequenceQuery(
+ $builder,
+ 'CREATE SEQUENCE user_id_seq'
+ );
+ }
+
+ public function test_create_sequence_with_all_options() : void
+ {
+ $builder = create()->sequence('user_id_seq')
+ ->asType('bigint')
+ ->startWith(1)
+ ->incrementBy(1)
+ ->minValue(1)
+ ->maxValue(1000000)
+ ->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'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ public function test_create_sequence_with_cycle() : void
+ {
+ $builder = create()->sequence('user_id_seq')
+ ->cycle();
+
+ $this->assertCreateSequenceQuery(
+ $builder,
+ 'CREATE SEQUENCE user_id_seq CYCLE'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ 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"'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ public function test_create_sequence_with_schema() : void
+ {
+ $builder = create()->sequence('user_id_seq', 'public');
+
+ $this->assertCreateSequenceQuery(
+ $builder,
+ 'CREATE SEQUENCE public.user_id_seq'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ public function test_create_temporary_sequence() : void
+ {
+ $builder = create()->sequence('temp_seq')->temporary();
+
+ $this->assertCreateSequenceQuery(
+ $builder,
+ 'CREATE TEMPORARY SEQUENCE temp_seq'
+ );
+ }
+
+ public function test_create_unlogged_sequence() : void
+ {
+ $builder = create()->sequence('fast_seq')->unlogged();
+
+ $this->assertCreateSequenceQuery(
+ $builder,
+ 'CREATE UNLOGGED SEQUENCE fast_seq'
+ );
+ }
+
+ public function test_drop_sequence_cascade() : void
+ {
+ $builder = drop()->sequence('user_id_seq')
+ ->cascade();
+
+ $this->assertDropSequenceQuery(
+ $builder,
+ 'DROP SEQUENCE user_id_seq CASCADE'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ public function test_drop_sequence_if_exists_cascade() : void
+ {
+ $builder = drop()->sequence('user_id_seq')
+ ->ifExists()
+ ->cascade();
+
+ $this->assertDropSequenceQuery(
+ $builder,
+ 'DROP SEQUENCE IF EXISTS user_id_seq CASCADE'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ public function test_drop_sequence_restrict() : void
+ {
+ $builder = drop()->sequence('user_id_seq')
+ ->restrict();
+
+ $this->assertDropSequenceQuery(
+ $builder,
+ 'DROP SEQUENCE user_id_seq'
+ );
+ }
+
+ public function test_drop_sequence_simple() : void
+ {
+ $builder = drop()->sequence('user_id_seq');
+
+ $this->assertDropSequenceQuery(
+ $builder,
+ 'DROP SEQUENCE user_id_seq'
+ );
+ }
+
+ public function test_drop_sequence_with_schema() : void
+ {
+ $builder = drop()->sequence('public.user_id_seq');
+
+ $this->assertDropSequenceQuery(
+ $builder,
+ 'DROP SEQUENCE public.user_id_seq'
+ );
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/TableBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/TableBuilderTest.php
new file mode 100644
index 000000000..b2cc7ef90
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/TableBuilderTest.php
@@ -0,0 +1,576 @@
+table('users')
+ ->addColumn(column('email', sql_type_varchar(255))->notNull());
+
+ $this->assertAlterTableQuery(
+ $builder,
+ 'ALTER TABLE users ADD COLUMN email varchar(255) NOT NULL'
+ );
+ }
+
+ 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)'
+ );
+ }
+
+ public function test_alter_table_alter_column_set_default() : void
+ {
+ $builder = alter()->table('users')
+ ->alterColumnSetDefault('status', "'active'");
+
+ $this->assertAlterTableQuery(
+ $builder,
+ "ALTER TABLE users ALTER COLUMN status SET DEFAULT 'active'"
+ );
+ }
+
+ 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'
+ );
+ }
+
+ public function test_alter_table_alter_column_type() : void
+ {
+ $builder = alter()->table('users')
+ ->alterColumnType('name', sql_type_text());
+
+ $this->assertAlterTableQuery(
+ $builder,
+ 'ALTER TABLE users ALTER COLUMN name TYPE pg_catalog.text'
+ );
+ }
+
+ public function test_alter_table_drop_column() : void
+ {
+ $builder = alter()->table('users')
+ ->dropColumn('temp_column');
+
+ $this->assertAlterTableQuery(
+ $builder,
+ 'ALTER TABLE users DROP temp_column'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ public function test_alter_table_if_exists() : void
+ {
+ $builder = alter()->table('users')
+ ->ifExists()
+ ->addColumn(column('email', sql_type_varchar(255)));
+
+ $this->assertAlterTableQuery(
+ $builder,
+ 'ALTER TABLE IF EXISTS users ADD COLUMN email varchar(255)'
+ );
+ }
+
+ public function test_alter_table_multiple_operations() : void
+ {
+ $builder = alter()->table('users')
+ ->addColumn(column('phone', sql_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'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ public function test_alter_table_rename_column_if_exists() : void
+ {
+ $builder = alter()->table('users')
+ ->ifExists()
+ ->renameColumn('old_name', 'new_name');
+
+ $this->assertRenameQuery(
+ $builder,
+ 'ALTER TABLE IF EXISTS users RENAME COLUMN old_name TO new_name'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ public function test_alter_table_set_schema() : void
+ {
+ $builder = alter()->table('users')
+ ->setSchema('archive');
+
+ $this->assertAlterObjectSchemaQuery(
+ $builder,
+ 'ALTER TABLE users SET SCHEMA archive'
+ );
+ }
+
+ public function test_alter_table_set_schema_if_exists() : void
+ {
+ $builder = alter()->table('users')
+ ->ifExists()
+ ->setSchema('archive');
+
+ $this->assertAlterObjectSchemaQuery(
+ $builder,
+ 'ALTER TABLE IF EXISTS users SET SCHEMA archive'
+ );
+ }
+
+ public function test_alter_table_with_schema() : void
+ {
+ $builder = alter()->table('users', 'public')
+ ->addColumn(column('email', sql_type_varchar(255)));
+
+ $this->assertAlterTableQuery(
+ $builder,
+ 'ALTER TABLE public.users ADD COLUMN email varchar(255)'
+ );
+ }
+
+ public function test_create_table_as_if_not_exists() : void
+ {
+ $selectBuilder = select()
+ ->select(col('id'), col('name'))
+ ->from(table('users'));
+
+ $builder = create()->tableAs('users_backup', $selectBuilder)
+ ->ifNotExists();
+
+ $this->assertCreateTableAsQuery(
+ $builder,
+ 'CREATE TABLE IF NOT EXISTS users_backup AS SELECT id, name FROM users'
+ );
+ }
+
+ public function test_create_table_as_with_column_names() : void
+ {
+ $selectBuilder = select()
+ ->select(col('id'), col('name'))
+ ->from(table('users'));
+
+ $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'
+ );
+ }
+
+ public function test_create_table_as_with_no_data() : void
+ {
+ $selectBuilder = select()
+ ->select(col('id'), col('name'))
+ ->from(table('users'));
+
+ $builder = create()->tableAs('users_backup', $selectBuilder)
+ ->withNoData();
+
+ $this->assertCreateTableAsQuery(
+ $builder,
+ 'CREATE TABLE users_backup AS SELECT id, name FROM users WITH NO DATA'
+ );
+ }
+
+ public function test_create_table_if_not_exists() : void
+ {
+ $builder = create()->table('users')
+ ->ifNotExists()
+ ->column(column('id', sql_type_serial())->primaryKey())
+ ->column(column('name', sql_type_varchar(100)));
+
+ $this->assertCreateTableQuery(
+ $builder,
+ 'CREATE TABLE IF NOT EXISTS users (id serial PRIMARY KEY, name varchar(100))'
+ );
+ }
+
+ public function test_create_table_simple() : void
+ {
+ $builder = create()->table('users')
+ ->column(column('id', sql_type_serial())->primaryKey())
+ ->column(column('name', sql_type_varchar(100))->notNull());
+
+ $this->assertCreateTableQuery(
+ $builder,
+ 'CREATE TABLE users (id serial PRIMARY KEY, name varchar(100) NOT NULL)'
+ );
+ }
+
+ public function test_create_table_with_check_constraint() : void
+ {
+ $builder = create()->table('products')
+ ->column(column('id', sql_type_serial())->primaryKey())
+ ->column(column('price', sql_type_integer()))
+ ->constraint(check_constraint('price > 0')->name('positive_price'));
+
+ $this->assertCreateTableQuery(
+ $builder,
+ 'CREATE TABLE products (id serial PRIMARY KEY, price int, CONSTRAINT positive_price CHECK (price > 0))'
+ );
+ }
+
+ public function test_create_table_with_column_default() : void
+ {
+ $builder = create()->table('users')
+ ->column(column('id', sql_type_serial())->primaryKey())
+ ->column(column('active', sql_type_boolean())->default(true));
+
+ $this->assertCreateTableQuery(
+ $builder,
+ 'CREATE TABLE users (id serial PRIMARY KEY, active boolean DEFAULT true)'
+ );
+ }
+
+ public function test_create_table_with_composite_primary_key() : void
+ {
+ $builder = create()->table('order_items')
+ ->column(column('order_id', sql_type_integer())->notNull())
+ ->column(column('product_id', sql_type_integer())->notNull())
+ ->column(column('quantity', sql_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))'
+ );
+ }
+
+ public function test_create_table_with_foreign_key() : void
+ {
+ $builder = create()->table('orders')
+ ->column(column('id', sql_type_serial())->primaryKey())
+ ->column(column('user_id', sql_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)'
+ );
+ }
+
+ public function test_create_table_with_foreign_key_set_null() : void
+ {
+ $builder = create()->table('comments')
+ ->column(column('id', sql_type_serial())->primaryKey())
+ ->column(column('user_id', sql_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)'
+ );
+ }
+
+ public function test_create_table_with_schema() : void
+ {
+ $builder = create()->table('users', 'public')
+ ->column(column('id', sql_type_serial())->primaryKey());
+
+ $this->assertCreateTableQuery(
+ $builder,
+ 'CREATE TABLE public.users (id serial PRIMARY KEY)'
+ );
+ }
+
+ public function test_create_table_with_timestamp() : void
+ {
+ $builder = create()->table('audit_log')
+ ->column(column('id', sql_type_serial())->primaryKey())
+ ->column(column('created_at', sql_type_timestamp())->notNull())
+ ->column(column('updated_at', sql_type_timestamp()));
+
+ $this->assertCreateTableQuery(
+ $builder,
+ 'CREATE TABLE audit_log (id serial PRIMARY KEY, created_at timestamp NOT NULL, updated_at timestamp)'
+ );
+ }
+
+ public function test_create_table_with_unique_constraint() : void
+ {
+ $builder = create()->table('users')
+ ->column(column('id', sql_type_serial())->primaryKey())
+ ->column(column('email', sql_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))'
+ );
+ }
+
+ public function test_drop_table_cascade() : void
+ {
+ $builder = drop()->table('users')
+ ->cascade();
+
+ $this->assertDropTableQuery(
+ $builder,
+ 'DROP TABLE users CASCADE'
+ );
+ }
+
+ public function test_drop_table_if_exists() : void
+ {
+ $builder = drop()->table('users')
+ ->ifExists();
+
+ $this->assertDropTableQuery(
+ $builder,
+ 'DROP TABLE IF EXISTS users'
+ );
+ }
+
+ public function test_drop_table_if_exists_cascade() : void
+ {
+ $builder = drop()->table('users')
+ ->ifExists()
+ ->cascade();
+
+ $this->assertDropTableQuery(
+ $builder,
+ 'DROP TABLE IF EXISTS users CASCADE'
+ );
+ }
+
+ public function test_drop_table_multiple_tables() : void
+ {
+ $builder = drop()->table('users', 'orders', 'products');
+
+ $this->assertDropTableQuery(
+ $builder,
+ 'DROP TABLE users, orders, products'
+ );
+ }
+
+ public function test_drop_table_restrict() : void
+ {
+ $builder = drop()->table('users')
+ ->restrict();
+
+ $this->assertDropTableQuery(
+ $builder,
+ 'DROP TABLE users'
+ );
+ }
+
+ public function test_drop_table_simple() : void
+ {
+ $builder = drop()->table('users');
+
+ $this->assertDropTableQuery(
+ $builder,
+ 'DROP TABLE users'
+ );
+ }
+
+ public function test_drop_table_with_schema() : void
+ {
+ $builder = drop()->table('public.users');
+
+ $this->assertDropTableQuery(
+ $builder,
+ 'DROP TABLE public.users'
+ );
+ }
+
+ public function test_simple_create_table_as() : void
+ {
+ $selectBuilder = select()
+ ->select(col('id'), col('name'))
+ ->from(table('users'));
+
+ $builder = create()->tableAs('users_backup', $selectBuilder);
+
+ $this->assertCreateTableAsQuery(
+ $builder,
+ 'CREATE TABLE users_backup AS SELECT id, name FROM users'
+ );
+ }
+
+ public function test_truncate_cascade() : void
+ {
+ $builder = truncate_table('users')
+ ->cascade();
+
+ $this->assertTruncateQuery(
+ $builder,
+ 'TRUNCATE users CASCADE'
+ );
+ }
+
+ public function test_truncate_multiple_tables() : void
+ {
+ $builder = truncate_table('users', 'orders', 'products');
+
+ $this->assertTruncateQuery(
+ $builder,
+ 'TRUNCATE users, orders, products'
+ );
+ }
+
+ public function test_truncate_restart_identity() : void
+ {
+ $builder = truncate_table('users')
+ ->restartIdentity();
+
+ $this->assertTruncateQuery(
+ $builder,
+ 'TRUNCATE users RESTART IDENTITY'
+ );
+ }
+
+ public function test_truncate_restart_identity_cascade() : void
+ {
+ $builder = truncate_table('users')
+ ->restartIdentity()
+ ->cascade();
+
+ $this->assertTruncateQuery(
+ $builder,
+ 'TRUNCATE users RESTART IDENTITY CASCADE'
+ );
+ }
+
+ public function test_truncate_restrict() : void
+ {
+ $builder = truncate_table('users')
+ ->restrict();
+
+ $this->assertTruncateQuery(
+ $builder,
+ 'TRUNCATE users'
+ );
+ }
+
+ public function test_truncate_simple() : void
+ {
+ $builder = truncate_table('users');
+
+ $this->assertTruncateQuery(
+ $builder,
+ 'TRUNCATE users'
+ );
+ }
+
+ public function test_truncate_with_schema() : void
+ {
+ $builder = truncate_table('public.users');
+
+ $this->assertTruncateQuery(
+ $builder,
+ 'TRUNCATE public.users'
+ );
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/TransactionBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/TransactionBuilderTest.php
new file mode 100644
index 000000000..e6966a291
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/TransactionBuilderTest.php
@@ -0,0 +1,330 @@
+assertTransactionQueryEquals(
+ $query,
+ 'BEGIN'
+ );
+ }
+
+ public function test_begin_with_all_options() : void
+ {
+ $query = begin()
+ ->isolationLevel(IsolationLevel::SERIALIZABLE)
+ ->readOnly()
+ ->deferrable();
+
+ $this->assertTransactionQueryEquals(
+ $query,
+ 'BEGIN ISOLATION LEVEL SERIALIZABLE, READ ONLY, DEFERRABLE'
+ );
+ }
+
+ public function test_begin_with_deferrable() : void
+ {
+ $query = begin()
+ ->deferrable();
+
+ $this->assertTransactionQueryEquals(
+ $query,
+ 'BEGIN DEFERRABLE'
+ );
+ }
+
+ public function test_begin_with_isolation_level_read_committed() : void
+ {
+ $query = begin()
+ ->isolationLevel(IsolationLevel::READ_COMMITTED);
+
+ $this->assertTransactionQueryEquals(
+ $query,
+ 'BEGIN ISOLATION LEVEL READ COMMITTED'
+ );
+ }
+
+ public function test_begin_with_isolation_level_read_uncommitted() : void
+ {
+ $query = begin()
+ ->isolationLevel(IsolationLevel::READ_UNCOMMITTED);
+
+ $this->assertTransactionQueryEquals(
+ $query,
+ 'BEGIN ISOLATION LEVEL READ UNCOMMITTED'
+ );
+ }
+
+ public function test_begin_with_isolation_level_repeatable_read() : void
+ {
+ $query = begin()
+ ->isolationLevel(IsolationLevel::REPEATABLE_READ);
+
+ $this->assertTransactionQueryEquals(
+ $query,
+ 'BEGIN ISOLATION LEVEL REPEATABLE READ'
+ );
+ }
+
+ public function test_begin_with_isolation_level_serializable() : void
+ {
+ $query = begin()
+ ->isolationLevel(IsolationLevel::SERIALIZABLE);
+
+ $this->assertTransactionQueryEquals(
+ $query,
+ 'BEGIN ISOLATION LEVEL SERIALIZABLE'
+ );
+ }
+
+ public function test_begin_with_not_deferrable() : void
+ {
+ $query = begin()
+ ->notDeferrable();
+
+ $this->assertTransactionQueryEquals(
+ $query,
+ 'BEGIN NOT DEFERRABLE'
+ );
+ }
+
+ public function test_begin_with_read_only() : void
+ {
+ $query = begin()
+ ->readOnly();
+
+ $this->assertTransactionQueryEquals(
+ $query,
+ 'BEGIN READ ONLY'
+ );
+ }
+
+ public function test_begin_with_read_write() : void
+ {
+ $query = begin()
+ ->readWrite();
+
+ $this->assertTransactionQueryEquals(
+ $query,
+ 'BEGIN READ WRITE'
+ );
+ }
+
+ public function test_commit_and_chain() : void
+ {
+ $query = commit()
+ ->andChain();
+
+ $this->assertTransactionQueryEquals(
+ $query,
+ 'COMMIT AND CHAIN'
+ );
+ }
+
+ // -------------------------------------------------------------------
+ // COMMIT
+ // -------------------------------------------------------------------
+
+ public function test_commit_basic() : void
+ {
+ $query = commit();
+
+ $this->assertTransactionQueryEquals(
+ $query,
+ 'COMMIT'
+ );
+ }
+
+ public function test_commit_prepared() : void
+ {
+ $query = commit_prepared('my_transaction');
+
+ $this->assertTransactionQueryEquals(
+ $query,
+ "COMMIT PREPARED 'my_transaction'"
+ );
+ }
+
+ public function test_prepare_transaction() : void
+ {
+ $query = prepare_transaction('my_transaction');
+
+ $this->assertTransactionQueryEquals(
+ $query,
+ "PREPARE TRANSACTION 'my_transaction'"
+ );
+ }
+
+ public function test_release_savepoint() : void
+ {
+ $query = release_savepoint('my_savepoint');
+
+ $this->assertTransactionQueryEquals(
+ $query,
+ 'RELEASE my_savepoint'
+ );
+ }
+
+ public function test_rollback_and_chain() : void
+ {
+ $query = rollback()
+ ->andChain();
+
+ $this->assertTransactionQueryEquals(
+ $query,
+ 'ROLLBACK AND CHAIN'
+ );
+ }
+
+ public function test_rollback_basic() : void
+ {
+ $query = rollback();
+
+ $this->assertTransactionQueryEquals(
+ $query,
+ 'ROLLBACK'
+ );
+ }
+
+ public function test_rollback_prepared() : void
+ {
+ $query = rollback_prepared('my_transaction');
+
+ $this->assertTransactionQueryEquals(
+ $query,
+ "ROLLBACK PREPARED 'my_transaction'"
+ );
+ }
+
+ public function test_rollback_to_savepoint() : void
+ {
+ $query = rollback()
+ ->toSavepoint('my_savepoint');
+
+ $this->assertTransactionQueryEquals(
+ $query,
+ 'ROLLBACK TO SAVEPOINT my_savepoint'
+ );
+ }
+
+ public function test_savepoint() : void
+ {
+ $query = savepoint('my_savepoint');
+
+ $this->assertTransactionQueryEquals(
+ $query,
+ 'SAVEPOINT my_savepoint'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ public function test_set_transaction_deferrable() : void
+ {
+ $query = set_transaction()
+ ->deferrable();
+
+ $this->assertSetTransactionQueryEquals(
+ $query,
+ 'SET TRANSACTION DEFERRABLE'
+ );
+ }
+
+ public function test_set_transaction_isolation_level() : void
+ {
+ $query = set_transaction()
+ ->isolationLevel(IsolationLevel::SERIALIZABLE);
+
+ $this->assertSetTransactionQueryEquals(
+ $query,
+ 'SET TRANSACTION ISOLATION LEVEL SERIALIZABLE'
+ );
+ }
+
+ public function test_set_transaction_read_only() : void
+ {
+ $query = set_transaction()
+ ->readOnly();
+
+ $this->assertSetTransactionQueryEquals(
+ $query,
+ 'SET TRANSACTION READ ONLY'
+ );
+ }
+
+ public function test_set_transaction_read_write() : void
+ {
+ $query = set_transaction()
+ ->readWrite();
+
+ $this->assertSetTransactionQueryEquals(
+ $query,
+ 'SET TRANSACTION READ WRITE'
+ );
+ }
+
+ public function test_set_transaction_with_multiple_options() : void
+ {
+ $query = set_transaction()
+ ->isolationLevel(IsolationLevel::SERIALIZABLE)
+ ->readOnly()
+ ->deferrable();
+
+ $this->assertSetTransactionQueryEquals(
+ $query,
+ 'SET TRANSACTION ISOLATION LEVEL SERIALIZABLE, READ ONLY, DEFERRABLE'
+ );
+ }
+
+ public function test_start_transaction_basic() : void
+ {
+ $query = begin();
+
+ $this->assertTransactionQueryEquals(
+ $query,
+ 'BEGIN'
+ );
+ }
+
+ public function test_transaction_snapshot() : void
+ {
+ $query = transaction_snapshot('00000003-0000001A-1');
+
+ $this->assertSetTransactionQueryEquals(
+ $query,
+ "SET TRANSACTION SNAPSHOT '00000003-0000001A-1'"
+ );
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/TriggerBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/TriggerBuilderTest.php
new file mode 100644
index 000000000..3a60dc745
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/TriggerBuilderTest.php
@@ -0,0 +1,243 @@
+table('users')
+ ->disableTrigger('audit_trigger');
+
+ $this->assertAlterTableQuery($builder, 'ALTER TABLE users DISABLE TRIGGER audit_trigger');
+ }
+
+ public function test_alter_table_disable_trigger_all() : void
+ {
+ $builder = alter()->table('users')
+ ->disableTriggerAll();
+
+ $this->assertAlterTableQuery($builder, 'ALTER TABLE users DISABLE TRIGGER ALL');
+ }
+
+ public function test_alter_table_disable_trigger_user() : void
+ {
+ $builder = alter()->table('users')
+ ->disableTriggerUser();
+
+ $this->assertAlterTableQuery($builder, 'ALTER TABLE users DISABLE TRIGGER USER');
+ }
+
+ 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');
+ }
+
+ public function test_alter_table_enable_trigger_all() : void
+ {
+ $builder = alter()->table('users')
+ ->enableTriggerAll();
+
+ $this->assertAlterTableQuery($builder, 'ALTER TABLE users ENABLE TRIGGER ALL');
+ }
+
+ 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');
+ }
+
+ 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');
+ }
+
+ public function test_alter_table_enable_trigger_user() : void
+ {
+ $builder = alter()->table('users')
+ ->enableTriggerUser();
+
+ $this->assertAlterTableQuery($builder, 'ALTER TABLE users ENABLE TRIGGER USER');
+ }
+
+ public function test_alter_trigger_depends_on_extension() : void
+ {
+ $builder = alter()->trigger('my_trigger')
+ ->on('users')
+ ->dependsOnExtension('my_extension');
+
+ $this->assertAlterTriggerDependsQuery($builder, 'ALTER TRIGGER my_trigger ON users DEPENDS ON EXTENSION my_extension');
+ }
+
+ public function test_alter_trigger_no_depends_on_extension() : void
+ {
+ $builder = alter()->trigger('my_trigger')
+ ->on('users')
+ ->noDependsOnExtension('my_extension');
+
+ $this->assertAlterTriggerDependsQuery($builder, 'ALTER TRIGGER my_trigger ON users NO DEPENDS ON EXTENSION my_extension');
+ }
+
+ public function test_alter_trigger_rename() : void
+ {
+ $builder = alter()->trigger('old_trigger')
+ ->on('users')
+ ->renameTo('new_trigger');
+
+ $this->assertAlterTriggerRenameQuery($builder, 'ALTER TRIGGER old_trigger ON users RENAME TO new_trigger');
+ }
+
+ public function test_create_trigger_after_insert() : void
+ {
+ $builder = create()->trigger('audit_trigger')
+ ->after(TriggerEvent::INSERT)
+ ->on('users')
+ ->execute('audit_function');
+
+ $this->assertCreateTriggerQuery($builder, 'CREATE TRIGGER audit_trigger AFTER INSERT ON users EXECUTE FUNCTION audit_function()');
+ }
+
+ public function test_create_trigger_after_insert_or_update() : void
+ {
+ $builder = create()->trigger('audit_trigger')
+ ->after(TriggerEvent::INSERT, TriggerEvent::UPDATE)
+ ->on('users')
+ ->forEachRow()
+ ->execute('audit_function');
+
+ $this->assertCreateTriggerQuery($builder, 'CREATE TRIGGER audit_trigger AFTER INSERT OR UPDATE ON users FOR EACH ROW EXECUTE FUNCTION audit_function()');
+ }
+
+ public function test_create_trigger_after_update_of_columns() : void
+ {
+ $builder = create()->trigger('track_changes')
+ ->afterUpdateOf('status', 'updated_at')
+ ->on('orders')
+ ->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()');
+ }
+
+ public function test_create_trigger_before_delete_with_when() : void
+ {
+ $builder = create()->trigger('prevent_delete')
+ ->before(TriggerEvent::DELETE)
+ ->on('users')
+ ->forEachRow()
+ ->when(raw_cond('OLD.protected = 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()');
+ }
+
+ public function test_create_trigger_constraint_deferrable() : void
+ {
+ $builder = create()->trigger('fk_trigger')
+ ->constraint()
+ ->after(TriggerEvent::INSERT)
+ ->on('orders')
+ ->from('users')
+ ->deferrable()
+ ->initiallyDeferred()
+ ->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()');
+ }
+
+ public function test_create_trigger_instead_of_on_view() : void
+ {
+ $builder = create()->trigger('view_insert')
+ ->insteadOf(TriggerEvent::INSERT)
+ ->on('users_view')
+ ->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()');
+ }
+
+ public function test_create_trigger_or_replace() : void
+ {
+ $builder = create()->trigger('audit_trigger')
+ ->orReplace()
+ ->after(TriggerEvent::INSERT)
+ ->on('users')
+ ->execute('audit_function');
+
+ $this->assertCreateTriggerQuery($builder, 'CREATE OR REPLACE TRIGGER audit_trigger AFTER INSERT ON users EXECUTE FUNCTION audit_function()');
+ }
+
+ public function test_create_trigger_with_referencing() : void
+ {
+ $builder = create()->trigger('statement_trigger')
+ ->after(TriggerEvent::INSERT)
+ ->on('users')
+ ->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()');
+ }
+
+ public function test_create_trigger_with_schema() : void
+ {
+ $builder = create()->trigger('audit_trigger')
+ ->after(TriggerEvent::INSERT)
+ ->on('public.users')
+ ->execute('audit_function');
+
+ $this->assertCreateTriggerQuery($builder, 'CREATE TRIGGER audit_trigger AFTER INSERT ON public.users EXECUTE FUNCTION audit_function()');
+ }
+
+ public function test_drop_trigger() : void
+ {
+ $builder = drop()->trigger('audit_trigger')
+ ->on('users');
+
+ $this->assertDropTriggerQuery($builder, 'DROP TRIGGER audit_trigger ON users');
+ }
+
+ public function test_drop_trigger_cascade() : void
+ {
+ $builder = drop()->trigger('audit_trigger')
+ ->on('users')
+ ->cascade();
+
+ $this->assertDropTriggerQuery($builder, 'DROP TRIGGER audit_trigger ON users CASCADE');
+ }
+
+ public function test_drop_trigger_if_exists() : void
+ {
+ $builder = drop()->trigger('audit_trigger')
+ ->ifExists()
+ ->on('users');
+
+ $this->assertDropTriggerQuery($builder, 'DROP TRIGGER IF EXISTS audit_trigger ON users');
+ }
+
+ public function test_drop_trigger_with_schema() : void
+ {
+ $builder = drop()->trigger('audit_trigger')
+ ->on('public.users')
+ ->restrict();
+
+ $this->assertDropTriggerQuery($builder, 'DROP TRIGGER audit_trigger ON public.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
new file mode 100644
index 000000000..0f8d5e24e
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/TypeBuilderTest.php
@@ -0,0 +1,240 @@
+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', sql_type_text()),
+ type_attr('city', sql_type_text()),
+ type_attr('zip', sql_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', sql_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', sql_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
new file mode 100644
index 000000000..2cf4303b8
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/UpdateBuilderTest.php
@@ -0,0 +1,161 @@
+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/UtilityBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/UtilityBuilderTest.php
new file mode 100644
index 000000000..cbb5c2785
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/UtilityBuilderTest.php
@@ -0,0 +1,647 @@
+assertAnalyzeQuery(
+ $builder,
+ 'ANALYZE'
+ );
+ }
+
+ public function test_analyze_multiple_tables() : void
+ {
+ $builder = analyze()->tables('users', 'orders', 'products');
+
+ $this->assertAnalyzeQuery(
+ $builder,
+ 'ANALYZE users, orders, products'
+ );
+ }
+
+ public function test_analyze_single_table() : void
+ {
+ $builder = analyze()->table('users');
+
+ $this->assertAnalyzeQuery(
+ $builder,
+ 'ANALYZE users'
+ );
+ }
+
+ public function test_analyze_skip_locked() : void
+ {
+ $builder = analyze()->skipLocked()->table('users');
+
+ $this->assertAnalyzeQuery(
+ $builder,
+ 'ANALYZE (SKIP_LOCKED) users'
+ );
+ }
+
+ public function test_analyze_table_with_columns() : void
+ {
+ $builder = analyze()->table('users', 'email', 'name');
+
+ $this->assertAnalyzeQuery(
+ $builder,
+ 'ANALYZE users(email, name)'
+ );
+ }
+
+ public function test_analyze_verbose() : void
+ {
+ $builder = analyze()->verbose()->table('users');
+
+ $this->assertAnalyzeQuery(
+ $builder,
+ 'ANALYZE (VERBOSE) users'
+ );
+ }
+
+ public function test_cluster_all_tables() : void
+ {
+ $builder = cluster();
+
+ $this->assertClusterQuery(
+ $builder,
+ 'CLUSTER'
+ );
+ }
+
+ public function test_cluster_single_table() : void
+ {
+ $builder = cluster()->table('users');
+
+ $this->assertClusterQuery(
+ $builder,
+ 'CLUSTER users'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ public function test_cluster_table_with_schema() : void
+ {
+ $builder = cluster()->table('public.users');
+
+ $this->assertClusterQuery(
+ $builder,
+ 'CLUSTER public.users'
+ );
+ }
+
+ public function test_cluster_verbose() : void
+ {
+ $builder = cluster()->verbose()->table('users');
+
+ $this->assertClusterQuery(
+ $builder,
+ 'CLUSTER (VERBOSE) users'
+ );
+ }
+
+ 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'"
+ );
+ }
+
+ 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'"
+ );
+ }
+
+ 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'"
+ );
+ }
+
+ 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'"
+ );
+ }
+
+ public function test_comment_remove() : void
+ {
+ $builder = comment(CommentTarget::TABLE, 'users')->isNull();
+
+ $this->assertCommentQuery(
+ $builder,
+ 'COMMENT ON TABLE users IS NULL'
+ );
+ }
+
+ public function test_discard_all() : void
+ {
+ $builder = discard(DiscardType::ALL);
+
+ $this->assertDiscardQuery(
+ $builder,
+ 'DISCARD ALL'
+ );
+ }
+
+ public function test_discard_plans() : void
+ {
+ $builder = discard(DiscardType::PLANS);
+
+ $this->assertDiscardQuery(
+ $builder,
+ 'DISCARD PLANS'
+ );
+ }
+
+ public function test_discard_sequences() : void
+ {
+ $builder = discard(DiscardType::SEQUENCES);
+
+ $this->assertDiscardQuery(
+ $builder,
+ 'DISCARD SEQUENCES'
+ );
+ }
+
+ public function test_discard_temp() : void
+ {
+ $builder = discard(DiscardType::TEMP);
+
+ $this->assertDiscardQuery(
+ $builder,
+ 'DISCARD TEMP'
+ );
+ }
+
+ public function test_explain_analyze() : void
+ {
+ $builder = explain(select(star())->from(table('users')))->analyze();
+
+ $this->assertExplainQuery(
+ $builder,
+ 'EXPLAIN (ANALYZE) SELECT * FROM users'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ public function test_explain_full_options() : void
+ {
+ $builder = explain(select(star())->from(table('users')))
+ ->analyze()
+ ->verbose()
+ ->buffers(true)
+ ->timing(true)
+ ->format(ExplainFormat::JSON);
+
+ $this->assertExplainQuery(
+ $builder,
+ 'EXPLAIN (ANALYZE, VERBOSE, BUFFERS 1, TIMING 1, FORMAT "json") SELECT * FROM users'
+ );
+ }
+
+ public function test_explain_select() : void
+ {
+ $builder = explain(select(star())->from(table('users')));
+
+ $this->assertExplainQuery(
+ $builder,
+ 'EXPLAIN SELECT * FROM users'
+ );
+ }
+
+ public function test_explain_verbose() : void
+ {
+ $builder = explain(select(star())->from(table('users')))->verbose();
+
+ $this->assertExplainQuery(
+ $builder,
+ 'EXPLAIN (VERBOSE) SELECT * FROM users'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ public function test_lock_multiple_tables() : void
+ {
+ $builder = lock_table('users', 'orders')->exclusive();
+
+ $this->assertLockQuery(
+ $builder,
+ 'LOCK TABLE users, orders IN EXCLUSIVE MODE'
+ );
+ }
+
+ public function test_lock_table_access_exclusive() : void
+ {
+ $builder = lock_table('users')->accessExclusive();
+
+ $this->assertLockQuery(
+ $builder,
+ 'LOCK TABLE users'
+ );
+ }
+
+ public function test_lock_table_access_share() : void
+ {
+ $builder = lock_table('users')->accessShare();
+
+ $this->assertLockQuery(
+ $builder,
+ 'LOCK TABLE users IN ACCESS SHARE MODE'
+ );
+ }
+
+ public function test_lock_table_default() : void
+ {
+ $builder = lock_table('users');
+
+ $this->assertLockQuery(
+ $builder,
+ 'LOCK TABLE users'
+ );
+ }
+
+ public function test_lock_table_exclusive() : void
+ {
+ $builder = lock_table('users')->exclusive();
+
+ $this->assertLockQuery(
+ $builder,
+ 'LOCK TABLE users IN EXCLUSIVE MODE'
+ );
+ }
+
+ public function test_lock_table_nowait() : void
+ {
+ $builder = lock_table('users')->exclusive()->nowait();
+
+ $this->assertLockQuery(
+ $builder,
+ 'LOCK TABLE users IN EXCLUSIVE MODE NOWAIT'
+ );
+ }
+
+ public function test_lock_table_row_exclusive() : void
+ {
+ $builder = lock_table('users')->rowExclusive();
+
+ $this->assertLockQuery(
+ $builder,
+ 'LOCK TABLE users IN ROW EXCLUSIVE MODE'
+ );
+ }
+
+ public function test_lock_table_row_share() : void
+ {
+ $builder = lock_table('users')->rowShare();
+
+ $this->assertLockQuery(
+ $builder,
+ 'LOCK TABLE users IN ROW SHARE MODE'
+ );
+ }
+
+ public function test_lock_table_share() : void
+ {
+ $builder = lock_table('users')->share();
+
+ $this->assertLockQuery(
+ $builder,
+ 'LOCK TABLE users IN SHARE MODE'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ 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'
+ );
+ }
+
+ public function test_vacuum_all_tables() : void
+ {
+ $builder = vacuum();
+
+ $this->assertVacuumQuery(
+ $builder,
+ 'VACUUM'
+ );
+ }
+
+ public function test_vacuum_analyze() : void
+ {
+ $builder = vacuum()->analyze()->tables('users');
+
+ $this->assertVacuumQuery(
+ $builder,
+ 'VACUUM (ANALYZE) users'
+ );
+ }
+
+ public function test_vacuum_disable_page_skipping() : void
+ {
+ $builder = vacuum()->disablePageSkipping()->table('users');
+
+ $this->assertVacuumQuery(
+ $builder,
+ 'VACUUM (DISABLE_PAGE_SKIPPING) users'
+ );
+ }
+
+ public function test_vacuum_freeze() : void
+ {
+ $builder = vacuum()->freeze()->table('users');
+
+ $this->assertVacuumQuery(
+ $builder,
+ 'VACUUM (FREEZE) users'
+ );
+ }
+
+ public function test_vacuum_full() : void
+ {
+ $builder = vacuum()->full()->tables('users');
+
+ $this->assertVacuumQuery(
+ $builder,
+ 'VACUUM (FULL) users'
+ );
+ }
+
+ public function test_vacuum_full_analyze_verbose() : void
+ {
+ $builder = vacuum()->full()->analyze()->verbose()->table('users');
+
+ $this->assertVacuumQuery(
+ $builder,
+ 'VACUUM (FULL, VERBOSE, ANALYZE) users'
+ );
+ }
+
+ public function test_vacuum_index_cleanup_off() : void
+ {
+ $builder = vacuum()->indexCleanup(IndexCleanup::OFF)->table('users');
+
+ $this->assertVacuumQuery(
+ $builder,
+ 'VACUUM (INDEX_CLEANUP OFF) users'
+ );
+ }
+
+ public function test_vacuum_index_cleanup_on() : void
+ {
+ $builder = vacuum()->indexCleanup(IndexCleanup::ON)->table('users');
+
+ $this->assertVacuumQuery(
+ $builder,
+ 'VACUUM (INDEX_CLEANUP ON) users'
+ );
+ }
+
+ public function test_vacuum_multiple_tables() : void
+ {
+ $builder = vacuum()->tables('users', 'orders', 'products');
+
+ $this->assertVacuumQuery(
+ $builder,
+ 'VACUUM users, orders, products'
+ );
+ }
+
+ public function test_vacuum_parallel() : void
+ {
+ $builder = vacuum()->parallel(4)->table('users');
+
+ $this->assertVacuumQuery(
+ $builder,
+ 'VACUUM (PARALLEL 4) users'
+ );
+ }
+
+ public function test_vacuum_process_main() : void
+ {
+ $builder = vacuum()->processMain(true)->table('users');
+
+ $this->assertVacuumQuery(
+ $builder,
+ 'VACUUM (PROCESS_MAIN 1) users'
+ );
+ }
+
+ public function test_vacuum_process_toast() : void
+ {
+ $builder = vacuum()->processToast(false)->table('users');
+
+ $this->assertVacuumQuery(
+ $builder,
+ 'VACUUM (PROCESS_TOAST 0) users'
+ );
+ }
+
+ public function test_vacuum_single_table() : void
+ {
+ $builder = vacuum()->table('users');
+
+ $this->assertVacuumQuery(
+ $builder,
+ 'VACUUM users'
+ );
+ }
+
+ public function test_vacuum_skip_locked() : void
+ {
+ $builder = vacuum()->skipLocked()->table('users');
+
+ $this->assertVacuumQuery(
+ $builder,
+ 'VACUUM (SKIP_LOCKED) users'
+ );
+ }
+
+ public function test_vacuum_table_with_columns() : void
+ {
+ $builder = vacuum()->table('users', 'email', 'name');
+
+ $this->assertVacuumQuery(
+ $builder,
+ 'VACUUM users(email, name)'
+ );
+ }
+
+ public function test_vacuum_table_with_schema() : void
+ {
+ $builder = vacuum()->table('public.users');
+
+ $this->assertVacuumQuery(
+ $builder,
+ 'VACUUM public.users'
+ );
+ }
+
+ public function test_vacuum_truncate_false() : void
+ {
+ $builder = vacuum()->truncate(false)->table('users');
+
+ $this->assertVacuumQuery(
+ $builder,
+ 'VACUUM (TRUNCATE 0) users'
+ );
+ }
+
+ public function test_vacuum_truncate_true() : void
+ {
+ $builder = vacuum()->truncate(true)->table('users');
+
+ $this->assertVacuumQuery(
+ $builder,
+ 'VACUUM (TRUNCATE 1) users'
+ );
+ }
+
+ public function test_vacuum_verbose() : void
+ {
+ $builder = vacuum()->verbose()->table('users');
+
+ $this->assertVacuumQuery(
+ $builder,
+ 'VACUUM (VERBOSE) users'
+ );
+ }
+}
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
new file mode 100644
index 000000000..53b901815
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Integration/QueryBuilder/ViewBuilderTest.php
@@ -0,0 +1,504 @@
+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/pg-query/tests/Flow/PgQuery/Tests/Unit/AST/Nodes/ColumnTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/AST/Nodes/ColumnTest.php
similarity index 95%
rename from src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/AST/Nodes/ColumnTest.php
rename to src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/AST/Nodes/ColumnTest.php
index e362db786..951627228 100644
--- a/src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/AST/Nodes/ColumnTest.php
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/AST/Nodes/ColumnTest.php
@@ -2,10 +2,10 @@
declare(strict_types=1);
-namespace Flow\PgQuery\Tests\Unit\AST\Nodes;
+namespace Flow\PostgreSql\Tests\Unit\AST\Nodes;
-use Flow\PgQuery\AST\Nodes\Column;
-use Flow\PgQuery\Protobuf\AST\{ColumnRef, ParseResult};
+use Flow\PostgreSql\AST\Nodes\Column;
+use Flow\PostgreSql\Protobuf\AST\{ColumnRef, ParseResult};
use PHPUnit\Framework\TestCase;
final class ColumnTest extends TestCase
diff --git a/src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/AST/Nodes/FunctionCallTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/AST/Nodes/FunctionCallTest.php
similarity index 94%
rename from src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/AST/Nodes/FunctionCallTest.php
rename to src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/AST/Nodes/FunctionCallTest.php
index 61d168e0c..b20150c0d 100644
--- a/src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/AST/Nodes/FunctionCallTest.php
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/AST/Nodes/FunctionCallTest.php
@@ -2,10 +2,10 @@
declare(strict_types=1);
-namespace Flow\PgQuery\Tests\Unit\AST\Nodes;
+namespace Flow\PostgreSql\Tests\Unit\AST\Nodes;
-use Flow\PgQuery\AST\Nodes\FunctionCall;
-use Flow\PgQuery\Protobuf\AST\{FuncCall, ParseResult};
+use Flow\PostgreSql\AST\Nodes\FunctionCall;
+use Flow\PostgreSql\Protobuf\AST\{FuncCall, ParseResult};
use PHPUnit\Framework\TestCase;
final class FunctionCallTest extends TestCase
diff --git a/src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/AST/Nodes/TableTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/AST/Nodes/TableTest.php
similarity index 95%
rename from src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/AST/Nodes/TableTest.php
rename to src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/AST/Nodes/TableTest.php
index e8be3584a..1c1ccdae7 100644
--- a/src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/AST/Nodes/TableTest.php
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/AST/Nodes/TableTest.php
@@ -2,10 +2,10 @@
declare(strict_types=1);
-namespace Flow\PgQuery\Tests\Unit\AST\Nodes;
+namespace Flow\PostgreSql\Tests\Unit\AST\Nodes;
-use Flow\PgQuery\AST\Nodes\Table;
-use Flow\PgQuery\Protobuf\AST\{ParseResult, RangeVar};
+use Flow\PostgreSql\AST\Nodes\Table;
+use Flow\PostgreSql\Protobuf\AST\{ParseResult, RangeVar};
use PHPUnit\Framework\TestCase;
final class TableTest extends TestCase
diff --git a/src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/AST/Transformers/CountModifierEdgeCasesTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/AST/Transformers/CountModifierEdgeCasesTest.php
similarity index 91%
rename from src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/AST/Transformers/CountModifierEdgeCasesTest.php
rename to src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/AST/Transformers/CountModifierEdgeCasesTest.php
index dce41bfed..591ac2f5e 100644
--- a/src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/AST/Transformers/CountModifierEdgeCasesTest.php
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/AST/Transformers/CountModifierEdgeCasesTest.php
@@ -2,9 +2,9 @@
declare(strict_types=1);
-namespace Flow\PgQuery\Tests\Unit\AST\Transformers;
+namespace Flow\PostgreSql\Tests\Unit\AST\Transformers;
-use function Flow\PgQuery\DSL\{pg_to_count_query, pg_to_paginated_query};
+use function Flow\PostgreSql\DSL\{sql_to_count_query, sql_to_paginated_query};
use PHPUnit\Framework\TestCase;
@@ -32,19 +32,19 @@ public function test_complete_paginator_pattern() : void
ORDER BY p.name ASC, p.id
SQL;
- $countQuery = pg_to_count_query($baseQuery);
+ $countQuery = sql_to_count_query($baseQuery);
self::assertSame(
'SELECT count(*) FROM (SELECT p.id, p.name, p.price, c.name AS category_name FROM products p JOIN categories c ON p.category_id = c.id WHERE p.active = true AND p.price >= 10) _count_subq',
$countQuery
);
- $page1 = pg_to_paginated_query($baseQuery, limit: 25, offset: 0);
+ $page1 = sql_to_paginated_query($baseQuery, limit: 25, offset: 0);
self::assertSame(
'SELECT p.id, p.name, p.price, c.name AS category_name FROM products p JOIN categories c ON p.category_id = c.id WHERE p.active = true AND p.price >= 10 ORDER BY p.name ASC, p.id LIMIT 25',
$page1
);
- $page2 = pg_to_paginated_query($baseQuery, limit: 25, offset: 25);
+ $page2 = sql_to_paginated_query($baseQuery, limit: 25, offset: 25);
self::assertSame(
'SELECT p.id, p.name, p.price, c.name AS category_name FROM products p JOIN categories c ON p.category_id = c.id WHERE p.active = true AND p.price >= 10 ORDER BY p.name ASC, p.id LIMIT 25 OFFSET 25',
$page2
@@ -65,7 +65,7 @@ public function test_count_with_aggregation() : void
ORDER BY product_count DESC
SQL;
- $countQuery = pg_to_count_query($baseQuery);
+ $countQuery = sql_to_count_query($baseQuery);
self::assertSame(
'SELECT count(*) FROM (SELECT category_id, count(*) AS product_count, avg(price) AS avg_price FROM products WHERE active = true GROUP BY category_id HAVING count(*) >= 5) _count_subq',
@@ -90,7 +90,7 @@ public function test_count_with_complex_joins() : void
ORDER BY o.created_at DESC, o.id
SQL;
- $countQuery = pg_to_count_query($baseQuery);
+ $countQuery = sql_to_count_query($baseQuery);
self::assertSame(
'SELECT count(*) FROM (SELECT o.id, o.total_amount, u.email, p.name AS product_name FROM orders o JOIN users u ON o.user_id = u.id JOIN order_items oi ON o.id = oi.order_id JOIN products p ON oi.product_id = p.id WHERE o.status = \'completed\' AND o.created_at >= \'2025-01-01\') _count_subq',
@@ -114,7 +114,7 @@ public function test_count_with_cte() : void
ORDER BY order_count DESC
SQL;
- $countQuery = pg_to_count_query($baseQuery);
+ $countQuery = sql_to_count_query($baseQuery);
self::assertSame(
'SELECT count(*) FROM (WITH active_customers AS (SELECT DISTINCT u.id, u.email FROM users u JOIN orders o ON u.id = o.user_id WHERE o.created_at >= (now() - \'30 days\'::interval)) SELECT ac.id, ac.email, count(o.id) AS order_count FROM active_customers ac JOIN orders o ON ac.id = o.user_id GROUP BY ac.id, ac.email) _count_subq',
@@ -135,7 +135,7 @@ public function test_count_with_distinct() : void
ORDER BY u.name
SQL;
- $countQuery = pg_to_count_query($baseQuery);
+ $countQuery = sql_to_count_query($baseQuery);
self::assertSame(
'SELECT count(*) FROM (SELECT DISTINCT u.id, u.email, u.name FROM users u JOIN orders o ON u.id = o.user_id WHERE o.total_amount > 100) _count_subq',
@@ -165,7 +165,7 @@ public function test_count_with_subquery_in_where() : void
ORDER BY p.price DESC
SQL;
- $countQuery = pg_to_count_query($baseQuery);
+ $countQuery = sql_to_count_query($baseQuery);
self::assertSame(
'SELECT count(*) FROM (SELECT p.id, p.name, p.price FROM products p WHERE p.category_id IN (SELECT c.id FROM categories c WHERE c.active = true AND c.parent_id IS NOT NULL) AND p.price > (SELECT avg(price) FROM products WHERE active = true)) _count_subq',
@@ -184,7 +184,7 @@ public function test_count_with_union() : void
ORDER BY id DESC
SQL;
- $countQuery = pg_to_count_query($baseQuery);
+ $countQuery = sql_to_count_query($baseQuery);
self::assertSame(
'SELECT count(*) FROM ((SELECT id, \'order\' AS notification_type, message FROM order_notifications WHERE read = false UNION ALL SELECT id, \'payment\' AS notification_type, message FROM payment_notifications WHERE read = false) UNION ALL SELECT id, \'shipping\' AS notification_type, message FROM shipping_notifications WHERE read = false) _count_subq',
@@ -206,7 +206,7 @@ public function test_count_with_window_functions() : void
ORDER BY e.department_id, dept_rank
SQL;
- $countQuery = pg_to_count_query($baseQuery);
+ $countQuery = sql_to_count_query($baseQuery);
self::assertSame(
'SELECT count(*) FROM (SELECT e.id, e.name, e.salary, e.department_id, rank() OVER (PARTITION BY e.department_id ORDER BY e.salary DESC) AS dept_rank FROM employees e WHERE e.active = true) _count_subq',
diff --git a/src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/AST/Transformers/CountModifierTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/AST/Transformers/CountModifierTest.php
similarity index 65%
rename from src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/AST/Transformers/CountModifierTest.php
rename to src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/AST/Transformers/CountModifierTest.php
index cee32d28f..750f0b8d4 100644
--- a/src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/AST/Transformers/CountModifierTest.php
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/AST/Transformers/CountModifierTest.php
@@ -2,9 +2,10 @@
declare(strict_types=1);
-namespace Flow\PgQuery\Tests\Unit\AST\Transformers;
+namespace Flow\PostgreSql\Tests\Unit\AST\Transformers;
-use function Flow\PgQuery\DSL\{pg_count_modifier, pg_parse};
+use function Flow\PostgreSql\DSL\sql_parse;
+use Flow\PostgreSql\AST\Transformers\CountModifier;
use PHPUnit\Framework\TestCase;
final class CountModifierTest extends TestCase
@@ -18,9 +19,9 @@ protected function setUp() : void
public function test_count_cte_query() : void
{
- $parsed = pg_parse('WITH active AS (SELECT * FROM users WHERE active = true) SELECT * FROM active ORDER BY name');
+ $parsed = sql_parse('WITH active AS (SELECT * FROM users WHERE active = true) SELECT * FROM active ORDER BY name');
- $modifier = pg_count_modifier();
+ $modifier = new CountModifier();
$parsed->traverse($modifier);
self::assertSame('SELECT count(*) FROM (WITH active AS (SELECT * FROM users WHERE active = true) SELECT * FROM active) _count_subq', $parsed->deparse());
@@ -28,9 +29,9 @@ public function test_count_cte_query() : void
public function test_count_distinct_query() : void
{
- $parsed = pg_parse('SELECT DISTINCT name FROM users');
+ $parsed = sql_parse('SELECT DISTINCT name FROM users');
- $modifier = pg_count_modifier();
+ $modifier = new CountModifier();
$parsed->traverse($modifier);
self::assertSame('SELECT count(*) FROM (SELECT DISTINCT name FROM users) _count_subq', $parsed->deparse());
@@ -38,9 +39,9 @@ public function test_count_distinct_query() : void
public function test_count_except_query() : void
{
- $parsed = pg_parse('SELECT id FROM users EXCEPT SELECT id FROM banned ORDER BY id');
+ $parsed = sql_parse('SELECT id FROM users EXCEPT SELECT id FROM banned ORDER BY id');
- $modifier = pg_count_modifier();
+ $modifier = new CountModifier();
$parsed->traverse($modifier);
self::assertSame('SELECT count(*) FROM (SELECT id FROM users EXCEPT SELECT id FROM banned) _count_subq', $parsed->deparse());
@@ -48,9 +49,9 @@ public function test_count_except_query() : void
public function test_count_group_by_query() : void
{
- $parsed = pg_parse('SELECT dept, COUNT(*) as cnt FROM users GROUP BY dept HAVING COUNT(*) > 5 ORDER BY dept');
+ $parsed = sql_parse('SELECT dept, COUNT(*) as cnt FROM users GROUP BY dept HAVING COUNT(*) > 5 ORDER BY dept');
- $modifier = pg_count_modifier();
+ $modifier = new CountModifier();
$parsed->traverse($modifier);
self::assertSame('SELECT count(*) FROM (SELECT dept, count(*) AS cnt FROM users GROUP BY dept HAVING count(*) > 5) _count_subq', $parsed->deparse());
@@ -58,9 +59,9 @@ public function test_count_group_by_query() : void
public function test_count_intersect_query() : void
{
- $parsed = pg_parse('SELECT id FROM users INTERSECT SELECT id FROM admins ORDER BY id');
+ $parsed = sql_parse('SELECT id FROM users INTERSECT SELECT id FROM admins ORDER BY id');
- $modifier = pg_count_modifier();
+ $modifier = new CountModifier();
$parsed->traverse($modifier);
self::assertSame('SELECT count(*) FROM (SELECT id FROM users INTERSECT SELECT id FROM admins) _count_subq', $parsed->deparse());
@@ -68,9 +69,9 @@ public function test_count_intersect_query() : void
public function test_count_removes_order_by() : void
{
- $parsed = pg_parse('SELECT id, name FROM users WHERE active = true ORDER BY name ASC, id DESC');
+ $parsed = sql_parse('SELECT id, name FROM users WHERE active = true ORDER BY name ASC, id DESC');
- $modifier = pg_count_modifier();
+ $modifier = new CountModifier();
$parsed->traverse($modifier);
self::assertSame('SELECT count(*) FROM (SELECT id, name FROM users WHERE active = true) _count_subq', $parsed->deparse());
@@ -78,9 +79,9 @@ public function test_count_removes_order_by() : void
public function test_count_simple_select() : void
{
- $parsed = pg_parse('SELECT * FROM users');
+ $parsed = sql_parse('SELECT * FROM users');
- $modifier = pg_count_modifier();
+ $modifier = new CountModifier();
$parsed->traverse($modifier);
self::assertSame('SELECT count(*) FROM (SELECT * FROM users) _count_subq', $parsed->deparse());
@@ -88,9 +89,9 @@ public function test_count_simple_select() : void
public function test_count_strips_existing_limit_and_offset() : void
{
- $parsed = pg_parse('SELECT * FROM users ORDER BY id LIMIT 100 OFFSET 50');
+ $parsed = sql_parse('SELECT * FROM users ORDER BY id LIMIT 100 OFFSET 50');
- $modifier = pg_count_modifier();
+ $modifier = new CountModifier();
$parsed->traverse($modifier);
self::assertSame('SELECT count(*) FROM (SELECT * FROM users) _count_subq', $parsed->deparse());
@@ -98,9 +99,9 @@ public function test_count_strips_existing_limit_and_offset() : void
public function test_count_union_query() : void
{
- $parsed = pg_parse('SELECT id FROM users UNION SELECT id FROM admins ORDER BY id');
+ $parsed = sql_parse('SELECT id FROM users UNION SELECT id FROM admins ORDER BY id');
- $modifier = pg_count_modifier();
+ $modifier = new CountModifier();
$parsed->traverse($modifier);
self::assertSame('SELECT count(*) FROM (SELECT id FROM users UNION SELECT id FROM admins) _count_subq', $parsed->deparse());
@@ -108,9 +109,9 @@ public function test_count_union_query() : void
public function test_subquery_in_from_clause_not_counted() : void
{
- $parsed = pg_parse('SELECT * FROM (SELECT id FROM users) AS sub ORDER BY id');
+ $parsed = sql_parse('SELECT * FROM (SELECT id FROM users) AS sub ORDER BY id');
- $modifier = pg_count_modifier();
+ $modifier = new CountModifier();
$parsed->traverse($modifier);
self::assertSame('SELECT count(*) FROM (SELECT * FROM (SELECT id FROM users) sub) _count_subq', $parsed->deparse());
@@ -118,9 +119,9 @@ public function test_subquery_in_from_clause_not_counted() : void
public function test_subquery_in_where_clause_not_counted() : void
{
- $parsed = pg_parse('SELECT * FROM users WHERE id IN (SELECT user_id FROM orders) ORDER BY id');
+ $parsed = sql_parse('SELECT * FROM users WHERE id IN (SELECT user_id FROM orders) ORDER BY id');
- $modifier = pg_count_modifier();
+ $modifier = new CountModifier();
$parsed->traverse($modifier);
self::assertSame('SELECT count(*) FROM (SELECT * FROM users WHERE id IN (SELECT user_id FROM orders)) _count_subq', $parsed->deparse());
diff --git a/src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/AST/Transformers/KeysetPaginationEdgeCasesTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/AST/Transformers/KeysetPaginationEdgeCasesTest.php
similarity index 77%
rename from src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/AST/Transformers/KeysetPaginationEdgeCasesTest.php
rename to src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/AST/Transformers/KeysetPaginationEdgeCasesTest.php
index dcccdb7bb..0d195abb2 100644
--- a/src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/AST/Transformers/KeysetPaginationEdgeCasesTest.php
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/AST/Transformers/KeysetPaginationEdgeCasesTest.php
@@ -2,11 +2,11 @@
declare(strict_types=1);
-namespace Flow\PgQuery\Tests\Unit\AST\Transformers;
+namespace Flow\PostgreSql\Tests\Unit\AST\Transformers;
-use function Flow\PgQuery\DSL\{pg_keyset_column, pg_to_keyset_query};
+use function Flow\PostgreSql\DSL\{sql_keyset_column, sql_to_keyset_query};
-use Flow\PgQuery\AST\Transformers\SortOrder;
+use Flow\PostgreSql\AST\Transformers\SortOrder;
use PHPUnit\Framework\TestCase;
@@ -38,17 +38,17 @@ public function test_audit_log_iteration() : void
SQL;
$columns = [
- pg_keyset_column('al.created_at', SortOrder::DESC),
- pg_keyset_column('al.id', SortOrder::DESC),
+ sql_keyset_column('al.created_at', SortOrder::DESC),
+ sql_keyset_column('al.id', SortOrder::DESC),
];
- $page1 = pg_to_keyset_query($baseQuery, limit: 1000, columns: $columns, cursor: null);
+ $page1 = sql_to_keyset_query($baseQuery, limit: 1000, columns: $columns, cursor: null);
self::assertSame(
'SELECT al.id, al.event_type, al.entity_type, al.entity_id, al.user_id, al.ip_address, al.changes, al.created_at FROM audit_log al WHERE al.event_type IN (\'create\', \'update\', \'delete\') AND al.created_at >= \'2025-01-01\' ORDER BY al.created_at DESC, al.id DESC LIMIT 1000',
$page1
);
- $page100 = pg_to_keyset_query($baseQuery, limit: 1000, columns: $columns, cursor: ['2025-01-05 08:30:00', 50000]);
+ $page100 = sql_to_keyset_query($baseQuery, limit: 1000, columns: $columns, cursor: ['2025-01-05 08:30:00', 50000]);
self::assertSame(
'SELECT al.id, al.event_type, al.entity_type, al.entity_id, al.user_id, al.ip_address, al.changes, al.created_at FROM audit_log al WHERE (al.event_type IN (\'create\', \'update\', \'delete\') AND al.created_at >= \'2025-01-01\') AND (al.created_at < $1 OR (al.created_at = $1 AND al.id < $2)) ORDER BY al.created_at DESC, al.id DESC LIMIT 1000',
$page100
@@ -69,23 +69,23 @@ public function test_iterate_through_pages() : void
SQL;
$columns = [
- pg_keyset_column('a.created_at', SortOrder::DESC),
- pg_keyset_column('a.id', SortOrder::DESC),
+ sql_keyset_column('a.created_at', SortOrder::DESC),
+ sql_keyset_column('a.id', SortOrder::DESC),
];
- $page1 = pg_to_keyset_query($baseQuery, limit: 50, columns: $columns, cursor: null);
+ $page1 = sql_to_keyset_query($baseQuery, limit: 50, columns: $columns, cursor: null);
self::assertSame(
'SELECT a.id, a.user_id, a.action_type, a.metadata, a.created_at FROM activity_log a ORDER BY a.created_at DESC, a.id DESC LIMIT 50',
$page1
);
- $page2 = pg_to_keyset_query($baseQuery, limit: 50, columns: $columns, cursor: ['2025-01-15 14:30:00', 1000]);
+ $page2 = sql_to_keyset_query($baseQuery, limit: 50, columns: $columns, cursor: ['2025-01-15 14:30:00', 1000]);
self::assertSame(
'SELECT a.id, a.user_id, a.action_type, a.metadata, a.created_at FROM activity_log a WHERE a.created_at < $1 OR (a.created_at = $1 AND a.id < $2) ORDER BY a.created_at DESC, a.id DESC LIMIT 50',
$page2
);
- $page3 = pg_to_keyset_query($baseQuery, limit: 50, columns: $columns, cursor: ['2025-01-15 12:15:00', 850]);
+ $page3 = sql_to_keyset_query($baseQuery, limit: 50, columns: $columns, cursor: ['2025-01-15 12:15:00', 850]);
self::assertSame(
'SELECT a.id, a.user_id, a.action_type, a.metadata, a.created_at FROM activity_log a WHERE a.created_at < $1 OR (a.created_at = $1 AND a.id < $2) ORDER BY a.created_at DESC, a.id DESC LIMIT 50',
$page3
@@ -110,17 +110,17 @@ public function test_with_complex_joins() : void
SQL;
$columns = [
- pg_keyset_column('o.created_at', SortOrder::DESC),
- pg_keyset_column('o.id', SortOrder::DESC),
+ sql_keyset_column('o.created_at', SortOrder::DESC),
+ sql_keyset_column('o.id', SortOrder::DESC),
];
- $page1 = pg_to_keyset_query($baseQuery, limit: 25, columns: $columns, cursor: null);
+ $page1 = sql_to_keyset_query($baseQuery, limit: 25, columns: $columns, cursor: null);
self::assertSame(
'SELECT o.id AS order_id, o.created_at, o.total_amount, u.email AS customer_email, p.name AS product_name FROM orders o JOIN users u ON o.user_id = u.id JOIN order_items oi ON o.id = oi.order_id JOIN products p ON oi.product_id = p.id WHERE o.status = \'completed\' ORDER BY o.created_at DESC, o.id DESC LIMIT 25',
$page1
);
- $page2 = pg_to_keyset_query($baseQuery, limit: 25, columns: $columns, cursor: ['2025-01-10 09:45:00', 5000]);
+ $page2 = sql_to_keyset_query($baseQuery, limit: 25, columns: $columns, cursor: ['2025-01-10 09:45:00', 5000]);
self::assertSame(
'SELECT o.id AS order_id, o.created_at, o.total_amount, u.email AS customer_email, p.name AS product_name FROM orders o JOIN users u ON o.user_id = u.id JOIN order_items oi ON o.id = oi.order_id JOIN products p ON oi.product_id = p.id WHERE o.status = \'completed\' AND (o.created_at < $1 OR (o.created_at = $1 AND o.id < $2)) ORDER BY o.created_at DESC, o.id DESC LIMIT 25',
$page2
@@ -146,17 +146,17 @@ public function test_with_existing_complex_where() : void
SQL;
$columns = [
- pg_keyset_column('p.created_at', SortOrder::DESC),
- pg_keyset_column('p.id', SortOrder::DESC),
+ sql_keyset_column('p.created_at', SortOrder::DESC),
+ sql_keyset_column('p.id', SortOrder::DESC),
];
- $page1 = pg_to_keyset_query($baseQuery, limit: 12, columns: $columns, cursor: null);
+ $page1 = sql_to_keyset_query($baseQuery, limit: 12, columns: $columns, cursor: null);
self::assertSame(
'SELECT p.id, p.name, p.price, p.category_id, p.created_at FROM products p WHERE p.active = true AND p.price BETWEEN 50 AND 500 AND p.category_id IN (1, 2, 3, 4, 5) AND p.stock_quantity > 0 AND (p.name ILIKE \'%phone%\' OR p.name ILIKE \'%tablet%\') ORDER BY p.created_at DESC, p.id DESC LIMIT 12',
$page1
);
- $page2 = pg_to_keyset_query($baseQuery, limit: 12, columns: $columns, cursor: ['2025-01-10 15:00:00', 750]);
+ $page2 = sql_to_keyset_query($baseQuery, limit: 12, columns: $columns, cursor: ['2025-01-10 15:00:00', 750]);
self::assertSame(
'SELECT p.id, p.name, p.price, p.category_id, p.created_at FROM products p WHERE (p.active = true AND p.price BETWEEN 50 AND 500 AND p.category_id IN (1, 2, 3, 4, 5) AND p.stock_quantity > 0 AND (p.name ILIKE \'%phone%\' OR p.name ILIKE \'%tablet%\')) AND (p.created_at < $1 OR (p.created_at = $1 AND p.id < $2)) ORDER BY p.created_at DESC, p.id DESC LIMIT 12',
$page2
@@ -178,18 +178,18 @@ public function test_with_mixed_sort_orders() : void
SQL;
$columns = [
- pg_keyset_column('t.priority', SortOrder::DESC),
- pg_keyset_column('t.created_at', SortOrder::ASC),
- pg_keyset_column('t.id', SortOrder::ASC),
+ sql_keyset_column('t.priority', SortOrder::DESC),
+ sql_keyset_column('t.created_at', SortOrder::ASC),
+ sql_keyset_column('t.id', SortOrder::ASC),
];
- $page1 = pg_to_keyset_query($baseQuery, limit: 20, columns: $columns, cursor: null);
+ $page1 = sql_to_keyset_query($baseQuery, limit: 20, columns: $columns, cursor: null);
self::assertSame(
'SELECT t.id, t.title, t.priority, t.created_at, t.status FROM tickets t WHERE t.status <> \'closed\' ORDER BY t.priority DESC, t.created_at ASC, t.id ASC LIMIT 20',
$page1
);
- $page2 = pg_to_keyset_query($baseQuery, limit: 20, columns: $columns, cursor: [5, '2025-01-01 10:00:00', 100]);
+ $page2 = sql_to_keyset_query($baseQuery, limit: 20, columns: $columns, cursor: [5, '2025-01-01 10:00:00', 100]);
self::assertSame(
'SELECT t.id, t.title, t.priority, t.created_at, t.status FROM tickets t WHERE t.status <> \'closed\' AND (t.priority < $1 OR (t.priority = $1 AND t.created_at > $2) OR (t.priority = $1 AND t.created_at = $2 AND t.id > $3)) ORDER BY t.priority DESC, t.created_at ASC, t.id ASC LIMIT 20',
$page2
@@ -212,17 +212,17 @@ public function test_with_window_functions() : void
SQL;
$columns = [
- pg_keyset_column('e.hire_date', SortOrder::DESC),
- pg_keyset_column('e.id', SortOrder::DESC),
+ sql_keyset_column('e.hire_date', SortOrder::DESC),
+ sql_keyset_column('e.id', SortOrder::DESC),
];
- $page1 = pg_to_keyset_query($baseQuery, limit: 30, columns: $columns, cursor: null);
+ $page1 = sql_to_keyset_query($baseQuery, limit: 30, columns: $columns, cursor: null);
self::assertSame(
'SELECT e.id, e.name, e.department_id, e.salary, rank() OVER (PARTITION BY e.department_id ORDER BY e.salary DESC) AS salary_rank, e.hire_date FROM employees e WHERE e.active = true ORDER BY e.hire_date DESC, e.id DESC LIMIT 30',
$page1
);
- $page2 = pg_to_keyset_query($baseQuery, limit: 30, columns: $columns, cursor: ['2024-06-15', 500]);
+ $page2 = sql_to_keyset_query($baseQuery, limit: 30, columns: $columns, cursor: ['2024-06-15', 500]);
self::assertSame(
'SELECT e.id, e.name, e.department_id, e.salary, rank() OVER (PARTITION BY e.department_id ORDER BY e.salary DESC) AS salary_rank, e.hire_date FROM employees e WHERE e.active = true AND (e.hire_date < $1 OR (e.hire_date = $1 AND e.id < $2)) ORDER BY e.hire_date DESC, e.id DESC LIMIT 30',
$page2
diff --git a/src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/AST/Transformers/KeysetPaginationModifierTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/AST/Transformers/KeysetPaginationModifierTest.php
similarity index 54%
rename from src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/AST/Transformers/KeysetPaginationModifierTest.php
rename to src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/AST/Transformers/KeysetPaginationModifierTest.php
index f8cdf6a52..499528c1e 100644
--- a/src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/AST/Transformers/KeysetPaginationModifierTest.php
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/AST/Transformers/KeysetPaginationModifierTest.php
@@ -2,11 +2,11 @@
declare(strict_types=1);
-namespace Flow\PgQuery\Tests\Unit\AST\Transformers;
+namespace Flow\PostgreSql\Tests\Unit\AST\Transformers;
-use function Flow\PgQuery\DSL\{pg_keyset_column, pg_keyset_pagination, pg_keyset_pagination_config, pg_parse};
-use Flow\PgQuery\AST\Transformers\SortOrder;
-use Flow\PgQuery\Exception\PaginationException;
+use function Flow\PostgreSql\DSL\{sql_keyset_column, sql_parse};
+use Flow\PostgreSql\AST\Transformers\{KeysetPaginationConfig, KeysetPaginationModifier, SortOrder};
+use Flow\PostgreSql\Exception\PaginationException;
use PHPUnit\Framework\TestCase;
final class KeysetPaginationModifierTest extends TestCase
@@ -20,12 +20,12 @@ protected function setUp() : void
public function test_first_page_multiple_columns() : void
{
- $parsed = pg_parse('SELECT * FROM users ORDER BY created_at, id');
+ $parsed = sql_parse('SELECT * FROM users ORDER BY created_at, id');
- $modifier = pg_keyset_pagination(10, [
- pg_keyset_column('created_at', SortOrder::ASC),
- pg_keyset_column('id', SortOrder::ASC),
- ]);
+ $modifier = new KeysetPaginationModifier(new KeysetPaginationConfig(10, [
+ sql_keyset_column('created_at', SortOrder::ASC),
+ sql_keyset_column('id', SortOrder::ASC),
+ ]));
$parsed->traverse($modifier);
self::assertSame('SELECT * FROM users ORDER BY created_at, id LIMIT 10', $parsed->deparse());
@@ -33,9 +33,9 @@ public function test_first_page_multiple_columns() : void
public function test_first_page_single_column_asc() : void
{
- $parsed = pg_parse('SELECT * FROM users ORDER BY id');
+ $parsed = sql_parse('SELECT * FROM users ORDER BY id');
- $modifier = pg_keyset_pagination(10, [pg_keyset_column('id', SortOrder::ASC)]);
+ $modifier = new KeysetPaginationModifier(new KeysetPaginationConfig(10, [sql_keyset_column('id', SortOrder::ASC)]));
$parsed->traverse($modifier);
self::assertSame('SELECT * FROM users ORDER BY id LIMIT 10', $parsed->deparse());
@@ -43,9 +43,9 @@ public function test_first_page_single_column_asc() : void
public function test_first_page_single_column_desc() : void
{
- $parsed = pg_parse('SELECT * FROM users ORDER BY id DESC');
+ $parsed = sql_parse('SELECT * FROM users ORDER BY id DESC');
- $modifier = pg_keyset_pagination(10, [pg_keyset_column('id', SortOrder::DESC)]);
+ $modifier = new KeysetPaginationModifier(new KeysetPaginationConfig(10, [sql_keyset_column('id', SortOrder::DESC)]));
$parsed->traverse($modifier);
self::assertSame('SELECT * FROM users ORDER BY id DESC LIMIT 10', $parsed->deparse());
@@ -53,9 +53,9 @@ public function test_first_page_single_column_desc() : void
public function test_keyset_pagination_config_default_cursor() : void
{
- $columns = [pg_keyset_column('id', SortOrder::ASC)];
+ $columns = [sql_keyset_column('id', SortOrder::ASC)];
- $config = pg_keyset_pagination_config(20, $columns);
+ $config = new KeysetPaginationConfig(20, $columns);
self::assertSame(20, $config->limit);
self::assertSame($columns, $config->columns);
@@ -65,12 +65,12 @@ public function test_keyset_pagination_config_default_cursor() : void
public function test_keyset_pagination_config_returns_config_object() : void
{
$columns = [
- pg_keyset_column('created_at', SortOrder::ASC),
- pg_keyset_column('id', SortOrder::ASC),
+ sql_keyset_column('created_at', SortOrder::ASC),
+ sql_keyset_column('id', SortOrder::ASC),
];
$cursor = ['2025-01-15', 42];
- $config = pg_keyset_pagination_config(10, $columns, $cursor);
+ $config = new KeysetPaginationConfig(10, $columns, $cursor);
self::assertSame(10, $config->limit);
self::assertSame($columns, $config->columns);
@@ -79,9 +79,9 @@ public function test_keyset_pagination_config_returns_config_object() : void
public function test_qualified_column_names() : void
{
- $parsed = pg_parse('SELECT u.* FROM users u ORDER BY u.id');
+ $parsed = sql_parse('SELECT u.* FROM users u ORDER BY u.id');
- $modifier = pg_keyset_pagination(10, [pg_keyset_column('u.id', SortOrder::ASC)], [42]);
+ $modifier = new KeysetPaginationModifier(new KeysetPaginationConfig(10, [sql_keyset_column('u.id', SortOrder::ASC)], [42]));
$parsed->traverse($modifier);
self::assertSame('SELECT u.* FROM users u WHERE u.id > $1 ORDER BY u.id LIMIT 10', $parsed->deparse());
@@ -89,9 +89,9 @@ public function test_qualified_column_names() : void
public function test_subquery_not_modified() : void
{
- $parsed = pg_parse('SELECT * FROM (SELECT id FROM users ORDER BY id) AS sub ORDER BY id');
+ $parsed = sql_parse('SELECT * FROM (SELECT id FROM users ORDER BY id) AS sub ORDER BY id');
- $modifier = pg_keyset_pagination(10, [pg_keyset_column('id', SortOrder::ASC)], [42]);
+ $modifier = new KeysetPaginationModifier(new KeysetPaginationConfig(10, [sql_keyset_column('id', SortOrder::ASC)], [42]));
$parsed->traverse($modifier);
self::assertSame(
@@ -102,12 +102,12 @@ public function test_subquery_not_modified() : void
public function test_subsequent_page_multiple_columns_all_asc() : void
{
- $parsed = pg_parse('SELECT * FROM users ORDER BY created_at, id');
+ $parsed = sql_parse('SELECT * FROM users ORDER BY created_at, id');
- $modifier = pg_keyset_pagination(10, [
- pg_keyset_column('created_at', SortOrder::ASC),
- pg_keyset_column('id', SortOrder::ASC),
- ], ['2025-01-15 12:30:00', 42]);
+ $modifier = new KeysetPaginationModifier(new KeysetPaginationConfig(10, [
+ sql_keyset_column('created_at', SortOrder::ASC),
+ sql_keyset_column('id', SortOrder::ASC),
+ ], ['2025-01-15 12:30:00', 42]));
$parsed->traverse($modifier);
self::assertSame(
@@ -118,12 +118,12 @@ public function test_subsequent_page_multiple_columns_all_asc() : void
public function test_subsequent_page_multiple_columns_mixed_order() : void
{
- $parsed = pg_parse('SELECT * FROM users ORDER BY created_at ASC, id DESC');
+ $parsed = sql_parse('SELECT * FROM users ORDER BY created_at ASC, id DESC');
- $modifier = pg_keyset_pagination(10, [
- pg_keyset_column('created_at', SortOrder::ASC),
- pg_keyset_column('id', SortOrder::DESC),
- ], ['2025-01-15 12:30:00', 42]);
+ $modifier = new KeysetPaginationModifier(new KeysetPaginationConfig(10, [
+ sql_keyset_column('created_at', SortOrder::ASC),
+ sql_keyset_column('id', SortOrder::DESC),
+ ], ['2025-01-15 12:30:00', 42]));
$parsed->traverse($modifier);
self::assertSame(
@@ -134,9 +134,9 @@ public function test_subsequent_page_multiple_columns_mixed_order() : void
public function test_subsequent_page_single_column_asc() : void
{
- $parsed = pg_parse('SELECT * FROM users ORDER BY id');
+ $parsed = sql_parse('SELECT * FROM users ORDER BY id');
- $modifier = pg_keyset_pagination(10, [pg_keyset_column('id', SortOrder::ASC)], [42]);
+ $modifier = new KeysetPaginationModifier(new KeysetPaginationConfig(10, [sql_keyset_column('id', SortOrder::ASC)], [42]));
$parsed->traverse($modifier);
self::assertSame('SELECT * FROM users WHERE id > $1 ORDER BY id LIMIT 10', $parsed->deparse());
@@ -144,9 +144,9 @@ public function test_subsequent_page_single_column_asc() : void
public function test_subsequent_page_single_column_desc() : void
{
- $parsed = pg_parse('SELECT * FROM users ORDER BY id DESC');
+ $parsed = sql_parse('SELECT * FROM users ORDER BY id DESC');
- $modifier = pg_keyset_pagination(10, [pg_keyset_column('id', SortOrder::DESC)], [42]);
+ $modifier = new KeysetPaginationModifier(new KeysetPaginationConfig(10, [sql_keyset_column('id', SortOrder::DESC)], [42]));
$parsed->traverse($modifier);
self::assertSame('SELECT * FROM users WHERE id < $1 ORDER BY id DESC LIMIT 10', $parsed->deparse());
@@ -154,13 +154,13 @@ public function test_subsequent_page_single_column_desc() : void
public function test_subsequent_page_three_columns() : void
{
- $parsed = pg_parse('SELECT * FROM users ORDER BY status, created_at DESC, id');
+ $parsed = sql_parse('SELECT * FROM users ORDER BY status, created_at DESC, id');
- $modifier = pg_keyset_pagination(10, [
- pg_keyset_column('status', SortOrder::ASC),
- pg_keyset_column('created_at', SortOrder::DESC),
- pg_keyset_column('id', SortOrder::ASC),
- ], ['active', '2025-01-15', 100]);
+ $modifier = new KeysetPaginationModifier(new KeysetPaginationConfig(10, [
+ sql_keyset_column('status', SortOrder::ASC),
+ sql_keyset_column('created_at', SortOrder::DESC),
+ sql_keyset_column('id', SortOrder::ASC),
+ ], ['active', '2025-01-15', 100]));
$parsed->traverse($modifier);
self::assertSame(
@@ -174,12 +174,12 @@ public function test_throws_when_cursor_count_mismatch() : void
$this->expectException(PaginationException::class);
$this->expectExceptionMessage('Cursor values count (1) must match columns count (2)');
- $parsed = pg_parse('SELECT * FROM users ORDER BY created_at, id');
+ $parsed = sql_parse('SELECT * FROM users ORDER BY created_at, id');
- $modifier = pg_keyset_pagination(10, [
- pg_keyset_column('created_at', SortOrder::ASC),
- pg_keyset_column('id', SortOrder::ASC),
- ], [42]);
+ $modifier = new KeysetPaginationModifier(new KeysetPaginationConfig(10, [
+ sql_keyset_column('created_at', SortOrder::ASC),
+ sql_keyset_column('id', SortOrder::ASC),
+ ], [42]));
$parsed->traverse($modifier);
}
@@ -188,9 +188,9 @@ public function test_throws_when_no_columns() : void
$this->expectException(PaginationException::class);
$this->expectExceptionMessage('Keyset pagination requires at least one column');
- $parsed = pg_parse('SELECT * FROM users ORDER BY id');
+ $parsed = sql_parse('SELECT * FROM users ORDER BY id');
- $modifier = pg_keyset_pagination(10, []);
+ $modifier = new KeysetPaginationModifier(new KeysetPaginationConfig(10, []));
$parsed->traverse($modifier);
}
@@ -199,17 +199,17 @@ public function test_throws_when_no_order_by() : void
$this->expectException(PaginationException::class);
$this->expectExceptionMessage('Keyset pagination requires ORDER BY clause');
- $parsed = pg_parse('SELECT * FROM users');
+ $parsed = sql_parse('SELECT * FROM users');
- $modifier = pg_keyset_pagination(10, [pg_keyset_column('id', SortOrder::ASC)]);
+ $modifier = new KeysetPaginationModifier(new KeysetPaginationConfig(10, [sql_keyset_column('id', SortOrder::ASC)]));
$parsed->traverse($modifier);
}
public function test_with_existing_where_clause() : void
{
- $parsed = pg_parse('SELECT * FROM users WHERE active = true ORDER BY id');
+ $parsed = sql_parse('SELECT * FROM users WHERE active = true ORDER BY id');
- $modifier = pg_keyset_pagination(10, [pg_keyset_column('id', SortOrder::ASC)], [42]);
+ $modifier = new KeysetPaginationModifier(new KeysetPaginationConfig(10, [sql_keyset_column('id', SortOrder::ASC)], [42]));
$parsed->traverse($modifier);
self::assertSame(
diff --git a/src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/AST/Transformers/OffsetPaginationEdgeCasesTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/AST/Transformers/OffsetPaginationEdgeCasesTest.php
similarity index 89%
rename from src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/AST/Transformers/OffsetPaginationEdgeCasesTest.php
rename to src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/AST/Transformers/OffsetPaginationEdgeCasesTest.php
index 9a37aa8fe..f1cd065dc 100644
--- a/src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/AST/Transformers/OffsetPaginationEdgeCasesTest.php
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/AST/Transformers/OffsetPaginationEdgeCasesTest.php
@@ -2,9 +2,9 @@
declare(strict_types=1);
-namespace Flow\PgQuery\Tests\Unit\AST\Transformers;
+namespace Flow\PostgreSql\Tests\Unit\AST\Transformers;
-use function Flow\PgQuery\DSL\pg_to_paginated_query;
+use function Flow\PostgreSql\DSL\sql_to_paginated_query;
use PHPUnit\Framework\TestCase;
@@ -33,13 +33,13 @@ public function test_complex_aggregation_pagination() : void
ORDER BY product_count DESC, category_id
SQL;
- $page1 = pg_to_paginated_query($baseQuery, limit: 10, offset: 0);
+ $page1 = sql_to_paginated_query($baseQuery, limit: 10, offset: 0);
self::assertSame(
'SELECT category_id, count(*) AS product_count, avg(price) AS avg_price, min(price) AS min_price, max(price) AS max_price FROM products WHERE active = true GROUP BY category_id HAVING count(*) >= 5 ORDER BY product_count DESC, category_id LIMIT 10',
$page1
);
- $page2 = pg_to_paginated_query($baseQuery, limit: 10, offset: 10);
+ $page2 = sql_to_paginated_query($baseQuery, limit: 10, offset: 10);
self::assertSame(
'SELECT category_id, count(*) AS product_count, avg(price) AS avg_price, min(price) AS min_price, max(price) AS max_price FROM products WHERE active = true GROUP BY category_id HAVING count(*) >= 5 ORDER BY product_count DESC, category_id LIMIT 10 OFFSET 10',
$page2
@@ -65,13 +65,13 @@ public function test_iterate_cte_query() : void
ORDER BY level, name
SQL;
- $page1 = pg_to_paginated_query($baseQuery, limit: 50, offset: 0);
+ $page1 = sql_to_paginated_query($baseQuery, limit: 50, offset: 0);
self::assertSame(
'WITH RECURSIVE org_tree AS (SELECT id, name, manager_id, 1 AS level FROM employees WHERE manager_id IS NULL UNION ALL SELECT e.id, e.name, e.manager_id, ot.level + 1 FROM employees e JOIN org_tree ot ON e.manager_id = ot.id) SELECT id, name, level FROM org_tree ORDER BY level, name LIMIT 50',
$page1
);
- $page2 = pg_to_paginated_query($baseQuery, limit: 50, offset: 50);
+ $page2 = sql_to_paginated_query($baseQuery, limit: 50, offset: 50);
self::assertSame(
'WITH RECURSIVE org_tree AS (SELECT id, name, manager_id, 1 AS level FROM employees WHERE manager_id IS NULL UNION ALL SELECT e.id, e.name, e.manager_id, ot.level + 1 FROM employees e JOIN org_tree ot ON e.manager_id = ot.id) SELECT id, name, level FROM org_tree ORDER BY level, name LIMIT 50 OFFSET 50',
$page2
@@ -96,19 +96,19 @@ public function test_iterate_through_pages_with_joins() : void
ORDER BY o.created_at DESC, o.id
SQL;
- $page1 = pg_to_paginated_query($baseQuery, limit: 25, offset: 0);
+ $page1 = sql_to_paginated_query($baseQuery, limit: 25, offset: 0);
self::assertSame(
'SELECT u.id AS user_id, u.email, o.id AS order_id, o.total_amount, p.name AS product_name, oi.quantity FROM users u JOIN orders o ON u.id = o.user_id JOIN order_items oi ON o.id = oi.order_id JOIN products p ON oi.product_id = p.id WHERE o.status = \'completed\' ORDER BY o.created_at DESC, o.id LIMIT 25',
$page1
);
- $page2 = pg_to_paginated_query($baseQuery, limit: 25, offset: 25);
+ $page2 = sql_to_paginated_query($baseQuery, limit: 25, offset: 25);
self::assertSame(
'SELECT u.id AS user_id, u.email, o.id AS order_id, o.total_amount, p.name AS product_name, oi.quantity FROM users u JOIN orders o ON u.id = o.user_id JOIN order_items oi ON o.id = oi.order_id JOIN products p ON oi.product_id = p.id WHERE o.status = \'completed\' ORDER BY o.created_at DESC, o.id LIMIT 25 OFFSET 25',
$page2
);
- $page3 = pg_to_paginated_query($baseQuery, limit: 25, offset: 50);
+ $page3 = sql_to_paginated_query($baseQuery, limit: 25, offset: 50);
self::assertSame(
'SELECT u.id AS user_id, u.email, o.id AS order_id, o.total_amount, p.name AS product_name, oi.quantity FROM users u JOIN orders o ON u.id = o.user_id JOIN order_items oi ON o.id = oi.order_id JOIN products p ON oi.product_id = p.id WHERE o.status = \'completed\' ORDER BY o.created_at DESC, o.id LIMIT 25 OFFSET 50',
$page3
@@ -126,13 +126,13 @@ public function test_iterate_union_query() : void
ORDER BY created_at DESC
SQL;
- $page1 = pg_to_paginated_query($baseQuery, limit: 20, offset: 0);
+ $page1 = sql_to_paginated_query($baseQuery, limit: 20, offset: 0);
self::assertSame(
'SELECT * FROM ((SELECT id, \'order\' AS type, message, created_at FROM order_notifications UNION ALL SELECT id, \'payment\' AS type, message, created_at FROM payment_notifications) UNION ALL SELECT id, \'shipping\' AS type, message, created_at FROM shipping_notifications ORDER BY created_at DESC) _pagination_subq LIMIT 20',
$page1
);
- $page2 = pg_to_paginated_query($baseQuery, limit: 20, offset: 20);
+ $page2 = sql_to_paginated_query($baseQuery, limit: 20, offset: 20);
self::assertSame(
'SELECT * FROM ((SELECT id, \'order\' AS type, message, created_at FROM order_notifications UNION ALL SELECT id, \'payment\' AS type, message, created_at FROM payment_notifications) UNION ALL SELECT id, \'shipping\' AS type, message, created_at FROM shipping_notifications ORDER BY created_at DESC) _pagination_subq LIMIT 20 OFFSET 20',
$page2
@@ -164,13 +164,13 @@ public function test_nested_cte_pagination() : void
ORDER BY total_spent DESC
SQL;
- $page1 = pg_to_paginated_query($baseQuery, limit: 15, offset: 0);
+ $page1 = sql_to_paginated_query($baseQuery, limit: 15, offset: 0);
self::assertSame(
'WITH active_users AS (SELECT id, name, email FROM users WHERE status = \'active\'), user_orders AS (SELECT au.id AS user_id, au.name, count(o.id) AS order_count, sum(o.total_amount) AS total_spent FROM active_users au LEFT JOIN orders o ON au.id = o.user_id GROUP BY au.id, au.name) SELECT user_id, name, order_count, total_spent FROM user_orders WHERE order_count > 0 ORDER BY total_spent DESC LIMIT 15',
$page1
);
- $page2 = pg_to_paginated_query($baseQuery, limit: 15, offset: 15);
+ $page2 = sql_to_paginated_query($baseQuery, limit: 15, offset: 15);
self::assertSame(
'WITH active_users AS (SELECT id, name, email FROM users WHERE status = \'active\'), user_orders AS (SELECT au.id AS user_id, au.name, count(o.id) AS order_count, sum(o.total_amount) AS total_spent FROM active_users au LEFT JOIN orders o ON au.id = o.user_id GROUP BY au.id, au.name) SELECT user_id, name, order_count, total_spent FROM user_orders WHERE order_count > 0 ORDER BY total_spent DESC LIMIT 15 OFFSET 15',
$page2
@@ -196,13 +196,13 @@ public function test_pagination_with_lateral_subquery() : void
ORDER BY u.id
SQL;
- $page1 = pg_to_paginated_query($baseQuery, limit: 10, offset: 0);
+ $page1 = sql_to_paginated_query($baseQuery, limit: 10, offset: 0);
self::assertSame(
'SELECT u.id, u.name, recent_orders.order_id, recent_orders.amount FROM users u, LATERAL (SELECT o.id AS order_id, o.total_amount AS amount FROM orders o WHERE o.user_id = u.id ORDER BY o.created_at DESC LIMIT 3) recent_orders ORDER BY u.id LIMIT 10',
$page1
);
- $page2 = pg_to_paginated_query($baseQuery, limit: 10, offset: 10);
+ $page2 = sql_to_paginated_query($baseQuery, limit: 10, offset: 10);
self::assertSame(
'SELECT u.id, u.name, recent_orders.order_id, recent_orders.amount FROM users u, LATERAL (SELECT o.id AS order_id, o.total_amount AS amount FROM orders o WHERE o.user_id = u.id ORDER BY o.created_at DESC LIMIT 3) recent_orders ORDER BY u.id LIMIT 10 OFFSET 10',
$page2
@@ -234,19 +234,19 @@ public function test_product_catalog_with_filters() : void
ORDER BY r.avg_rating DESC NULLS LAST, p.name
SQL;
- $page1 = pg_to_paginated_query($baseQuery, limit: 24, offset: 0);
+ $page1 = sql_to_paginated_query($baseQuery, limit: 24, offset: 0);
self::assertSame(
'SELECT p.id, p.name, p.price, c.name AS category_name, b.name AS brand_name, COALESCE(r.avg_rating, 0) AS rating FROM products p JOIN categories c ON p.category_id = c.id JOIN brands b ON p.brand_id = b.id LEFT JOIN (SELECT product_id, avg(rating) AS avg_rating FROM reviews GROUP BY product_id) r ON p.id = r.product_id WHERE p.active = true AND p.price BETWEEN 10 AND 100 AND c.slug IN (\'electronics\', \'computers\') AND p.stock_quantity > 0 ORDER BY r.avg_rating DESC NULLS LAST, p.name LIMIT 24',
$page1
);
- $page2 = pg_to_paginated_query($baseQuery, limit: 24, offset: 24);
+ $page2 = sql_to_paginated_query($baseQuery, limit: 24, offset: 24);
self::assertSame(
'SELECT p.id, p.name, p.price, c.name AS category_name, b.name AS brand_name, COALESCE(r.avg_rating, 0) AS rating FROM products p JOIN categories c ON p.category_id = c.id JOIN brands b ON p.brand_id = b.id LEFT JOIN (SELECT product_id, avg(rating) AS avg_rating FROM reviews GROUP BY product_id) r ON p.id = r.product_id WHERE p.active = true AND p.price BETWEEN 10 AND 100 AND c.slug IN (\'electronics\', \'computers\') AND p.stock_quantity > 0 ORDER BY r.avg_rating DESC NULLS LAST, p.name LIMIT 24 OFFSET 24',
$page2
);
- $page3 = pg_to_paginated_query($baseQuery, limit: 24, offset: 48);
+ $page3 = sql_to_paginated_query($baseQuery, limit: 24, offset: 48);
self::assertSame(
'SELECT p.id, p.name, p.price, c.name AS category_name, b.name AS brand_name, COALESCE(r.avg_rating, 0) AS rating FROM products p JOIN categories c ON p.category_id = c.id JOIN brands b ON p.brand_id = b.id LEFT JOIN (SELECT product_id, avg(rating) AS avg_rating FROM reviews GROUP BY product_id) r ON p.id = r.product_id WHERE p.active = true AND p.price BETWEEN 10 AND 100 AND c.slug IN (\'electronics\', \'computers\') AND p.stock_quantity > 0 ORDER BY r.avg_rating DESC NULLS LAST, p.name LIMIT 24 OFFSET 48',
$page3
diff --git a/src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/AST/Transformers/PaginationModifierTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/AST/Transformers/PaginationModifierTest.php
similarity index 61%
rename from src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/AST/Transformers/PaginationModifierTest.php
rename to src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/AST/Transformers/PaginationModifierTest.php
index dc1823cd6..232e6fbd6 100644
--- a/src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/AST/Transformers/PaginationModifierTest.php
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/AST/Transformers/PaginationModifierTest.php
@@ -2,11 +2,12 @@
declare(strict_types=1);
-namespace Flow\PgQuery\Tests\Unit\AST\Transformers;
+namespace Flow\PostgreSql\Tests\Unit\AST\Transformers;
-use function Flow\PgQuery\DSL\{pg_pagination, pg_pagination_config, pg_parse};
-use Flow\PgQuery\AST\Traverser;
-use Flow\PgQuery\Exception\PaginationException;
+use function Flow\PostgreSql\DSL\sql_parse;
+use Flow\PostgreSql\AST\Transformers\{PaginationConfig, PaginationModifier};
+use Flow\PostgreSql\AST\Traverser;
+use Flow\PostgreSql\Exception\PaginationException;
use PHPUnit\Framework\TestCase;
final class PaginationModifierTest extends TestCase
@@ -20,9 +21,9 @@ protected function setUp() : void
public function test_add_pagination_to_simple_select() : void
{
- $parsed = pg_parse('SELECT * FROM users ORDER BY id');
+ $parsed = sql_parse('SELECT * FROM users ORDER BY id');
- $modifier = pg_pagination(10, 5);
+ $modifier = new PaginationModifier(new PaginationConfig(10, 5));
$traverser = new Traverser($modifier);
$traverser->traverse($parsed->raw());
@@ -32,9 +33,9 @@ public function test_add_pagination_to_simple_select() : void
public function test_add_pagination_without_offset() : void
{
- $parsed = pg_parse('SELECT id, name FROM users WHERE active = true');
+ $parsed = sql_parse('SELECT id, name FROM users WHERE active = true');
- $modifier = pg_pagination(20);
+ $modifier = new PaginationModifier(new PaginationConfig(20));
$traverser = new Traverser($modifier);
$traverser->traverse($parsed->raw());
@@ -44,9 +45,9 @@ public function test_add_pagination_without_offset() : void
public function test_clears_existing_offset_when_new_offset_is_zero() : void
{
- $parsed = pg_parse('SELECT * FROM users LIMIT 100 OFFSET 50');
+ $parsed = sql_parse('SELECT * FROM users LIMIT 100 OFFSET 50');
- $modifier = pg_pagination(10, 0);
+ $modifier = new PaginationModifier(new PaginationConfig(10, 0));
$parsed->traverse($modifier);
self::assertSame('SELECT * FROM users LIMIT 10', $parsed->deparse());
@@ -54,9 +55,9 @@ public function test_clears_existing_offset_when_new_offset_is_zero() : void
public function test_cte_main_query_gets_paginated() : void
{
- $parsed = pg_parse('WITH active AS (SELECT * FROM users WHERE active = true) SELECT * FROM active');
+ $parsed = sql_parse('WITH active AS (SELECT * FROM users WHERE active = true) SELECT * FROM active');
- $modifier = pg_pagination(10);
+ $modifier = new PaginationModifier(new PaginationConfig(10));
$traverser = new Traverser($modifier);
$traverser->traverse($parsed->raw());
@@ -66,9 +67,9 @@ public function test_cte_main_query_gets_paginated() : void
public function test_deeply_nested_subqueries() : void
{
- $parsed = pg_parse('SELECT * FROM (SELECT * FROM (SELECT id FROM users) AS inner1) AS outer1');
+ $parsed = sql_parse('SELECT * FROM (SELECT * FROM (SELECT id FROM users) AS inner1) AS outer1');
- $modifier = pg_pagination(10);
+ $modifier = new PaginationModifier(new PaginationConfig(10));
$parsed->traverse($modifier);
self::assertSame('SELECT * FROM (SELECT * FROM (SELECT id FROM users) inner1) outer1 LIMIT 10', $parsed->deparse());
@@ -76,9 +77,9 @@ public function test_deeply_nested_subqueries() : void
public function test_distinct_query() : void
{
- $parsed = pg_parse('SELECT DISTINCT name FROM users');
+ $parsed = sql_parse('SELECT DISTINCT name FROM users');
- $modifier = pg_pagination(10);
+ $modifier = new PaginationModifier(new PaginationConfig(10));
$traverser = new Traverser($modifier);
$traverser->traverse($parsed->raw());
@@ -88,9 +89,9 @@ public function test_distinct_query() : void
public function test_except_query_wraps_in_subquery() : void
{
- $parsed = pg_parse('SELECT id FROM users EXCEPT SELECT id FROM banned');
+ $parsed = sql_parse('SELECT id FROM users EXCEPT SELECT id FROM banned');
- $modifier = pg_pagination(15);
+ $modifier = new PaginationModifier(new PaginationConfig(15));
$traverser = new Traverser($modifier);
$traverser->traverse($parsed->raw());
@@ -100,9 +101,9 @@ public function test_except_query_wraps_in_subquery() : void
public function test_group_by_having_query() : void
{
- $parsed = pg_parse('SELECT dept, COUNT(*) as cnt FROM users GROUP BY dept HAVING COUNT(*) > 5');
+ $parsed = sql_parse('SELECT dept, COUNT(*) as cnt FROM users GROUP BY dept HAVING COUNT(*) > 5');
- $modifier = pg_pagination(10);
+ $modifier = new PaginationModifier(new PaginationConfig(10));
$traverser = new Traverser($modifier);
$traverser->traverse($parsed->raw());
@@ -112,9 +113,9 @@ public function test_group_by_having_query() : void
public function test_inner_join() : void
{
- $parsed = pg_parse('SELECT u.id, o.amount FROM users u INNER JOIN orders o ON u.id = o.user_id');
+ $parsed = sql_parse('SELECT u.id, o.amount FROM users u INNER JOIN orders o ON u.id = o.user_id');
- $modifier = pg_pagination(10);
+ $modifier = new PaginationModifier(new PaginationConfig(10));
$parsed->traverse($modifier);
self::assertSame('SELECT u.id, o.amount FROM users u JOIN orders o ON u.id = o.user_id LIMIT 10', $parsed->deparse());
@@ -122,9 +123,9 @@ public function test_inner_join() : void
public function test_intersect_query_wraps_in_subquery() : void
{
- $parsed = pg_parse('SELECT id FROM users INTERSECT SELECT id FROM admins ORDER BY id');
+ $parsed = sql_parse('SELECT id FROM users INTERSECT SELECT id FROM admins ORDER BY id');
- $modifier = pg_pagination(5, 2);
+ $modifier = new PaginationModifier(new PaginationConfig(5, 2));
$traverser = new Traverser($modifier);
$traverser->traverse($parsed->raw());
@@ -134,9 +135,9 @@ public function test_intersect_query_wraps_in_subquery() : void
public function test_lateral_join() : void
{
- $parsed = pg_parse('SELECT u.id, latest.amount FROM users u, LATERAL (SELECT amount FROM orders WHERE user_id = u.id ORDER BY created_at DESC LIMIT 1) AS latest');
+ $parsed = sql_parse('SELECT u.id, latest.amount FROM users u, LATERAL (SELECT amount FROM orders WHERE user_id = u.id ORDER BY created_at DESC LIMIT 1) AS latest');
- $modifier = pg_pagination(10);
+ $modifier = new PaginationModifier(new PaginationConfig(10));
$parsed->traverse($modifier);
self::assertSame('SELECT u.id, latest.amount FROM users u, LATERAL (SELECT amount FROM orders WHERE user_id = u.id ORDER BY created_at DESC LIMIT 1) latest LIMIT 10', $parsed->deparse());
@@ -144,9 +145,9 @@ public function test_lateral_join() : void
public function test_left_join() : void
{
- $parsed = pg_parse('SELECT u.id, o.amount FROM users u LEFT JOIN orders o ON u.id = o.user_id');
+ $parsed = sql_parse('SELECT u.id, o.amount FROM users u LEFT JOIN orders o ON u.id = o.user_id');
- $modifier = pg_pagination(10);
+ $modifier = new PaginationModifier(new PaginationConfig(10));
$parsed->traverse($modifier);
self::assertSame('SELECT u.id, o.amount FROM users u LEFT JOIN orders o ON u.id = o.user_id LIMIT 10', $parsed->deparse());
@@ -154,9 +155,9 @@ public function test_left_join() : void
public function test_multiple_joins() : void
{
- $parsed = pg_parse('SELECT u.id, o.amount, p.name FROM users u JOIN orders o ON u.id = o.user_id JOIN products p ON o.product_id = p.id');
+ $parsed = sql_parse('SELECT u.id, o.amount, p.name FROM users u JOIN orders o ON u.id = o.user_id JOIN products p ON o.product_id = p.id');
- $modifier = pg_pagination(10);
+ $modifier = new PaginationModifier(new PaginationConfig(10));
$parsed->traverse($modifier);
self::assertSame('SELECT u.id, o.amount, p.name FROM users u JOIN orders o ON u.id = o.user_id JOIN products p ON o.product_id = p.id LIMIT 10', $parsed->deparse());
@@ -164,9 +165,9 @@ public function test_multiple_joins() : void
public function test_nested_union() : void
{
- $parsed = pg_parse('(SELECT id FROM users UNION SELECT id FROM admins) UNION SELECT id FROM guests');
+ $parsed = sql_parse('(SELECT id FROM users UNION SELECT id FROM admins) UNION SELECT id FROM guests');
- $modifier = pg_pagination(10);
+ $modifier = new PaginationModifier(new PaginationConfig(10));
$parsed->traverse($modifier);
self::assertSame('SELECT * FROM ((SELECT id FROM users UNION SELECT id FROM admins) UNION SELECT id FROM guests) _pagination_subq LIMIT 10', $parsed->deparse());
@@ -174,9 +175,9 @@ public function test_nested_union() : void
public function test_offset_with_order_by_works() : void
{
- $parsed = pg_parse('SELECT * FROM users ORDER BY name ASC');
+ $parsed = sql_parse('SELECT * FROM users ORDER BY name ASC');
- $modifier = pg_pagination(10, 20);
+ $modifier = new PaginationModifier(new PaginationConfig(10, 20));
$parsed->traverse($modifier);
@@ -188,18 +189,18 @@ public function test_offset_without_order_by_throws_exception() : void
$this->expectException(PaginationException::class);
$this->expectExceptionMessage('OFFSET without ORDER BY produces non-deterministic results');
- $parsed = pg_parse('SELECT * FROM users');
+ $parsed = sql_parse('SELECT * FROM users');
- $modifier = pg_pagination(10, 5);
+ $modifier = new PaginationModifier(new PaginationConfig(10, 5));
$parsed->traverse($modifier);
}
public function test_order_by_query() : void
{
- $parsed = pg_parse('SELECT * FROM users ORDER BY name ASC');
+ $parsed = sql_parse('SELECT * FROM users ORDER BY name ASC');
- $modifier = pg_pagination(10);
+ $modifier = new PaginationModifier(new PaginationConfig(10));
$traverser = new Traverser($modifier);
$traverser->traverse($parsed->raw());
@@ -209,9 +210,9 @@ public function test_order_by_query() : void
public function test_overrides_existing_limit() : void
{
- $parsed = pg_parse('SELECT * FROM users LIMIT 100');
+ $parsed = sql_parse('SELECT * FROM users LIMIT 100');
- $modifier = pg_pagination(10);
+ $modifier = new PaginationModifier(new PaginationConfig(10));
$parsed->traverse($modifier);
@@ -220,9 +221,9 @@ public function test_overrides_existing_limit() : void
public function test_overrides_existing_limit_and_offset() : void
{
- $parsed = pg_parse('SELECT * FROM users ORDER BY id LIMIT 100 OFFSET 50');
+ $parsed = sql_parse('SELECT * FROM users ORDER BY id LIMIT 100 OFFSET 50');
- $modifier = pg_pagination(10, 5);
+ $modifier = new PaginationModifier(new PaginationConfig(10, 5));
$parsed->traverse($modifier);
@@ -231,7 +232,7 @@ public function test_overrides_existing_limit_and_offset() : void
public function test_pagination_config_default_offset() : void
{
- $config = pg_pagination_config(20);
+ $config = new PaginationConfig(20);
self::assertSame(20, $config->limit);
self::assertSame(0, $config->offset);
@@ -239,7 +240,7 @@ public function test_pagination_config_default_offset() : void
public function test_pagination_config_returns_config_object() : void
{
- $config = pg_pagination_config(10, 5);
+ $config = new PaginationConfig(10, 5);
self::assertSame(10, $config->limit);
self::assertSame(5, $config->offset);
@@ -247,9 +248,9 @@ public function test_pagination_config_returns_config_object() : void
public function test_self_join() : void
{
- $parsed = pg_parse('SELECT e.name AS employee, m.name AS manager FROM employees e LEFT JOIN employees m ON e.manager_id = m.id');
+ $parsed = sql_parse('SELECT e.name AS employee, m.name AS manager FROM employees e LEFT JOIN employees m ON e.manager_id = m.id');
- $modifier = pg_pagination(10);
+ $modifier = new PaginationModifier(new PaginationConfig(10));
$parsed->traverse($modifier);
self::assertSame('SELECT e.name AS employee, m.name AS manager FROM employees e LEFT JOIN employees m ON e.manager_id = m.id LIMIT 10', $parsed->deparse());
@@ -257,9 +258,9 @@ public function test_self_join() : void
public function test_subquery_in_from_clause_not_paginated() : void
{
- $parsed = pg_parse('SELECT * FROM (SELECT id FROM users) AS sub');
+ $parsed = sql_parse('SELECT * FROM (SELECT id FROM users) AS sub');
- $modifier = pg_pagination(10);
+ $modifier = new PaginationModifier(new PaginationConfig(10));
$traverser = new Traverser($modifier);
$traverser->traverse($parsed->raw());
@@ -269,9 +270,9 @@ public function test_subquery_in_from_clause_not_paginated() : void
public function test_subquery_in_where_clause_not_paginated() : void
{
- $parsed = pg_parse('SELECT * FROM users WHERE id IN (SELECT user_id FROM orders)');
+ $parsed = sql_parse('SELECT * FROM users WHERE id IN (SELECT user_id FROM orders)');
- $modifier = pg_pagination(10);
+ $modifier = new PaginationModifier(new PaginationConfig(10));
$traverser = new Traverser($modifier);
$traverser->traverse($parsed->raw());
@@ -281,9 +282,9 @@ public function test_subquery_in_where_clause_not_paginated() : void
public function test_union_all() : void
{
- $parsed = pg_parse('SELECT id FROM users UNION ALL SELECT id FROM admins');
+ $parsed = sql_parse('SELECT id FROM users UNION ALL SELECT id FROM admins');
- $modifier = pg_pagination(10);
+ $modifier = new PaginationModifier(new PaginationConfig(10));
$parsed->traverse($modifier);
self::assertSame('SELECT * FROM (SELECT id FROM users UNION ALL SELECT id FROM admins) _pagination_subq LIMIT 10', $parsed->deparse());
@@ -291,9 +292,9 @@ public function test_union_all() : void
public function test_union_query_wraps_in_subquery() : void
{
- $parsed = pg_parse('SELECT id FROM users UNION SELECT id FROM admins');
+ $parsed = sql_parse('SELECT id FROM users UNION SELECT id FROM admins');
- $modifier = pg_pagination(10);
+ $modifier = new PaginationModifier(new PaginationConfig(10));
$traverser = new Traverser($modifier);
$traverser->traverse($parsed->raw());
@@ -303,9 +304,9 @@ public function test_union_query_wraps_in_subquery() : void
public function test_values_clause() : void
{
- $parsed = pg_parse('SELECT * FROM (VALUES (1, \'a\'), (2, \'b\'), (3, \'c\')) AS t(id, name)');
+ $parsed = sql_parse('SELECT * FROM (VALUES (1, \'a\'), (2, \'b\'), (3, \'c\')) AS t(id, name)');
- $modifier = pg_pagination(2);
+ $modifier = new PaginationModifier(new PaginationConfig(2));
$parsed->traverse($modifier);
self::assertSame('SELECT * FROM (VALUES (1, \'a\'), (2, \'b\'), (3, \'c\')) t(id, name) LIMIT 2', $parsed->deparse());
@@ -313,9 +314,9 @@ public function test_values_clause() : void
public function test_window_function() : void
{
- $parsed = pg_parse('SELECT id, name, ROW_NUMBER() OVER (ORDER BY created_at) as rn FROM users');
+ $parsed = sql_parse('SELECT id, name, ROW_NUMBER() OVER (ORDER BY created_at) as rn FROM users');
- $modifier = pg_pagination(10);
+ $modifier = new PaginationModifier(new PaginationConfig(10));
$parsed->traverse($modifier);
self::assertSame('SELECT id, name, row_number() OVER (ORDER BY created_at) AS rn FROM users LIMIT 10', $parsed->deparse());
@@ -323,9 +324,9 @@ public function test_window_function() : void
public function test_window_function_with_partition() : void
{
- $parsed = pg_parse('SELECT id, dept, RANK() OVER (PARTITION BY dept ORDER BY salary DESC) as rank FROM employees');
+ $parsed = sql_parse('SELECT id, dept, RANK() OVER (PARTITION BY dept ORDER BY salary DESC) as rank FROM employees');
- $modifier = pg_pagination(10);
+ $modifier = new PaginationModifier(new PaginationConfig(10));
$parsed->traverse($modifier);
self::assertSame('SELECT id, dept, rank() OVER (PARTITION BY dept ORDER BY salary DESC) AS rank FROM employees LIMIT 10', $parsed->deparse());
@@ -333,9 +334,9 @@ public function test_window_function_with_partition() : void
public function test_with_pagination_helper_method() : void
{
- $parsed = pg_parse('SELECT * FROM users ORDER BY id');
+ $parsed = sql_parse('SELECT * FROM users ORDER BY id');
- $modifier = pg_pagination(25, 50);
+ $modifier = new PaginationModifier(new PaginationConfig(25, 50));
$parsed->traverse($modifier);
diff --git a/src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/AST/TraverserTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/AST/TraverserTest.php
similarity index 96%
rename from src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/AST/TraverserTest.php
rename to src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/AST/TraverserTest.php
index 19b60360c..d77bc46cd 100644
--- a/src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/AST/TraverserTest.php
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/AST/TraverserTest.php
@@ -2,11 +2,11 @@
declare(strict_types=1);
-namespace Flow\PgQuery\Tests\Unit\AST;
+namespace Flow\PostgreSql\Tests\Unit\AST;
-use Flow\PgQuery\AST\{ModificationContext, NodeModifier, NodeVisitor, Traverser};
-use Flow\PgQuery\AST\Visitors\{ColumnRefCollector, FuncCallCollector, RangeVarCollector};
-use Flow\PgQuery\Protobuf\AST\{ColumnRef, Node, ParseResult, SelectStmt};
+use Flow\PostgreSql\AST\{ModificationContext, NodeModifier, NodeVisitor, Traverser};
+use Flow\PostgreSql\AST\Visitors\{ColumnRefCollector, FuncCallCollector, RangeVarCollector};
+use Flow\PostgreSql\Protobuf\AST\{ColumnRef, Node, ParseResult, SelectStmt};
use PHPUnit\Framework\TestCase;
final class TraverserTest extends TestCase
@@ -167,17 +167,17 @@ public function modify(object $node, ModificationContext $context) : int|object|
{
/** @var SelectStmt $node */
if ($context->isTopLevel()) {
- $integer = new \Flow\PgQuery\Protobuf\AST\Integer();
+ $integer = new \Flow\PostgreSql\Protobuf\AST\Integer();
$integer->setIval(10);
- $aConst = new \Flow\PgQuery\Protobuf\AST\A_Const();
+ $aConst = new \Flow\PostgreSql\Protobuf\AST\A_Const();
/** @phpstan-ignore argument.type */
$aConst->setIval($integer);
$limitNode = new Node();
$limitNode->setAConst($aConst);
- $node->setLimitOption(\Flow\PgQuery\Protobuf\AST\LimitOption::LIMIT_OPTION_COUNT);
+ $node->setLimitOption(\Flow\PostgreSql\Protobuf\AST\LimitOption::LIMIT_OPTION_COUNT);
$node->setLimitCount($limitNode);
}
diff --git a/src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/AST/Visitors/ColumnRefCollectorTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/AST/Visitors/ColumnRefCollectorTest.php
similarity index 95%
rename from src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/AST/Visitors/ColumnRefCollectorTest.php
rename to src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/AST/Visitors/ColumnRefCollectorTest.php
index e4e9474c4..98aae346e 100644
--- a/src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/AST/Visitors/ColumnRefCollectorTest.php
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/AST/Visitors/ColumnRefCollectorTest.php
@@ -2,11 +2,11 @@
declare(strict_types=1);
-namespace Flow\PgQuery\Tests\Unit\AST\Visitors;
+namespace Flow\PostgreSql\Tests\Unit\AST\Visitors;
-use Flow\PgQuery\AST\Traverser;
-use Flow\PgQuery\AST\Visitors\ColumnRefCollector;
-use Flow\PgQuery\Protobuf\AST\{ColumnRef, ParseResult};
+use Flow\PostgreSql\AST\Traverser;
+use Flow\PostgreSql\AST\Visitors\ColumnRefCollector;
+use Flow\PostgreSql\Protobuf\AST\{ColumnRef, ParseResult};
use PHPUnit\Framework\TestCase;
final class ColumnRefCollectorTest extends TestCase
diff --git a/src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/AST/Visitors/FuncCallCollectorTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/AST/Visitors/FuncCallCollectorTest.php
similarity index 94%
rename from src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/AST/Visitors/FuncCallCollectorTest.php
rename to src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/AST/Visitors/FuncCallCollectorTest.php
index 900f06b9e..267fbf870 100644
--- a/src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/AST/Visitors/FuncCallCollectorTest.php
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/AST/Visitors/FuncCallCollectorTest.php
@@ -2,11 +2,11 @@
declare(strict_types=1);
-namespace Flow\PgQuery\Tests\Unit\AST\Visitors;
+namespace Flow\PostgreSql\Tests\Unit\AST\Visitors;
-use Flow\PgQuery\AST\Traverser;
-use Flow\PgQuery\AST\Visitors\FuncCallCollector;
-use Flow\PgQuery\Protobuf\AST\{FuncCall, ParseResult};
+use Flow\PostgreSql\AST\Traverser;
+use Flow\PostgreSql\AST\Visitors\FuncCallCollector;
+use Flow\PostgreSql\Protobuf\AST\{FuncCall, ParseResult};
use PHPUnit\Framework\TestCase;
final class FuncCallCollectorTest extends TestCase
diff --git a/src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/AST/Visitors/RangeVarCollectorTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/AST/Visitors/RangeVarCollectorTest.php
similarity index 96%
rename from src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/AST/Visitors/RangeVarCollectorTest.php
rename to src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/AST/Visitors/RangeVarCollectorTest.php
index f7400c011..fe5476894 100644
--- a/src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/AST/Visitors/RangeVarCollectorTest.php
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/AST/Visitors/RangeVarCollectorTest.php
@@ -2,11 +2,11 @@
declare(strict_types=1);
-namespace Flow\PgQuery\Tests\Unit\AST\Visitors;
+namespace Flow\PostgreSql\Tests\Unit\AST\Visitors;
-use Flow\PgQuery\AST\Traverser;
-use Flow\PgQuery\AST\Visitors\RangeVarCollector;
-use Flow\PgQuery\Protobuf\AST\{ParseResult, RangeVar};
+use Flow\PostgreSql\AST\Traverser;
+use Flow\PostgreSql\AST\Visitors\RangeVarCollector;
+use Flow\PostgreSql\Protobuf\AST\{ParseResult, RangeVar};
use PHPUnit\Framework\TestCase;
final class RangeVarCollectorTest extends TestCase
diff --git a/src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/NamedParameterNormalizerTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/NamedParameterNormalizerTest.php
similarity index 97%
rename from src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/NamedParameterNormalizerTest.php
rename to src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/NamedParameterNormalizerTest.php
index 764f51574..19b373afb 100644
--- a/src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/NamedParameterNormalizerTest.php
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/NamedParameterNormalizerTest.php
@@ -2,9 +2,9 @@
declare(strict_types=1);
-namespace Flow\PgQuery\Tests\Unit;
+namespace Flow\PostgreSql\Tests\Unit;
-use Flow\PgQuery\NamedParameterNormalizer;
+use Flow\PostgreSql\NamedParameterNormalizer;
use PHPUnit\Framework\TestCase;
final class NamedParameterNormalizerTest extends TestCase
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/ParsedQueryTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/ParsedQueryTest.php
new file mode 100644
index 000000000..b7109f279
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/ParsedQueryTest.php
@@ -0,0 +1,400 @@
+forTable('u');
+ $orderColumns = sql_query_columns($result)->forTable('o');
+
+ self::assertCount(2, $userColumns);
+ $userColumnNames = \array_map(fn (Column $c) => $c->name(), $userColumns);
+ self::assertContains('id', $userColumnNames);
+
+ self::assertCount(2, $orderColumns);
+ $orderColumnNames = \array_map(fn (Column $c) => $c->name(), $orderColumns);
+ self::assertContains('order_date', $orderColumnNames);
+ self::assertContains('user_id', $orderColumnNames);
+ }
+
+ public function test_columns_from_select() : void
+ {
+ $result = sql_parse('SELECT id, name FROM users');
+
+ $columns = sql_query_columns($result)->all();
+
+ self::assertCount(2, $columns);
+
+ $columnNames = \array_map(fn (Column $c) => $c->name(), $columns);
+ self::assertContains('id', $columnNames);
+ self::assertContains('name', $columnNames);
+ }
+
+ public function test_columns_from_where_clause() : void
+ {
+ $result = sql_parse('SELECT 1 FROM users WHERE active = true AND name LIKE \'%john%\'');
+
+ $columns = sql_query_columns($result)->all();
+
+ $columnNames = \array_map(fn (Column $c) => $c->name(), $columns);
+ self::assertContains('active', $columnNames);
+ self::assertContains('name', $columnNames);
+ }
+
+ public function test_columns_with_star() : void
+ {
+ $result = sql_parse('SELECT * FROM users');
+
+ $columns = sql_query_columns($result)->all();
+
+ self::assertCount(1, $columns);
+ self::assertSame('*', $columns[0]->name());
+ self::assertNull($columns[0]->table());
+ }
+
+ public function test_columns_with_table_qualified_star() : void
+ {
+ $result = sql_parse('SELECT u.* FROM users u');
+
+ $columns = sql_query_columns($result)->all();
+
+ self::assertCount(1, $columns);
+ self::assertSame('*', $columns[0]->name());
+ self::assertSame('u', $columns[0]->table());
+ }
+
+ public function test_columns_with_table_qualifier() : void
+ {
+ $result = sql_parse('SELECT u.id, u.name FROM users u');
+
+ $columns = sql_query_columns($result)->all();
+
+ self::assertCount(2, $columns);
+
+ foreach ($columns as $column) {
+ self::assertSame('u', $column->table());
+ }
+ }
+
+ public function test_functions_from_select() : void
+ {
+ $result = sql_parse('SELECT COUNT(*), SUM(amount) FROM orders');
+
+ $functions = sql_query_functions($result)->all();
+
+ self::assertCount(2, $functions);
+
+ $functionNames = \array_map(fn (FunctionCall $f) => $f->name(), $functions);
+ self::assertContains('count', $functionNames);
+ self::assertContains('sum', $functionNames);
+ }
+
+ public function test_functions_nested() : void
+ {
+ $result = sql_parse('SELECT UPPER(CONCAT(first_name, last_name)) FROM users');
+
+ $functions = sql_query_functions($result)->all();
+
+ self::assertCount(2, $functions);
+
+ $functionNames = \array_map(fn (FunctionCall $f) => $f->name(), $functions);
+ self::assertContains('upper', $functionNames);
+ self::assertContains('concat', $functionNames);
+ }
+
+ public function test_functions_with_schema() : void
+ {
+ $result = sql_parse('SELECT pg_catalog.now()');
+
+ $functions = sql_query_functions($result)->all();
+
+ self::assertCount(1, $functions);
+ self::assertSame('now', $functions[0]->name());
+ self::assertSame('pg_catalog', $functions[0]->schema());
+ }
+
+ public function test_raw_returns_parse_result() : void
+ {
+ $result = sql_parse('SELECT 1');
+
+ self::assertInstanceOf(ParseResult::class, $result->raw());
+ }
+
+ public function test_tables_from_cte() : void
+ {
+ $result = sql_parse('WITH active_users AS (SELECT * FROM users WHERE active = true) SELECT * FROM active_users');
+
+ $tables = sql_query_tables($result)->all();
+
+ self::assertCount(2, $tables);
+
+ $tableNames = \array_map(fn (Table $t) => $t->name(), $tables);
+ self::assertContains('users', $tableNames);
+ self::assertContains('active_users', $tableNames);
+ }
+
+ public function test_tables_from_delete() : void
+ {
+ $result = sql_parse('DELETE FROM users WHERE id = 1');
+
+ $tables = sql_query_tables($result)->all();
+
+ self::assertCount(1, $tables);
+ self::assertSame('users', $tables[0]->name());
+ }
+
+ public function test_tables_from_insert() : void
+ {
+ $result = sql_parse('INSERT INTO users (name) VALUES (\'john\')');
+
+ $tables = sql_query_tables($result)->all();
+
+ self::assertCount(1, $tables);
+ self::assertSame('users', $tables[0]->name());
+ }
+
+ public function test_tables_from_join() : void
+ {
+ $result = sql_parse('SELECT * FROM users u JOIN orders o ON u.id = o.user_id');
+
+ $tables = sql_query_tables($result)->all();
+
+ self::assertCount(2, $tables);
+
+ $tableNames = \array_map(fn (Table $t) => $t->name(), $tables);
+ self::assertContains('users', $tableNames);
+ self::assertContains('orders', $tableNames);
+ }
+
+ public function test_tables_from_simple_select() : void
+ {
+ $result = sql_parse('SELECT * FROM users');
+
+ $tables = sql_query_tables($result)->all();
+
+ self::assertCount(1, $tables);
+ self::assertInstanceOf(Table::class, $tables[0]);
+ self::assertSame('users', $tables[0]->name());
+ self::assertNull($tables[0]->schema());
+ self::assertNull($tables[0]->alias());
+ }
+
+ public function test_tables_from_subquery() : void
+ {
+ $result = sql_parse('SELECT * FROM (SELECT * FROM orders) AS sub');
+
+ $tables = sql_query_tables($result)->all();
+
+ self::assertCount(1, $tables);
+ self::assertSame('orders', $tables[0]->name());
+ }
+
+ public function test_tables_from_update() : void
+ {
+ $result = sql_parse('UPDATE users SET name = \'john\' WHERE id = 1');
+
+ $tables = sql_query_tables($result)->all();
+
+ self::assertCount(1, $tables);
+ self::assertSame('users', $tables[0]->name());
+ }
+
+ public function test_tables_with_alias() : void
+ {
+ $result = sql_parse('SELECT * FROM users AS u');
+
+ $tables = sql_query_tables($result)->all();
+
+ self::assertCount(1, $tables);
+ self::assertSame('users', $tables[0]->name());
+ self::assertSame('u', $tables[0]->alias());
+ }
+
+ public function test_tables_with_schema() : void
+ {
+ $result = sql_parse('SELECT * FROM public.users');
+
+ $tables = sql_query_tables($result)->all();
+
+ self::assertCount(1, $tables);
+ self::assertSame('users', $tables[0]->name());
+ self::assertSame('public', $tables[0]->schema());
+ }
+
+ public function test_to_delete_builder() : void
+ {
+ $builder = sql_parse('DELETE FROM users WHERE id = 1')->toDeleteBuilder();
+
+ self::assertInstanceOf(DeleteBuilder::class, $builder);
+ }
+
+ public function test_to_delete_builder_throws_on_wrong_type() : void
+ {
+ $this->expectException(\InvalidArgumentException::class);
+ $this->expectExceptionMessage('Query is not a DELETE statement');
+
+ sql_parse('SELECT * FROM users')->toDeleteBuilder();
+ }
+
+ public function test_to_insert_builder() : void
+ {
+ $builder = sql_parse("INSERT INTO users (name) VALUES ('John')")->toInsertBuilder();
+
+ self::assertInstanceOf(InsertBuilder::class, $builder);
+ }
+
+ public function test_to_insert_builder_throws_on_wrong_type() : void
+ {
+ $this->expectException(\InvalidArgumentException::class);
+ $this->expectExceptionMessage('Query is not an INSERT statement');
+
+ sql_parse('SELECT * FROM users')->toInsertBuilder();
+ }
+
+ public function test_to_query_builder_delete() : void
+ {
+ $builder = sql_parse('DELETE FROM users WHERE id = 1')->toQueryBuilder();
+
+ self::assertInstanceOf(DeleteBuilder::class, $builder);
+ }
+
+ public function test_to_query_builder_dsl_function() : void
+ {
+ $builder = sql_to_query_builder('SELECT * FROM users');
+
+ self::assertInstanceOf(SelectBuilder::class, $builder);
+ }
+
+ public function test_to_query_builder_insert() : void
+ {
+ $builder = sql_parse("INSERT INTO users (name) VALUES ('John')")->toQueryBuilder();
+
+ self::assertInstanceOf(InsertBuilder::class, $builder);
+ }
+
+ public function test_to_query_builder_modify_and_deparse() : void
+ {
+ $builder = sql_parse('SELECT * FROM users')->toQueryBuilder();
+
+ self::assertInstanceOf(SelectBuilder::class, $builder);
+
+ $modified = $builder
+ ->where(cond_and(
+ eq(col('id'), literal(1)),
+ gt(col('age'), literal(18))
+ ))
+ ->limit(10);
+
+ $sql = sql_parse('SELECT 1')->raw();
+ $rawStmt = new RawStmt();
+ $node = new Node();
+ $node->setSelectStmt($modified->toAst());
+ $rawStmt->setStmt($node);
+ $sql->setStmts([$rawStmt]);
+
+ $result = (new ParsedQuery($sql))->deparse();
+
+ self::assertSame('SELECT * FROM users WHERE id = 1 AND age > 18 LIMIT 10', $result);
+ }
+
+ public function test_to_query_builder_select() : void
+ {
+ $builder = sql_parse('SELECT * FROM users')->toQueryBuilder();
+
+ self::assertInstanceOf(SelectBuilder::class, $builder);
+ }
+
+ public function test_to_query_builder_throws_on_multiple_statements() : void
+ {
+ $this->expectException(\InvalidArgumentException::class);
+ $this->expectExceptionMessage('Multiple statements found. Use pg_split() to parse statements individually.');
+
+ sql_parse('SELECT 1; SELECT 2')->toQueryBuilder();
+ }
+
+ public function test_to_query_builder_update() : void
+ {
+ $builder = sql_parse("UPDATE users SET name = 'John' WHERE id = 1")->toQueryBuilder();
+
+ self::assertInstanceOf(UpdateBuilder::class, $builder);
+ }
+
+ public function test_to_select_builder() : void
+ {
+ $builder = sql_parse('SELECT * FROM users')->toSelectBuilder();
+
+ self::assertInstanceOf(SelectBuilder::class, $builder);
+ }
+
+ public function test_to_select_builder_throws_on_wrong_type() : void
+ {
+ $this->expectException(\InvalidArgumentException::class);
+ $this->expectExceptionMessage('Query is not a SELECT statement');
+
+ sql_parse('DELETE FROM users')->toSelectBuilder();
+ }
+
+ public function test_to_update_builder() : void
+ {
+ $builder = sql_parse("UPDATE users SET name = 'John' WHERE id = 1")->toUpdateBuilder();
+
+ self::assertInstanceOf(UpdateBuilder::class, $builder);
+ }
+
+ public function test_to_update_builder_throws_on_wrong_type() : void
+ {
+ $this->expectException(\InvalidArgumentException::class);
+ $this->expectExceptionMessage('Query is not an UPDATE statement');
+
+ sql_parse('SELECT * FROM users')->toUpdateBuilder();
+ }
+
+ public function test_traverse_with_multiple_visitors() : void
+ {
+ $result = sql_parse('SELECT COUNT(id), name FROM users WHERE active = true');
+
+ $columnCollector = new ColumnRefCollector();
+ $funcCollector = new FuncCallCollector();
+ $rangeVarCollector = new RangeVarCollector();
+
+ $result->traverse($columnCollector, $funcCollector, $rangeVarCollector);
+
+ self::assertCount(3, $columnCollector->getColumnRefs());
+ self::assertCount(1, $funcCollector->getFuncCalls());
+ self::assertCount(1, $rangeVarCollector->getRangeVars());
+ }
+
+ public function test_traverse_with_single_visitor() : void
+ {
+ $result = sql_parse('SELECT id, name FROM users');
+
+ $collector = new ColumnRefCollector();
+ $result->traverse($collector);
+
+ self::assertCount(2, $collector->getColumnRefs());
+ }
+}
diff --git a/src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/ParserTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/ParserTest.php
similarity index 80%
rename from src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/ParserTest.php
rename to src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/ParserTest.php
index fdaa37f8a..1de6656cc 100644
--- a/src/lib/pg-query/tests/Flow/PgQuery/Tests/Unit/ParserTest.php
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/ParserTest.php
@@ -2,10 +2,10 @@
declare(strict_types=1);
-namespace Flow\PgQuery\Tests\Unit;
+namespace Flow\PostgreSql\Tests\Unit;
-use function Flow\PgQuery\DSL\{pg_deparse, pg_deparse_options, pg_fingerprint, pg_format, pg_normalize, pg_normalize_utility, pg_parse, pg_parser, pg_split, pg_summary};
-use Flow\PgQuery\ParsedQuery;
+use function Flow\PostgreSql\DSL\{sql_deparse, sql_deparse_options, sql_fingerprint, sql_format, sql_normalize, sql_normalize_utility, sql_parse, sql_parser, sql_split, sql_summary};
+use Flow\PostgreSql\ParsedQuery;
use PHPUnit\Framework\TestCase;
final class ParserTest extends TestCase
@@ -23,7 +23,7 @@ public function test_deparse_complex_query() : void
self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
}
- $parser = pg_parser();
+ $parser = sql_parser();
$sql = 'SELECT u.id, u.name, COUNT(*) AS total FROM users u JOIN orders o ON u.id = o.user_id WHERE u.active = true GROUP BY u.id, u.name ORDER BY total DESC LIMIT 10';
$parsed = $parser->parse($sql);
@@ -42,7 +42,7 @@ public function test_deparse_round_trip() : void
self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
}
- $parser = pg_parser();
+ $parser = sql_parser();
$parsed = $parser->parse('SELECT id FROM users WHERE name = \'john\'');
$deparsed = $parsed->deparse();
@@ -58,7 +58,7 @@ public function test_deparse_select_with_columns() : void
self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
}
- $parser = pg_parser();
+ $parser = sql_parser();
$parsed = $parser->parse('SELECT id, name FROM users');
$deparsed = $parsed->deparse();
@@ -72,7 +72,7 @@ public function test_deparse_select_with_where() : void
self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
}
- $parser = pg_parser();
+ $parser = sql_parser();
$parsed = $parser->parse('SELECT * FROM users WHERE active = true');
$deparsed = $parsed->deparse();
@@ -86,7 +86,7 @@ public function test_deparse_simple_select() : void
self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
}
- $parser = pg_parser();
+ $parser = sql_parser();
$parsed = $parser->parse('SELECT 1');
$deparsed = $parsed->deparse();
@@ -100,11 +100,11 @@ public function test_deparse_with_options_complex_query() : void
self::markTestSkipped('pg_query_deparse_opts function not available. Rebuild the pg_query extension.');
}
- $parser = pg_parser();
+ $parser = sql_parser();
$sql = 'SELECT u.id, u.name, COUNT(*) AS total FROM users u JOIN orders o ON u.id = o.user_id WHERE u.active = true GROUP BY u.id, u.name HAVING COUNT(*) > 5 ORDER BY total DESC LIMIT 10';
$parsed = $parser->parse($sql);
- $formatted = $parsed->deparse(pg_deparse_options()->indentSize(2));
+ $formatted = $parsed->deparse(sql_deparse_options()->indentSize(2));
$expected = <<<'SQL'
SELECT u.id, u.name, count(*) AS total
@@ -130,10 +130,10 @@ public function test_deparse_with_options_create_table() : void
self::markTestSkipped('pg_query_deparse_opts function not available. Rebuild the pg_query extension.');
}
- $parser = pg_parser();
+ $parser = sql_parser();
$parsed = $parser->parse('CREATE TABLE users (id SERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL, email VARCHAR(255) UNIQUE, created_at TIMESTAMP DEFAULT NOW())');
- $formatted = $parsed->deparse(pg_deparse_options());
+ $formatted = $parsed->deparse(sql_deparse_options());
self::assertStringContainsString('CREATE TABLE users', $formatted);
self::assertStringContainsString('id serial', \strtolower($formatted));
@@ -147,10 +147,10 @@ public function test_deparse_with_options_custom_indent_size() : void
self::markTestSkipped('pg_query_deparse_opts function not available. Rebuild the pg_query extension.');
}
- $parser = pg_parser();
+ $parser = sql_parser();
$parsed = $parser->parse('SELECT u.id FROM users u JOIN orders o ON u.id = o.user_id');
- $formatted = $parsed->deparse(pg_deparse_options()->indentSize(2));
+ $formatted = $parsed->deparse(sql_deparse_options()->indentSize(2));
$expected = <<<'SQL'
SELECT u.id
@@ -168,10 +168,10 @@ public function test_deparse_with_options_insert() : void
self::markTestSkipped('pg_query_deparse_opts function not available. Rebuild the pg_query extension.');
}
- $parser = pg_parser();
+ $parser = sql_parser();
$parsed = $parser->parse("INSERT INTO users (name, email, active) VALUES ('john', 'john@example.com', true)");
- $formatted = $parsed->deparse(pg_deparse_options());
+ $formatted = $parsed->deparse(sql_deparse_options());
$expected = <<<'SQL'
INSERT INTO users (name, email, active)
@@ -187,11 +187,11 @@ public function test_deparse_with_options_pretty_print_disabled_equals_regular_d
self::markTestSkipped('pg_query_deparse_opts function not available. Rebuild the pg_query extension.');
}
- $parser = pg_parser();
+ $parser = sql_parser();
$parsed = $parser->parse('SELECT id FROM users');
$regular = $parsed->deparse();
- $formatted = $parsed->deparse(pg_deparse_options()->prettyPrint(false));
+ $formatted = $parsed->deparse(sql_deparse_options()->prettyPrint(false));
self::assertSame($regular, $formatted);
}
@@ -202,10 +202,10 @@ public function test_deparse_with_options_pretty_prints_join() : void
self::markTestSkipped('pg_query_deparse_opts function not available. Rebuild the pg_query extension.');
}
- $parser = pg_parser();
+ $parser = sql_parser();
$parsed = $parser->parse('SELECT u.id, u.name, o.total FROM users u JOIN orders o ON u.id = o.user_id WHERE u.active = true');
- $formatted = $parsed->deparse(pg_deparse_options());
+ $formatted = $parsed->deparse(sql_deparse_options());
$expected = <<<'SQL'
SELECT u.id, u.name, o.total
@@ -224,10 +224,10 @@ public function test_deparse_with_options_pretty_prints_simple_select() : void
self::markTestSkipped('pg_query_deparse_opts function not available. Rebuild the pg_query extension.');
}
- $parser = pg_parser();
+ $parser = sql_parser();
$parsed = $parser->parse('SELECT id, name, email FROM users WHERE active = true');
- $formatted = $parsed->deparse(pg_deparse_options());
+ $formatted = $parsed->deparse(sql_deparse_options());
$expected = <<<'SQL'
SELECT id, name, email
@@ -244,17 +244,17 @@ public function test_deparse_with_options_trailing_newline() : void
self::markTestSkipped('pg_query_deparse_opts function not available. Rebuild the pg_query extension.');
}
- $parser = pg_parser();
+ $parser = sql_parser();
$parsed = $parser->parse('SELECT 1');
- $formatted = $parsed->deparse(pg_deparse_options()->trailingNewline());
+ $formatted = $parsed->deparse(sql_deparse_options()->trailingNewline());
self::assertSame("SELECT 1\n", $formatted);
}
public function test_fingerprint() : void
{
- $fingerprint = pg_fingerprint('SELECT 1');
+ $fingerprint = sql_fingerprint('SELECT 1');
self::assertIsString($fingerprint);
self::assertNotEmpty($fingerprint);
@@ -262,15 +262,15 @@ public function test_fingerprint() : void
public function test_fingerprint_same_for_equivalent_queries() : void
{
- $fingerprint1 = pg_fingerprint('SELECT id FROM users WHERE id = 1');
- $fingerprint2 = pg_fingerprint('SELECT id FROM users WHERE id = 2');
+ $fingerprint1 = sql_fingerprint('SELECT id FROM users WHERE id = 1');
+ $fingerprint2 = sql_fingerprint('SELECT id FROM users WHERE id = 2');
self::assertSame($fingerprint1, $fingerprint2);
}
public function test_normalize() : void
{
- $normalized = pg_normalize('SELECT * FROM users WHERE id = 1');
+ $normalized = sql_normalize('SELECT * FROM users WHERE id = 1');
self::assertIsString($normalized);
self::assertStringContainsString('$1', $normalized);
@@ -278,7 +278,7 @@ public function test_normalize() : void
public function test_normalize_multiple_values() : void
{
- $normalized = pg_normalize("SELECT * FROM users WHERE id = 1 AND name = 'john'");
+ $normalized = sql_normalize("SELECT * FROM users WHERE id = 1 AND name = 'john'");
self::assertIsString($normalized);
self::assertStringContainsString('$1', $normalized);
@@ -291,7 +291,7 @@ public function test_normalize_utility() : void
self::markTestSkipped('pg_query_normalize_utility function not available. Rebuild the pg_query extension.');
}
- $normalized = pg_normalize_utility('CREATE TABLE users (id INT, name VARCHAR(255))');
+ $normalized = sql_normalize_utility('CREATE TABLE users (id INT, name VARCHAR(255))');
self::assertIsString($normalized);
self::assertStringContainsString('CREATE TABLE', $normalized);
@@ -304,7 +304,7 @@ public function test_normalize_utility_preserves_ddl_structure() : void
self::markTestSkipped('pg_query_normalize_utility function not available. Rebuild the pg_query extension.');
}
- $normalized = pg_normalize_utility('ALTER TABLE users ADD COLUMN email VARCHAR(255)');
+ $normalized = sql_normalize_utility('ALTER TABLE users ADD COLUMN email VARCHAR(255)');
self::assertIsString($normalized);
self::assertStringContainsString('ALTER TABLE', $normalized);
@@ -314,7 +314,7 @@ public function test_normalize_utility_preserves_ddl_structure() : void
public function test_normalize_with_named_parameters() : void
{
- $normalized = pg_normalize('SELECT * FROM users WHERE id = :id AND name = :name');
+ $normalized = sql_normalize('SELECT * FROM users WHERE id = :id AND name = :name');
self::assertIsString($normalized);
self::assertStringContainsString('$1', $normalized);
@@ -323,9 +323,9 @@ public function test_normalize_with_named_parameters() : void
public function test_parse_invalid_sql_throws_exception() : void
{
- $parser = pg_parser();
+ $parser = sql_parser();
- $this->expectException(\Flow\PgQuery\Exception\ParserException::class);
+ $this->expectException(\Flow\PostgreSql\Exception\ParserException::class);
$this->expectExceptionMessage('syntax error');
$parser->parse('SELECT FROM WHERE');
@@ -333,7 +333,7 @@ public function test_parse_invalid_sql_throws_exception() : void
public function test_parse_multiple_statements() : void
{
- $parser = pg_parser();
+ $parser = sql_parser();
$result = $parser->parse('SELECT 1; SELECT 2');
self::assertInstanceOf(ParsedQuery::class, $result);
@@ -342,7 +342,7 @@ public function test_parse_multiple_statements() : void
public function test_parse_select_with_columns() : void
{
- $parser = pg_parser();
+ $parser = sql_parser();
$result = $parser->parse('SELECT id, name FROM users');
self::assertInstanceOf(ParsedQuery::class, $result);
@@ -351,7 +351,7 @@ public function test_parse_select_with_columns() : void
public function test_parse_select_with_where() : void
{
- $parser = pg_parser();
+ $parser = sql_parser();
$result = $parser->parse('SELECT * FROM users WHERE active = true');
self::assertInstanceOf(ParsedQuery::class, $result);
@@ -360,7 +360,7 @@ public function test_parse_select_with_where() : void
public function test_parse_simple_select() : void
{
- $parser = pg_parser();
+ $parser = sql_parser();
$result = $parser->parse('SELECT 1');
self::assertInstanceOf(ParsedQuery::class, $result);
@@ -373,9 +373,9 @@ public function test_pg_deparse_with_options() : void
self::markTestSkipped('pg_query_deparse_opts function not available. Rebuild the pg_query extension.');
}
- $parsed = pg_parse('SELECT id FROM users u JOIN orders o ON u.id = o.user_id');
+ $parsed = sql_parse('SELECT id FROM users u JOIN orders o ON u.id = o.user_id');
- $deparsed = pg_deparse($parsed, pg_deparse_options()->indentSize(2));
+ $deparsed = sql_deparse($parsed, sql_deparse_options()->indentSize(2));
$expected = <<<'SQL'
SELECT id
@@ -393,9 +393,9 @@ public function test_pg_deparse_without_options() : void
self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
}
- $parsed = pg_parse('SELECT id, name FROM users');
+ $parsed = sql_parse('SELECT id, name FROM users');
- $deparsed = pg_deparse($parsed);
+ $deparsed = sql_deparse($parsed);
self::assertSame('SELECT id, name FROM users', $deparsed);
}
@@ -406,7 +406,7 @@ public function test_pg_format_with_custom_options() : void
self::markTestSkipped('pg_query_deparse_opts function not available. Rebuild the pg_query extension.');
}
- $formatted = pg_format('SELECT 1', pg_deparse_options()->trailingNewline());
+ $formatted = sql_format('SELECT 1', sql_deparse_options()->trailingNewline());
self::assertSame("SELECT 1\n", $formatted);
}
@@ -417,7 +417,7 @@ public function test_pg_format_with_default_options() : void
self::markTestSkipped('pg_query_deparse_opts function not available. Rebuild the pg_query extension.');
}
- $formatted = pg_format('SELECT id, name FROM users WHERE active = true');
+ $formatted = sql_format('SELECT id, name FROM users WHERE active = true');
$expected = <<<'SQL'
SELECT id, name
@@ -430,7 +430,7 @@ public function test_pg_format_with_default_options() : void
public function test_split() : void
{
- $statements = pg_split('SELECT 1; SELECT 2;');
+ $statements = sql_split('SELECT 1; SELECT 2;');
self::assertCount(2, $statements);
self::assertSame('SELECT 1', $statements[0]);
@@ -439,7 +439,7 @@ public function test_split() : void
public function test_split_single_statement() : void
{
- $statements = pg_split('SELECT 1');
+ $statements = sql_split('SELECT 1');
self::assertCount(1, $statements);
self::assertSame('SELECT 1', $statements[0]);
@@ -451,8 +451,8 @@ public function test_summary_different_queries_produce_different_results() : voi
self::markTestSkipped('pg_query_summary function not available. Rebuild the pg_query extension.');
}
- $summarySelect = pg_summary('SELECT * FROM users');
- $summaryInsert = pg_summary("INSERT INTO users (name) VALUES ('john')");
+ $summarySelect = sql_summary('SELECT * FROM users');
+ $summaryInsert = sql_summary("INSERT INTO users (name) VALUES ('john')");
self::assertNotSame($summarySelect, $summaryInsert);
}
@@ -463,9 +463,9 @@ public function test_summary_invalid_sql_throws_parser_exception() : void
self::markTestSkipped('pg_query_summary function not available. Rebuild the pg_query extension.');
}
- $this->expectException(\Flow\PgQuery\Exception\ParserException::class);
+ $this->expectException(\Flow\PostgreSql\Exception\ParserException::class);
- pg_summary('SELECT FROM WHERE');
+ sql_summary('SELECT FROM WHERE');
}
public function test_summary_returns_protobuf_for_cte() : void
@@ -474,7 +474,7 @@ public function test_summary_returns_protobuf_for_cte() : void
self::markTestSkipped('pg_query_summary function not available. Rebuild the pg_query extension.');
}
- $summary = pg_summary('WITH active_users AS (SELECT * FROM users WHERE active = true) SELECT * FROM active_users');
+ $summary = sql_summary('WITH active_users AS (SELECT * FROM users WHERE active = true) SELECT * FROM active_users');
self::assertNotEmpty($summary);
}
@@ -485,7 +485,7 @@ public function test_summary_returns_protobuf_for_ddl() : void
self::markTestSkipped('pg_query_summary function not available. Rebuild the pg_query extension.');
}
- $summary = pg_summary('CREATE TABLE users (id INT PRIMARY KEY, name VARCHAR(255))');
+ $summary = sql_summary('CREATE TABLE users (id INT PRIMARY KEY, name VARCHAR(255))');
self::assertNotEmpty($summary);
}
@@ -496,7 +496,7 @@ public function test_summary_returns_protobuf_for_delete() : void
self::markTestSkipped('pg_query_summary function not available. Rebuild the pg_query extension.');
}
- $summary = pg_summary('DELETE FROM users WHERE id = 1');
+ $summary = sql_summary('DELETE FROM users WHERE id = 1');
self::assertNotEmpty($summary);
}
@@ -507,7 +507,7 @@ public function test_summary_returns_protobuf_for_insert() : void
self::markTestSkipped('pg_query_summary function not available. Rebuild the pg_query extension.');
}
- $summary = pg_summary("INSERT INTO users (name, email) VALUES ('john', 'john@example.com')");
+ $summary = sql_summary("INSERT INTO users (name, email) VALUES ('john', 'john@example.com')");
self::assertNotEmpty($summary);
}
@@ -518,7 +518,7 @@ public function test_summary_returns_protobuf_for_join_query() : void
self::markTestSkipped('pg_query_summary function not available. Rebuild the pg_query extension.');
}
- $summary = pg_summary('SELECT u.name, o.total FROM users u JOIN orders o ON u.id = o.user_id');
+ $summary = sql_summary('SELECT u.name, o.total FROM users u JOIN orders o ON u.id = o.user_id');
self::assertNotEmpty($summary);
}
@@ -529,7 +529,7 @@ public function test_summary_returns_protobuf_for_select() : void
self::markTestSkipped('pg_query_summary function not available. Rebuild the pg_query extension.');
}
- $summary = pg_summary('SELECT * FROM users WHERE id = 1');
+ $summary = sql_summary('SELECT * FROM users WHERE id = 1');
self::assertNotEmpty($summary);
self::assertGreaterThan(0, \strlen($summary));
@@ -541,7 +541,7 @@ public function test_summary_returns_protobuf_for_subquery() : void
self::markTestSkipped('pg_query_summary function not available. Rebuild the pg_query extension.');
}
- $summary = pg_summary('SELECT * FROM users WHERE id IN (SELECT user_id FROM orders)');
+ $summary = sql_summary('SELECT * FROM users WHERE id IN (SELECT user_id FROM orders)');
self::assertNotEmpty($summary);
}
@@ -552,7 +552,7 @@ public function test_summary_returns_protobuf_for_update() : void
self::markTestSkipped('pg_query_summary function not available. Rebuild the pg_query extension.');
}
- $summary = pg_summary("UPDATE users SET name = 'jane' WHERE id = 1");
+ $summary = sql_summary("UPDATE users SET name = 'jane' WHERE id = 1");
self::assertNotEmpty($summary);
}
@@ -563,7 +563,7 @@ public function test_summary_with_parse_options() : void
self::markTestSkipped('pg_query_summary function not available. Rebuild the pg_query extension.');
}
- $summary = pg_summary('SELECT 1', PG_QUERY_PARSE_DEFAULT);
+ $summary = sql_summary('SELECT 1', PG_QUERY_PARSE_DEFAULT);
self::assertNotEmpty($summary);
}
@@ -576,8 +576,8 @@ public function test_summary_with_truncation_returns_different_result() : void
$longQuery = "SELECT * FROM users WHERE name = 'this is a very long string that should be truncated in the summary output'";
- $summaryWithoutTruncation = pg_summary($longQuery, 0, 0);
- $summaryWithTruncation = pg_summary($longQuery, 0, 20);
+ $summaryWithoutTruncation = sql_summary($longQuery, 0, 0);
+ $summaryWithTruncation = sql_summary($longQuery, 0, 20);
self::assertNotEmpty($summaryWithTruncation);
self::assertNotSame($summaryWithoutTruncation, $summaryWithTruncation);
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Clause/CTETest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Clause/CTETest.php
new file mode 100644
index 000000000..b3c068312
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Clause/CTETest.php
@@ -0,0 +1,150 @@
+createMockSelectNode();
+ $cte = new CTE('active_users', $query);
+
+ $node = $cte->toAst();
+
+ $commonTableExpr = $node->getCommonTableExpr();
+ self::assertNotNull($commonTableExpr);
+ self::assertSame('active_users', $commonTableExpr->getCtename());
+ self::assertSame($query, $commonTableExpr->getCtequery());
+ self::assertFalse($commonTableExpr->getCterecursive());
+ }
+
+ public function test_converts_to_ast_with_column_names() : void
+ {
+ $query = $this->createMockSelectNode();
+ $cte = new CTE('totals', $query, ['category', 'amount']);
+
+ $node = $cte->toAst();
+
+ $commonTableExpr = $node->getCommonTableExpr();
+ self::assertNotNull($commonTableExpr);
+
+ $aliasColumns = $commonTableExpr->getAliascolnames();
+ self::assertNotNull($aliasColumns);
+ self::assertCount(2, $aliasColumns);
+
+ $firstColumn = $aliasColumns[0]->getString();
+ self::assertNotNull($firstColumn);
+ self::assertSame('category', $firstColumn->getSval());
+
+ $secondColumn = $aliasColumns[1]->getString();
+ self::assertNotNull($secondColumn);
+ self::assertSame('amount', $secondColumn->getSval());
+ }
+
+ public function test_cte_getters() : void
+ {
+ $query = $this->createMockSelectNode();
+ $cte = new CTE('test_cte', $query, ['col1', 'col2'], CTEMaterialization::MATERIALIZED, true);
+
+ self::assertSame('test_cte', $cte->name());
+ self::assertSame($query, $cte->query());
+ self::assertSame(['col1', 'col2'], $cte->columnNames());
+ self::assertSame(CTEMaterialization::MATERIALIZED, $cte->materialization());
+ self::assertTrue($cte->recursive());
+ }
+
+ public function test_immutable_materialized_method() : void
+ {
+ $query = $this->createMockSelectNode();
+ $cte = new CTE('expensive', $query);
+
+ self::assertSame(CTEMaterialization::DEFAULT, $cte->materialization());
+
+ $materialized = $cte->materialized();
+
+ self::assertSame(CTEMaterialization::DEFAULT, $cte->materialization());
+ self::assertSame(CTEMaterialization::MATERIALIZED, $materialized->materialization());
+ self::assertNotSame($cte, $materialized);
+ }
+
+ public function test_immutable_not_materialized_method() : void
+ {
+ $query = $this->createMockSelectNode();
+ $cte = new CTE('temp', $query);
+
+ $notMaterialized = $cte->notMaterialized();
+
+ self::assertSame(CTEMaterialization::DEFAULT, $cte->materialization());
+ self::assertSame(CTEMaterialization::NOT_MATERIALIZED, $notMaterialized->materialization());
+ self::assertNotSame($cte, $notMaterialized);
+ }
+
+ public function test_immutable_with_columns_method() : void
+ {
+ $query = $this->createMockSelectNode();
+ $cte = new CTE('users', $query);
+
+ self::assertSame([], $cte->columnNames());
+
+ $withColumns = $cte->withColumns(['id', 'name']);
+
+ self::assertSame([], $cte->columnNames());
+ self::assertSame(['id', 'name'], $withColumns->columnNames());
+ self::assertNotSame($cte, $withColumns);
+ }
+
+ public function test_recursive_cte_to_ast() : void
+ {
+ $query = $this->createMockSelectNode();
+ $cte = new CTE('hierarchy', $query, recursive: true);
+
+ $node = $cte->toAst();
+
+ $commonTableExpr = $node->getCommonTableExpr();
+ self::assertNotNull($commonTableExpr);
+ self::assertTrue($commonTableExpr->getCterecursive());
+ }
+
+ public function test_roundtrip_conversion_simple() : void
+ {
+ $query = $this->createMockSelectNode();
+ $original = new CTE('test', $query);
+
+ $node = $original->toAst();
+ $reconstructed = CTE::fromAst($node);
+
+ self::assertSame($original->name(), $reconstructed->name());
+ self::assertSame($original->columnNames(), $reconstructed->columnNames());
+ self::assertSame($original->materialization(), $reconstructed->materialization());
+ self::assertSame($original->recursive(), $reconstructed->recursive());
+ }
+
+ public function test_roundtrip_conversion_with_all_options() : void
+ {
+ $query = $this->createMockSelectNode();
+ $original = new CTE('complex', $query, ['a', 'b', 'c'], CTEMaterialization::MATERIALIZED, true);
+
+ $node = $original->toAst();
+ $reconstructed = CTE::fromAst($node);
+
+ self::assertSame($original->name(), $reconstructed->name());
+ self::assertSame($original->columnNames(), $reconstructed->columnNames());
+ self::assertSame($original->materialization(), $reconstructed->materialization());
+ self::assertSame($original->recursive(), $reconstructed->recursive());
+ }
+
+ private function createMockSelectNode() : Node
+ {
+ $selectStmt = new SelectStmt();
+ $node = new Node();
+ $node->setSelectStmt($selectStmt);
+
+ return $node;
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Clause/ConflictTargetTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Clause/ConflictTargetTest.php
new file mode 100644
index 000000000..1e2e6c542
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Clause/ConflictTargetTest.php
@@ -0,0 +1,57 @@
+getColumns());
+ self::assertSame(['email'], $target->getColumns());
+ self::assertNull($target->getConstraint());
+ }
+
+ public function test_constraint() : void
+ {
+ $target = ConflictTarget::constraint('users_email_key');
+
+ self::assertEmpty($target->getColumns());
+ self::assertSame('users_email_key', $target->getConstraint());
+ }
+
+ public function test_multiple_columns() : void
+ {
+ $target = ConflictTarget::columns(['first_name', 'last_name']);
+
+ self::assertCount(2, $target->getColumns());
+ self::assertSame(['first_name', 'last_name'], $target->getColumns());
+ }
+
+ public function test_to_ast() : void
+ {
+ $target = ConflictTarget::columns(['email']);
+ $node = $target->toAst();
+ $inferClause = $node->getInferClause();
+
+ self::assertNotNull($inferClause);
+ }
+
+ public function test_where() : void
+ {
+ $target = ConflictTarget::columns(['email']);
+ $condition = new Comparison(Column::name('deleted_at'), ComparisonOperator::EQ, Literal::null());
+ $targetWithWhere = $target->where($condition);
+
+ self::assertNull($target->whereClause());
+ self::assertNotNull($targetWithWhere->whereClause());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Clause/FrameBoundTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Clause/FrameBoundTest.php
new file mode 100644
index 000000000..ae31ed6fd
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Clause/FrameBoundTest.php
@@ -0,0 +1,71 @@
+type());
+ self::assertNull($bound->offset());
+ }
+
+ public function test_following_with_offset() : void
+ {
+ $offset = Literal::int(5);
+ $bound = FrameBound::following($offset);
+
+ self::assertSame(FrameBoundType::FOLLOWING, $bound->type());
+ self::assertSame($offset, $bound->offset());
+ }
+
+ public function test_preceding_with_offset() : void
+ {
+ $offset = Literal::int(10);
+ $bound = FrameBound::preceding($offset);
+
+ self::assertSame(FrameBoundType::PRECEDING, $bound->type());
+ self::assertSame($offset, $bound->offset());
+ }
+
+ public function test_to_ast_and_from_ast_current_row() : void
+ {
+ $bound = FrameBound::currentRow();
+ $node = $bound->toAst();
+
+ self::assertInstanceOf(\Flow\PostgreSql\Protobuf\AST\Node::class, $node);
+ }
+
+ public function test_to_ast_with_offset() : void
+ {
+ $offset = Literal::int(3);
+ $bound = FrameBound::preceding($offset);
+ $node = $bound->toAst();
+
+ self::assertInstanceOf(\Flow\PostgreSql\Protobuf\AST\Node::class, $node);
+ }
+
+ public function test_unbounded_following() : void
+ {
+ $bound = FrameBound::unboundedFollowing();
+
+ self::assertSame(FrameBoundType::UNBOUNDED_FOLLOWING, $bound->type());
+ self::assertNull($bound->offset());
+ }
+
+ public function test_unbounded_preceding() : void
+ {
+ $bound = FrameBound::unboundedPreceding();
+
+ self::assertSame(FrameBoundType::UNBOUNDED_PRECEDING, $bound->type());
+ self::assertNull($bound->offset());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Clause/LockingClauseTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Clause/LockingClauseTest.php
new file mode 100644
index 000000000..f87637504
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Clause/LockingClauseTest.php
@@ -0,0 +1,92 @@
+strength());
+ self::assertEmpty($lock->tables());
+ }
+
+ public function test_for_key_share_with_tables() : void
+ {
+ $lock = LockingClause::forKeyShare(['users', 'posts']);
+
+ self::assertSame(LockStrength::KEY_SHARE, $lock->strength());
+ self::assertCount(2, $lock->tables());
+ }
+
+ public function test_for_no_key_update() : void
+ {
+ $lock = LockingClause::forNoKeyUpdate();
+
+ self::assertSame(LockStrength::NO_KEY_UPDATE, $lock->strength());
+ }
+
+ public function test_for_share() : void
+ {
+ $lock = LockingClause::forShare();
+
+ self::assertSame(LockStrength::SHARE, $lock->strength());
+ }
+
+ public function test_for_share_nowait() : void
+ {
+ $lock = LockingClause::forShare()->nowait();
+
+ self::assertSame(LockWaitPolicy::NOWAIT, $lock->waitPolicy());
+ }
+
+ public function test_for_share_skip_locked() : void
+ {
+ $lock = LockingClause::forShare()->skipLocked();
+
+ self::assertSame(LockWaitPolicy::SKIP_LOCKED, $lock->waitPolicy());
+ }
+
+ public function test_for_update() : void
+ {
+ $lock = LockingClause::forUpdate();
+
+ self::assertSame(LockStrength::UPDATE, $lock->strength());
+ self::assertSame(LockWaitPolicy::DEFAULT, $lock->waitPolicy());
+ }
+
+ public function test_for_update_with_tables() : void
+ {
+ $lock = LockingClause::forUpdate(['users']);
+
+ self::assertSame(LockStrength::UPDATE, $lock->strength());
+ self::assertCount(1, $lock->tables());
+ self::assertSame(['users'], $lock->tables());
+ }
+
+ public function test_to_ast() : void
+ {
+ $lock = LockingClause::forUpdate(['users']);
+ $node = $lock->toAst();
+ $lockingClause = $node->getLockingClause();
+
+ self::assertNotNull($lockingClause);
+ }
+
+ public function test_to_ast_and_from_ast() : void
+ {
+ $lock = LockingClause::forUpdate(['users'])->nowait();
+ $node = $lock->toAst();
+ $restored = LockingClause::fromAst($node);
+
+ self::assertSame($lock->strength(), $restored->strength());
+ self::assertSame($lock->waitPolicy(), $restored->waitPolicy());
+ self::assertSame($lock->tables(), $restored->tables());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Clause/OnConflictClauseTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Clause/OnConflictClauseTest.php
new file mode 100644
index 000000000..413ff615b
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Clause/OnConflictClauseTest.php
@@ -0,0 +1,82 @@
+action());
+ self::assertNull($conflict->target());
+ self::assertEmpty($conflict->updates());
+ }
+
+ public function test_do_nothing_with_target() : void
+ {
+ $target = ConflictTarget::columns(['email']);
+ $conflict = OnConflictClause::doNothing($target);
+
+ self::assertSame(ConflictAction::NOTHING, $conflict->action());
+ self::assertNotNull($conflict->target());
+ }
+
+ public function test_do_update() : void
+ {
+ $target = ConflictTarget::columns(['email']);
+ $conflict = OnConflictClause::doUpdate($target, [
+ 'name' => Column::name('excluded.name'),
+ 'updated_at' => new FunctionCall(['now']),
+ ]);
+
+ self::assertSame(ConflictAction::UPDATE, $conflict->action());
+ self::assertNotNull($conflict->target());
+ self::assertCount(2, $conflict->updates());
+ }
+
+ public function test_to_ast() : void
+ {
+ $target = ConflictTarget::columns(['email']);
+ $conflict = OnConflictClause::doUpdate($target, [
+ 'name' => Column::name('excluded.name'),
+ ]);
+ $node = $conflict->toAst();
+ $onConflictClause = $node->getOnConflictClause();
+
+ self::assertNotNull($onConflictClause);
+ }
+
+ public function test_to_ast_and_from_ast() : void
+ {
+ $target = ConflictTarget::columns(['email']);
+ $conflict = OnConflictClause::doUpdate($target, [
+ 'name' => Column::name('excluded.name'),
+ ]);
+ $node = $conflict->toAst();
+ $restored = OnConflictClause::fromAst($node);
+
+ self::assertSame($conflict->action(), $restored->action());
+ self::assertCount(1, $restored->updates());
+ }
+
+ public function test_where() : void
+ {
+ $target = ConflictTarget::columns(['email']);
+ $conflict = OnConflictClause::doUpdate($target, [
+ 'name' => Column::name('excluded.name'),
+ ]);
+ $condition = new Comparison(Column::name('deleted_at'), ComparisonOperator::EQ, Literal::null());
+ $conflictWithWhere = $conflict->where($condition);
+
+ self::assertNull($conflict->whereClause());
+ self::assertNotNull($conflictWithWhere->whereClause());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Clause/OrderByItemTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Clause/OrderByItemTest.php
new file mode 100644
index 000000000..8d9c8c5ff
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Clause/OrderByItemTest.php
@@ -0,0 +1,237 @@
+asc();
+
+ self::assertNotSame($orderBy, $ascOrderBy);
+ self::assertSame(SortDirection::ASC, $ascOrderBy->direction());
+ self::assertSame($column, $ascOrderBy->expression());
+ }
+
+ public function test_constructor_with_all_parameters() : void
+ {
+ $column = Column::name('priority');
+ $orderBy = new OrderByItem($column, SortDirection::DESC, NullsPosition::FIRST);
+
+ self::assertSame($column, $orderBy->expression());
+ self::assertSame(SortDirection::DESC, $orderBy->direction());
+ self::assertSame(NullsPosition::FIRST, $orderBy->nulls());
+ }
+
+ public function test_constructor_with_default_parameters() : void
+ {
+ $column = Column::name('name');
+ $orderBy = new OrderByItem($column);
+
+ self::assertSame($column, $orderBy->expression());
+ self::assertSame(SortDirection::ASC, $orderBy->direction());
+ self::assertSame(NullsPosition::DEFAULT, $orderBy->nulls());
+ }
+
+ public function test_desc_creates_new_instance_with_descending_direction() : void
+ {
+ $column = Column::name('created_at');
+ $orderBy = new OrderByItem($column);
+
+ $descOrderBy = $orderBy->desc();
+
+ self::assertNotSame($orderBy, $descOrderBy);
+ self::assertSame(SortDirection::DESC, $descOrderBy->direction());
+ self::assertSame($column, $descOrderBy->expression());
+ }
+
+ public function test_fluent_methods_return_new_instances() : void
+ {
+ $column = Column::name('score');
+ $original = new OrderByItem($column);
+
+ $modified = $original->desc()->nullsFirst();
+
+ self::assertNotSame($original, $modified);
+ self::assertSame(SortDirection::ASC, $original->direction());
+ self::assertSame(NullsPosition::DEFAULT, $original->nulls());
+ self::assertSame(SortDirection::DESC, $modified->direction());
+ self::assertSame(NullsPosition::FIRST, $modified->nulls());
+ }
+
+ public function test_from_ast_with_ascending_direction() : void
+ {
+ $columnNode = Column::name('name')->toAst();
+
+ $sortBy = new SortBy([
+ 'node' => $columnNode,
+ 'sortby_dir' => SortByDir::SORTBY_ASC,
+ 'sortby_nulls' => SortByNulls::SORTBY_NULLS_DEFAULT,
+ ]);
+
+ $orderBy = OrderByItem::fromAst($sortBy);
+
+ self::assertSame(SortDirection::ASC, $orderBy->direction());
+ self::assertSame(NullsPosition::DEFAULT, $orderBy->nulls());
+ self::assertInstanceOf(Column::class, $orderBy->expression());
+ }
+
+ public function test_from_ast_with_default_direction() : void
+ {
+ $columnNode = Column::name('id')->toAst();
+
+ $sortBy = new SortBy([
+ 'node' => $columnNode,
+ 'sortby_dir' => SortByDir::SORTBY_DEFAULT,
+ 'sortby_nulls' => SortByNulls::SORTBY_NULLS_DEFAULT,
+ ]);
+
+ $orderBy = OrderByItem::fromAst($sortBy);
+
+ self::assertSame(SortDirection::DEFAULT, $orderBy->direction());
+ self::assertSame(NullsPosition::DEFAULT, $orderBy->nulls());
+ }
+
+ public function test_from_ast_with_descending_direction() : void
+ {
+ $columnNode = Column::name('created_at')->toAst();
+
+ $sortBy = new SortBy([
+ 'node' => $columnNode,
+ 'sortby_dir' => SortByDir::SORTBY_DESC,
+ 'sortby_nulls' => SortByNulls::SORTBY_NULLS_DEFAULT,
+ ]);
+
+ $orderBy = OrderByItem::fromAst($sortBy);
+
+ self::assertSame(SortDirection::DESC, $orderBy->direction());
+ self::assertSame(NullsPosition::DEFAULT, $orderBy->nulls());
+ }
+
+ public function test_from_ast_with_nulls_first() : void
+ {
+ $columnNode = Column::name('priority')->toAst();
+
+ $sortBy = new SortBy([
+ 'node' => $columnNode,
+ 'sortby_dir' => SortByDir::SORTBY_ASC,
+ 'sortby_nulls' => SortByNulls::SORTBY_NULLS_FIRST,
+ ]);
+
+ $orderBy = OrderByItem::fromAst($sortBy);
+
+ self::assertSame(NullsPosition::FIRST, $orderBy->nulls());
+ }
+
+ public function test_from_ast_with_nulls_last() : void
+ {
+ $columnNode = Column::name('priority')->toAst();
+
+ $sortBy = new SortBy([
+ 'node' => $columnNode,
+ 'sortby_dir' => SortByDir::SORTBY_DESC,
+ 'sortby_nulls' => SortByNulls::SORTBY_NULLS_LAST,
+ ]);
+
+ $orderBy = OrderByItem::fromAst($sortBy);
+
+ self::assertSame(NullsPosition::LAST, $orderBy->nulls());
+ }
+
+ public function test_nulls_first_creates_new_instance_with_first_nulls_position() : void
+ {
+ $column = Column::name('priority');
+ $orderBy = new OrderByItem($column);
+
+ $nullsFirstOrderBy = $orderBy->nullsFirst();
+
+ self::assertNotSame($orderBy, $nullsFirstOrderBy);
+ self::assertSame(NullsPosition::FIRST, $nullsFirstOrderBy->nulls());
+ self::assertSame($column, $nullsFirstOrderBy->expression());
+ }
+
+ public function test_nulls_last_creates_new_instance_with_last_nulls_position() : void
+ {
+ $column = Column::name('priority');
+ $orderBy = new OrderByItem($column);
+
+ $nullsLastOrderBy = $orderBy->nullsLast();
+
+ self::assertNotSame($orderBy, $nullsLastOrderBy);
+ self::assertSame(NullsPosition::LAST, $nullsLastOrderBy->nulls());
+ self::assertSame($column, $nullsLastOrderBy->expression());
+ }
+
+ public function test_round_trip_with_all_variations() : void
+ {
+ $testCases = [
+ ['id', Column::name('id'), SortDirection::ASC, NullsPosition::DEFAULT],
+ ['name', Column::name('name'), SortDirection::DESC, NullsPosition::FIRST],
+ ['created_at', Column::name('created_at'), SortDirection::ASC, NullsPosition::LAST],
+ ['email', Column::tableColumn('users', 'email'), SortDirection::DESC, NullsPosition::DEFAULT],
+ ['score', Column::schemaTableColumn('public', 'users', 'score'), SortDirection::DEFAULT, NullsPosition::FIRST],
+ ];
+
+ foreach ($testCases as [$name, $expression, $direction, $nulls]) {
+ $original = new OrderByItem($expression, $direction, $nulls);
+ $ast = $original->toAst();
+ $restored = OrderByItem::fromAst($ast);
+
+ self::assertEquals($direction, $restored->direction(), "Direction mismatch for {$name}");
+ self::assertEquals($nulls, $restored->nulls(), "Nulls position mismatch for {$name}");
+
+ $restoredExpression = $restored->expression();
+ self::assertInstanceOf(Column::class, $restoredExpression);
+ self::assertEquals($expression->parts(), $restoredExpression->parts(), "Expression mismatch for {$name}");
+ }
+ }
+
+ public function test_to_ast_creates_sort_by_node() : void
+ {
+ $column = Column::name('name');
+ $orderBy = new OrderByItem($column);
+
+ $ast = $orderBy->toAst();
+
+ self::assertInstanceOf(SortBy::class, $ast);
+ self::assertNotNull($ast->getNode());
+ self::assertSame(SortByDir::SORTBY_ASC, $ast->getSortbyDir());
+ self::assertSame(SortByNulls::SORTBY_NULLS_DEFAULT, $ast->getSortbyNulls());
+ }
+
+ public function test_to_ast_with_all_options() : void
+ {
+ $column = Column::name('priority');
+ $orderBy = new OrderByItem($column, SortDirection::DESC, NullsPosition::LAST);
+
+ $ast = $orderBy->toAst();
+
+ self::assertInstanceOf(SortBy::class, $ast);
+ self::assertSame(SortByDir::SORTBY_DESC, $ast->getSortbyDir());
+ self::assertSame(SortByNulls::SORTBY_NULLS_LAST, $ast->getSortbyNulls());
+ }
+
+ public function test_to_ast_with_complex_column_reference() : void
+ {
+ $column = Column::tableColumn('users', 'email');
+ $orderBy = new OrderByItem($column, SortDirection::ASC, NullsPosition::FIRST);
+
+ $ast = $orderBy->toAst();
+
+ self::assertInstanceOf(SortBy::class, $ast);
+
+ $restored = OrderByItem::fromAst($ast);
+ self::assertInstanceOf(Column::class, $restored->expression());
+ self::assertSame(['users', 'email'], $restored->expression()->parts());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Clause/ReturningClauseTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Clause/ReturningClauseTest.php
new file mode 100644
index 000000000..33bd6ca27
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Clause/ReturningClauseTest.php
@@ -0,0 +1,57 @@
+expressions());
+ self::assertInstanceOf(Star::class, $returning->expressions()[0]);
+ }
+
+ public function test_columns() : void
+ {
+ $returning = ReturningClause::columns('id', 'created_at');
+
+ self::assertCount(2, $returning->expressions());
+ self::assertInstanceOf(Column::class, $returning->expressions()[0]);
+ self::assertInstanceOf(Column::class, $returning->expressions()[1]);
+ }
+
+ public function test_single_column() : void
+ {
+ $returning = ReturningClause::columns('id');
+
+ self::assertCount(1, $returning->expressions());
+ }
+
+ public function test_to_ast() : void
+ {
+ $returning = ReturningClause::columns('id');
+ $node = $returning->toAst();
+ $resTarget = $node->getResTarget();
+
+ self::assertNotNull($resTarget);
+ }
+
+ public function test_to_ast_nodes() : void
+ {
+ $returning = ReturningClause::columns('id', 'name');
+ $nodes = ReturningClause::toAstNodes($returning);
+
+ self::assertCount(2, $nodes);
+
+ foreach ($nodes as $node) {
+ self::assertNotNull($node->getResTarget());
+ }
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Clause/WindowDefinitionTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Clause/WindowDefinitionTest.php
new file mode 100644
index 000000000..a4153ff13
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Clause/WindowDefinitionTest.php
@@ -0,0 +1,100 @@
+name());
+ self::assertEmpty($window->partitionBy());
+ self::assertEmpty($window->orderBy());
+ self::assertNull($window->frame());
+ self::assertNull($window->refName());
+ }
+
+ public function test_to_ast() : void
+ {
+ $window = new WindowDefinition('w');
+ $node = $window->toAst();
+ $windowDef = $node->getWindowDef();
+
+ self::assertNotNull($windowDef);
+ self::assertSame('w', $windowDef->getName());
+ }
+
+ public function test_window_with_frame() : void
+ {
+ $frame = WindowFrame::rows(FrameBound::currentRow());
+ $window = new WindowDefinition('w', frame: $frame);
+
+ self::assertNotNull($window->frame());
+ self::assertSame($frame, $window->frame());
+ }
+
+ public function test_window_with_order_by() : void
+ {
+ $window = new WindowDefinition(
+ 'w',
+ orderBy: [new OrderBy(Column::name('created_at'))]
+ );
+
+ self::assertCount(1, $window->orderBy());
+ }
+
+ public function test_window_with_partition_by() : void
+ {
+ $window = new WindowDefinition(
+ 'w',
+ partitionBy: [Column::name('category')]
+ );
+
+ self::assertCount(1, $window->partitionBy());
+ }
+
+ public function test_window_with_ref_name() : void
+ {
+ $window = new WindowDefinition('w2', refName: 'w1');
+
+ self::assertSame('w2', $window->name());
+ self::assertSame('w1', $window->refName());
+ }
+
+ public function test_with_frame() : void
+ {
+ $window = new WindowDefinition('w');
+ $frame = WindowFrame::rows(FrameBound::currentRow());
+ $windowWithFrame = $window->withFrame($frame);
+
+ self::assertNull($window->frame());
+ self::assertNotNull($windowWithFrame->frame());
+ }
+
+ public function test_with_order_by() : void
+ {
+ $window = new WindowDefinition('w');
+ $orderBy = [new OrderBy(Column::name('id'))];
+ $windowWithOrder = $window->withOrderBy($orderBy);
+
+ self::assertEmpty($window->orderBy());
+ self::assertCount(1, $windowWithOrder->orderBy());
+ }
+
+ public function test_with_partition_by() : void
+ {
+ $window = new WindowDefinition('w');
+ $partitionBy = [Column::name('status')];
+ $windowWithPartition = $window->withPartitionBy($partitionBy);
+
+ self::assertEmpty($window->partitionBy());
+ self::assertCount(1, $windowWithPartition->partitionBy());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Clause/WindowFrameTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Clause/WindowFrameTest.php
new file mode 100644
index 000000000..62226534e
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Clause/WindowFrameTest.php
@@ -0,0 +1,77 @@
+mode());
+ self::assertInstanceOf(FrameBound::class, $frame->startBound());
+ self::assertNull($frame->endBound());
+ }
+
+ public function test_groups_frame_between() : void
+ {
+ $frame = WindowFrame::groups(
+ FrameBound::unboundedPreceding(),
+ FrameBound::currentRow()
+ );
+
+ self::assertSame(FrameMode::GROUPS, $frame->mode());
+ self::assertInstanceOf(FrameBound::class, $frame->startBound());
+ self::assertInstanceOf(FrameBound::class, $frame->endBound());
+ }
+
+ public function test_range_frame_between() : void
+ {
+ $frame = WindowFrame::range(
+ FrameBound::unboundedPreceding(),
+ FrameBound::currentRow()
+ );
+
+ self::assertSame(FrameMode::RANGE, $frame->mode());
+ self::assertInstanceOf(FrameBound::class, $frame->startBound());
+ self::assertInstanceOf(FrameBound::class, $frame->endBound());
+ }
+
+ public function test_range_frame_current_row() : void
+ {
+ $frame = WindowFrame::range(FrameBound::currentRow());
+
+ self::assertSame(FrameMode::RANGE, $frame->mode());
+ self::assertInstanceOf(FrameBound::class, $frame->startBound());
+ }
+
+ public function test_rows_frame_current_row() : void
+ {
+ $frame = WindowFrame::rows(FrameBound::currentRow());
+
+ self::assertSame(FrameMode::ROWS, $frame->mode());
+ self::assertInstanceOf(FrameBound::class, $frame->startBound());
+ }
+
+ public function test_to_ast() : void
+ {
+ $frame = WindowFrame::rows(FrameBound::currentRow());
+ $node = $frame->toAst();
+
+ self::assertInstanceOf(\Flow\PostgreSql\Protobuf\AST\Node::class, $node);
+ }
+
+ public function test_with_exclusion() : void
+ {
+ $frame = WindowFrame::rows(FrameBound::currentRow());
+ $frameWithExclusion = $frame->withExclusion(FrameExclusion::CURRENT_ROW);
+
+ self::assertSame(FrameExclusion::NO_OTHERS, $frame->exclusion());
+ self::assertSame(FrameExclusion::CURRENT_ROW, $frameWithExclusion->exclusion());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Clause/WithClauseTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Clause/WithClauseTest.php
new file mode 100644
index 000000000..0bb0315ac
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Clause/WithClauseTest.php
@@ -0,0 +1,156 @@
+createMockSelectNode();
+ $query2 = $this->createMockSelectNode();
+
+ $cte1 = new CTE('active', $query1);
+ $cte2 = new CTE('inactive', $query2);
+
+ $withClause = new WithClause([$cte1, $cte2]);
+
+ $node = $withClause->toAst();
+
+ $protoWithClause = $node->getWithClause();
+ self::assertNotNull($protoWithClause);
+
+ $ctes = $protoWithClause->getCtes();
+ self::assertNotNull($ctes);
+ self::assertCount(2, $ctes);
+
+ $firstCte = $ctes[0]->getCommonTableExpr();
+ self::assertNotNull($firstCte);
+ self::assertSame('active', $firstCte->getCtename());
+
+ $secondCte = $ctes[1]->getCommonTableExpr();
+ self::assertNotNull($secondCte);
+ self::assertSame('inactive', $secondCte->getCtename());
+ }
+
+ public function test_converts_single_cte_to_ast() : void
+ {
+ $query = $this->createMockSelectNode();
+ $cte = new CTE('users', $query);
+ $withClause = new WithClause([$cte]);
+
+ $node = $withClause->toAst();
+
+ $protoWithClause = $node->getWithClause();
+ self::assertNotNull($protoWithClause);
+
+ $ctes = $protoWithClause->getCtes();
+ self::assertNotNull($ctes);
+ self::assertCount(1, $ctes);
+
+ $firstCte = $ctes[0]->getCommonTableExpr();
+ self::assertNotNull($firstCte);
+ self::assertSame('users', $firstCte->getCtename());
+ }
+
+ public function test_getters() : void
+ {
+ $query = $this->createMockSelectNode();
+ $cte = new CTE('test', $query);
+ $withClause = new WithClause([$cte], true);
+
+ self::assertCount(1, $withClause->ctes());
+ self::assertSame($cte, $withClause->ctes()[0]);
+ self::assertTrue($withClause->recursive());
+ }
+
+ public function test_immutable_add_method() : void
+ {
+ $query1 = $this->createMockSelectNode();
+ $query2 = $this->createMockSelectNode();
+
+ $cte1 = new CTE('first', $query1);
+ $cte2 = new CTE('second', $query2);
+
+ $original = new WithClause([$cte1]);
+
+ self::assertCount(1, $original->ctes());
+
+ $modified = $original->add($cte2);
+
+ self::assertCount(1, $original->ctes());
+ self::assertCount(2, $modified->ctes());
+ self::assertNotSame($original, $modified);
+ self::assertSame($cte1, $modified->ctes()[0]);
+ self::assertSame($cte2, $modified->ctes()[1]);
+ }
+
+ public function test_recursive_with_clause_to_ast() : void
+ {
+ $query = $this->createMockSelectNode();
+ $cte = new CTE('hierarchy', $query, recursive: true);
+ $withClause = new WithClause([$cte], recursive: true);
+
+ $node = $withClause->toAst();
+
+ $protoWithClause = $node->getWithClause();
+ self::assertNotNull($protoWithClause);
+ self::assertTrue($protoWithClause->getRecursive());
+ }
+
+ public function test_roundtrip_conversion_multiple_ctes() : void
+ {
+ $query1 = $this->createMockSelectNode();
+ $query2 = $this->createMockSelectNode();
+ $query3 = $this->createMockSelectNode();
+
+ $cte1 = new CTE('first', $query1, ['a', 'b']);
+ $cte2 = new CTE('second', $query2);
+ $cte3 = new CTE('third', $query3, ['x']);
+
+ $original = new WithClause([$cte1, $cte2, $cte3], true);
+
+ $node = $original->toAst();
+ $reconstructed = WithClause::fromAst($node);
+
+ self::assertCount(3, $reconstructed->ctes());
+ self::assertTrue($reconstructed->recursive());
+
+ self::assertSame('first', $reconstructed->ctes()[0]->name());
+ self::assertSame(['a', 'b'], $reconstructed->ctes()[0]->columnNames());
+
+ self::assertSame('second', $reconstructed->ctes()[1]->name());
+ self::assertSame([], $reconstructed->ctes()[1]->columnNames());
+
+ self::assertSame('third', $reconstructed->ctes()[2]->name());
+ self::assertSame(['x'], $reconstructed->ctes()[2]->columnNames());
+ }
+
+ public function test_roundtrip_conversion_single_cte() : void
+ {
+ $query = $this->createMockSelectNode();
+ $cte = new CTE('test', $query);
+ $original = new WithClause([$cte]);
+
+ $node = $original->toAst();
+ $reconstructed = WithClause::fromAst($node);
+
+ self::assertCount(\count($original->ctes()), $reconstructed->ctes());
+ self::assertSame($original->recursive(), $reconstructed->recursive());
+ self::assertSame($original->ctes()[0]->name(), $reconstructed->ctes()[0]->name());
+ }
+
+ private function createMockSelectNode() : Node
+ {
+ $selectStmt = new SelectStmt();
+ $node = new Node();
+ $node->setSelectStmt($selectStmt);
+
+ return $node;
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/AllTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/AllTest.php
new file mode 100644
index 000000000..6c10ce297
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/AllTest.php
@@ -0,0 +1,138 @@
+and($condition2);
+
+ self::assertInstanceOf(AndCondition::class, $result);
+ }
+
+ public function test_converts_all_with_array_to_ast() : void
+ {
+ $condition = new All(
+ Column::name('id'),
+ ComparisonOperator::EQ,
+ Literal::int(1)
+ );
+
+ $node = $condition->toAst();
+
+ self::assertTrue($node->hasAExpr());
+
+ $aExpr = $node->getAExpr();
+ self::assertNotNull($aExpr);
+ self::assertSame(A_Expr_Kind::AEXPR_OP_ALL, $aExpr->getKind());
+ }
+
+ public function test_converts_all_with_subquery_to_ast() : void
+ {
+ $subquery = new Node(['select_stmt' => new SelectStmt()]);
+
+ $condition = new All(
+ Column::name('id'),
+ ComparisonOperator::GT,
+ $subquery
+ );
+
+ $node = $condition->toAst();
+
+ self::assertTrue($node->hasSubLink());
+
+ $subLink = $node->getSubLink();
+ self::assertNotNull($subLink);
+ self::assertSame(SubLinkType::ALL_SUBLINK, $subLink->getSubLinkType());
+ }
+
+ public function test_creates_all_condition_with_expression() : void
+ {
+ $condition = new All(
+ Column::name('id'),
+ ComparisonOperator::EQ,
+ Literal::int(1)
+ );
+
+ self::assertInstanceOf(All::class, $condition);
+ self::assertSame(ComparisonOperator::EQ, $condition->operator);
+ }
+
+ public function test_creates_all_condition_with_subquery() : void
+ {
+ $subquery = new Node(['select_stmt' => new SelectStmt()]);
+
+ $condition = new All(
+ Column::name('id'),
+ ComparisonOperator::GT,
+ $subquery
+ );
+
+ self::assertInstanceOf(All::class, $condition);
+ self::assertSame(ComparisonOperator::GT, $condition->operator);
+ self::assertInstanceOf(Node::class, $condition->arrayOrSubquery);
+ }
+
+ public function test_not_method_returns_not_condition() : void
+ {
+ $condition = new All(Column::name('id'), ComparisonOperator::EQ, Literal::int(1));
+
+ $result = $condition->not();
+
+ self::assertInstanceOf(NotCondition::class, $result);
+ }
+
+ public function test_or_method_returns_or_condition() : void
+ {
+ $condition1 = new All(Column::name('id'), ComparisonOperator::EQ, Literal::int(1));
+ $condition2 = new All(Column::name('status'), ComparisonOperator::NEQ, Literal::string('inactive'));
+
+ $result = $condition1->or($condition2);
+
+ self::assertInstanceOf(OrCondition::class, $result);
+ }
+
+ public function test_reconstructs_all_with_array_from_ast() : void
+ {
+ $original = new All(
+ Column::name('id'),
+ ComparisonOperator::LT,
+ Literal::int(10)
+ );
+
+ $node = $original->toAst();
+ $reconstructed = All::fromAst($node);
+
+ self::assertInstanceOf(All::class, $reconstructed);
+ self::assertSame(ComparisonOperator::LT, $reconstructed->operator);
+ }
+
+ public function test_reconstructs_all_with_subquery_from_ast() : void
+ {
+ $subquery = new Node(['select_stmt' => new SelectStmt()]);
+
+ $original = new All(
+ Column::name('id'),
+ ComparisonOperator::GT,
+ $subquery
+ );
+
+ $node = $original->toAst();
+ $reconstructed = All::fromAst($node);
+
+ self::assertInstanceOf(All::class, $reconstructed);
+ self::assertSame(ComparisonOperator::GT, $reconstructed->operator);
+ self::assertInstanceOf(Node::class, $reconstructed->arrayOrSubquery);
+ }
+}
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
new file mode 100644
index 000000000..a4395f7be
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/AndConditionTest.php
@@ -0,0 +1,181 @@
+and($cond3);
+
+ $ast = $and2->toAst();
+
+ self::assertTrue($ast->hasBoolExpr());
+
+ $boolExpr = $ast->getBoolExpr();
+ self::assertNotNull($boolExpr);
+ self::assertSame(BoolExprType::AND_EXPR, $boolExpr->getBoolop());
+ self::assertCount(3, $boolExpr->getArgs());
+ }
+
+ public function test_and_method_returns_new_instance() : void
+ {
+ $cond1 = new RawCondition('x = 1');
+ $cond2 = new RawCondition('y = 2');
+
+ $original = new AndCondition($cond1);
+ $modified = $original->and($cond2);
+
+ self::assertNotSame($original, $modified);
+ }
+
+ 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');
+
+ $and1 = new AndCondition($cond1, $cond2);
+ $and2 = new AndCondition($cond3, $cond4);
+ $combined = $and1->and($and2);
+
+ $ast = $combined->toAst();
+
+ self::assertTrue($ast->hasBoolExpr());
+
+ $boolExpr = $ast->getBoolExpr();
+ self::assertNotNull($boolExpr);
+ self::assertCount(4, $boolExpr->getArgs());
+ }
+
+ public function test_and_with_single_condition() : void
+ {
+ $cond1 = new RawCondition('x = 1');
+ $cond2 = new RawCondition('y = 2');
+
+ $and = new AndCondition($cond1, $cond2);
+ $ast = $and->toAst();
+
+ self::assertTrue($ast->hasBoolExpr());
+
+ $boolExpr = $ast->getBoolExpr();
+ self::assertNotNull($boolExpr);
+ self::assertSame(BoolExprType::AND_EXPR, $boolExpr->getBoolop());
+ self::assertCount(2, $boolExpr->getArgs());
+ }
+
+ public function test_empty_and_condition() : void
+ {
+ $and = new AndCondition();
+ $ast = $and->toAst();
+
+ self::assertTrue($ast->hasBoolExpr());
+
+ $boolExpr = $ast->getBoolExpr();
+ self::assertNotNull($boolExpr);
+ self::assertSame(BoolExprType::AND_EXPR, $boolExpr->getBoolop());
+ self::assertCount(0, $boolExpr->getArgs());
+ }
+
+ public function test_from_ast_reconstructs_and_condition() : void
+ {
+ $cond1 = new RawCondition('x = 1');
+ $cond2 = new RawCondition('y = 2');
+
+ $original = new AndCondition($cond1, $cond2);
+ $ast = $original->toAst();
+
+ $reconstructed = AndCondition::fromAst($ast);
+
+ self::assertInstanceOf(AndCondition::class, $reconstructed);
+
+ $reconstructedAst = $reconstructed->toAst();
+ self::assertTrue($reconstructedAst->hasBoolExpr());
+
+ $boolExpr = $reconstructedAst->getBoolExpr();
+ self::assertNotNull($boolExpr);
+ self::assertCount(2, $boolExpr->getArgs());
+ }
+
+ public function test_from_ast_throws_on_non_bool_expr() : void
+ {
+ $this->expectException(InvalidAstException::class);
+ $this->expectExceptionMessage('Expected BoolExpr node, got unknown');
+
+ $node = new Node();
+ AndCondition::fromAst($node);
+ }
+
+ public function test_from_ast_throws_on_wrong_bool_type() : void
+ {
+ $this->expectException(InvalidAstException::class);
+ $this->expectExceptionMessage('Expected BoolExpr with AND_EXPR');
+
+ $boolExpr = new BoolExpr();
+ $boolExpr->setBoolop(BoolExprType::OR_EXPR);
+
+ $node = new Node();
+ $node->setBoolExpr($boolExpr);
+
+ AndCondition::fromAst($node);
+ }
+
+ public function test_not_returns_not_condition() : void
+ {
+ $cond1 = new RawCondition('x = 1');
+ $cond2 = new RawCondition('y = 2');
+
+ $and = new AndCondition($cond1, $cond2);
+ $not = $and->not();
+
+ self::assertInstanceOf(NotCondition::class, $not);
+ }
+
+ public function test_or_returns_or_condition() : void
+ {
+ $cond1 = new RawCondition('x = 1');
+ $cond2 = new RawCondition('y = 2');
+ $cond3 = new RawCondition('z = 3');
+
+ $and = new AndCondition($cond1, $cond2);
+ $or = $and->or($cond3);
+
+ self::assertInstanceOf(OrCondition::class, $or);
+ }
+
+ public function test_to_ast_creates_bool_expr() : void
+ {
+ $cond1 = new RawCondition('x = 1');
+ $cond2 = new RawCondition('y = 2');
+
+ $and = new AndCondition($cond1, $cond2);
+ $ast = $and->toAst();
+
+ self::assertInstanceOf(Node::class, $ast);
+ self::assertTrue($ast->hasBoolExpr());
+
+ $boolExpr = $ast->getBoolExpr();
+ self::assertNotNull($boolExpr);
+ self::assertSame(BoolExprType::AND_EXPR, $boolExpr->getBoolop());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/AnyTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/AnyTest.php
new file mode 100644
index 000000000..5a954a390
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/AnyTest.php
@@ -0,0 +1,138 @@
+and($condition2);
+
+ self::assertInstanceOf(AndCondition::class, $result);
+ }
+
+ public function test_converts_any_with_array_to_ast() : void
+ {
+ $condition = new Any(
+ Column::name('id'),
+ ComparisonOperator::EQ,
+ Literal::int(1)
+ );
+
+ $node = $condition->toAst();
+
+ self::assertTrue($node->hasAExpr());
+
+ $aExpr = $node->getAExpr();
+ self::assertNotNull($aExpr);
+ self::assertSame(A_Expr_Kind::AEXPR_OP_ANY, $aExpr->getKind());
+ }
+
+ public function test_converts_any_with_subquery_to_ast() : void
+ {
+ $subquery = new Node(['select_stmt' => new SelectStmt()]);
+
+ $condition = new Any(
+ Column::name('id'),
+ ComparisonOperator::GT,
+ $subquery
+ );
+
+ $node = $condition->toAst();
+
+ self::assertTrue($node->hasSubLink());
+
+ $subLink = $node->getSubLink();
+ self::assertNotNull($subLink);
+ self::assertSame(SubLinkType::ANY_SUBLINK, $subLink->getSubLinkType());
+ }
+
+ public function test_creates_any_condition_with_expression() : void
+ {
+ $condition = new Any(
+ Column::name('id'),
+ ComparisonOperator::EQ,
+ Literal::int(1)
+ );
+
+ self::assertInstanceOf(Any::class, $condition);
+ self::assertSame(ComparisonOperator::EQ, $condition->operator);
+ }
+
+ public function test_creates_any_condition_with_subquery() : void
+ {
+ $subquery = new Node(['select_stmt' => new SelectStmt()]);
+
+ $condition = new Any(
+ Column::name('id'),
+ ComparisonOperator::GT,
+ $subquery
+ );
+
+ self::assertInstanceOf(Any::class, $condition);
+ self::assertSame(ComparisonOperator::GT, $condition->operator);
+ self::assertInstanceOf(Node::class, $condition->arrayOrSubquery);
+ }
+
+ public function test_not_method_returns_not_condition() : void
+ {
+ $condition = new Any(Column::name('id'), ComparisonOperator::EQ, Literal::int(1));
+
+ $result = $condition->not();
+
+ self::assertInstanceOf(NotCondition::class, $result);
+ }
+
+ public function test_or_method_returns_or_condition() : void
+ {
+ $condition1 = new Any(Column::name('id'), ComparisonOperator::EQ, Literal::int(1));
+ $condition2 = new Any(Column::name('status'), ComparisonOperator::NEQ, Literal::string('inactive'));
+
+ $result = $condition1->or($condition2);
+
+ self::assertInstanceOf(OrCondition::class, $result);
+ }
+
+ public function test_reconstructs_any_with_array_from_ast() : void
+ {
+ $original = new Any(
+ Column::name('id'),
+ ComparisonOperator::LT,
+ Literal::int(10)
+ );
+
+ $node = $original->toAst();
+ $reconstructed = Any::fromAst($node);
+
+ self::assertInstanceOf(Any::class, $reconstructed);
+ self::assertSame(ComparisonOperator::LT, $reconstructed->operator);
+ }
+
+ public function test_reconstructs_any_with_subquery_from_ast() : void
+ {
+ $subquery = new Node(['select_stmt' => new SelectStmt()]);
+
+ $original = new Any(
+ Column::name('id'),
+ ComparisonOperator::GT,
+ $subquery
+ );
+
+ $node = $original->toAst();
+ $reconstructed = Any::fromAst($node);
+
+ self::assertInstanceOf(Any::class, $reconstructed);
+ self::assertSame(ComparisonOperator::GT, $reconstructed->operator);
+ self::assertInstanceOf(Node::class, $reconstructed->arrayOrSubquery);
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/BetweenTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/BetweenTest.php
new file mode 100644
index 000000000..ba96b6d93
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/BetweenTest.php
@@ -0,0 +1,220 @@
+and($cond2);
+
+ self::assertInstanceOf(AndCondition::class, $and);
+ }
+
+ public function test_between_basic_to_ast() : void
+ {
+ $between = new Between(
+ Column::name('age'),
+ Literal::int(18),
+ Literal::int(65)
+ );
+
+ $ast = $between->toAst();
+
+ self::assertInstanceOf(Node::class, $ast);
+ self::assertTrue($ast->hasAExpr());
+
+ $aExpr = $ast->getAExpr();
+ self::assertNotNull($aExpr);
+ self::assertSame(A_Expr_Kind::AEXPR_BETWEEN, $aExpr->getKind());
+
+ $rexpr = $aExpr->getRexpr();
+ self::assertNotNull($rexpr);
+ self::assertTrue($rexpr->hasList());
+
+ $list = $rexpr->getList();
+ self::assertNotNull($list);
+ $items = $list->getItems();
+ self::assertCount(2, $items);
+ }
+
+ public function test_between_negated_to_ast() : void
+ {
+ $between = new Between(
+ Column::name('score'),
+ Literal::int(0),
+ Literal::int(50),
+ false,
+ true
+ );
+
+ $ast = $between->toAst();
+
+ self::assertTrue($ast->hasAExpr());
+
+ $aExpr = $ast->getAExpr();
+ self::assertNotNull($aExpr);
+ self::assertSame(A_Expr_Kind::AEXPR_NOT_BETWEEN, $aExpr->getKind());
+ }
+
+ public function test_between_symmetric_negated_to_ast() : void
+ {
+ $between = new Between(
+ Column::name('value'),
+ Literal::int(1),
+ Literal::int(100),
+ true,
+ true
+ );
+
+ $ast = $between->toAst();
+
+ self::assertTrue($ast->hasAExpr());
+
+ $aExpr = $ast->getAExpr();
+ self::assertNotNull($aExpr);
+ self::assertSame(A_Expr_Kind::AEXPR_NOT_BETWEEN_SYM, $aExpr->getKind());
+ }
+
+ public function test_between_symmetric_to_ast() : void
+ {
+ $between = new Between(
+ Column::name('price'),
+ Literal::float(10.0),
+ Literal::float(100.0),
+ true,
+ false
+ );
+
+ $ast = $between->toAst();
+
+ self::assertTrue($ast->hasAExpr());
+
+ $aExpr = $ast->getAExpr();
+ self::assertNotNull($aExpr);
+ self::assertSame(A_Expr_Kind::AEXPR_BETWEEN_SYM, $aExpr->getKind());
+ }
+
+ public function test_from_ast_reconstructs_between() : void
+ {
+ $original = new Between(
+ Column::name('date'),
+ Literal::string('2024-01-01'),
+ Literal::string('2024-12-31')
+ );
+
+ $ast = $original->toAst();
+ $reconstructed = Between::fromAst($ast);
+
+ self::assertInstanceOf(Between::class, $reconstructed);
+ self::assertFalse($reconstructed->symmetric);
+ self::assertFalse($reconstructed->negated);
+
+ $reconstructedAst = $reconstructed->toAst();
+ self::assertTrue($reconstructedAst->hasAExpr());
+
+ $aExpr = $reconstructedAst->getAExpr();
+ self::assertNotNull($aExpr);
+ self::assertSame(A_Expr_Kind::AEXPR_BETWEEN, $aExpr->getKind());
+ }
+
+ public function test_from_ast_reconstructs_negated_between() : void
+ {
+ $original = new Between(
+ Column::name('id'),
+ Literal::int(1),
+ Literal::int(10),
+ false,
+ true
+ );
+
+ $ast = $original->toAst();
+ $reconstructed = Between::fromAst($ast);
+
+ self::assertInstanceOf(Between::class, $reconstructed);
+ self::assertFalse($reconstructed->symmetric);
+ self::assertTrue($reconstructed->negated);
+ }
+
+ public function test_from_ast_reconstructs_symmetric_between() : void
+ {
+ $original = new Between(
+ Column::name('value'),
+ Literal::int(10),
+ Literal::int(20),
+ true,
+ false
+ );
+
+ $ast = $original->toAst();
+ $reconstructed = Between::fromAst($ast);
+
+ self::assertInstanceOf(Between::class, $reconstructed);
+ self::assertTrue($reconstructed->symmetric);
+ self::assertFalse($reconstructed->negated);
+ }
+
+ public function test_from_ast_throws_on_non_a_expr() : void
+ {
+ $this->expectException(InvalidAstException::class);
+ $this->expectExceptionMessage('Expected A_Expr node, got unknown');
+
+ $node = new Node();
+ Between::fromAst($node);
+ }
+
+ public function test_from_ast_throws_on_wrong_kind() : void
+ {
+ $this->expectException(InvalidAstException::class);
+ $this->expectExceptionMessage('Expected BETWEEN variant for Between condition');
+
+ $aExpr = new A_Expr();
+ $aExpr->setKind(A_Expr_Kind::AEXPR_OP);
+
+ $node = new Node();
+ $node->setAExpr($aExpr);
+
+ Between::fromAst($node);
+ }
+
+ public function test_not_returns_not_condition() : void
+ {
+ $between = new Between(
+ Column::name('age'),
+ Literal::int(18),
+ Literal::int(65)
+ );
+
+ $not = $between->not();
+
+ self::assertInstanceOf(NotCondition::class, $not);
+ }
+
+ public function test_or_returns_or_condition() : void
+ {
+ $cond1 = new Between(Column::name('x'), Literal::int(1), Literal::int(10));
+ $cond2 = new Between(Column::name('y'), Literal::int(20), Literal::int(30));
+
+ $or = $cond1->or($cond2);
+
+ self::assertInstanceOf(OrCondition::class, $or);
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/ComparisonTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/ComparisonTest.php
new file mode 100644
index 000000000..c416f4de4
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/ComparisonTest.php
@@ -0,0 +1,235 @@
+and($cond2);
+
+ self::assertInstanceOf(AndCondition::class, $and);
+ }
+
+ public function test_comparison_eq_to_ast() : void
+ {
+ $comparison = new Comparison(
+ Column::name('status'),
+ ComparisonOperator::EQ,
+ Literal::string('active')
+ );
+
+ $ast = $comparison->toAst();
+
+ self::assertInstanceOf(Node::class, $ast);
+ self::assertTrue($ast->hasAExpr());
+
+ $aExpr = $ast->getAExpr();
+ self::assertNotNull($aExpr);
+ self::assertSame(A_Expr_Kind::AEXPR_OP, $aExpr->getKind());
+
+ $name = $aExpr->getName();
+ self::assertNotNull($name);
+ self::assertCount(1, $name);
+
+ $operatorNode = $name->offsetGet(0);
+ $operatorString = $operatorNode->getString();
+ self::assertNotNull($operatorString);
+ self::assertSame('=', $operatorString->getSval());
+ }
+
+ public function test_comparison_gt_to_ast() : void
+ {
+ $comparison = new Comparison(
+ Column::name('age'),
+ ComparisonOperator::GT,
+ Literal::int(18)
+ );
+
+ $ast = $comparison->toAst();
+
+ self::assertTrue($ast->hasAExpr());
+
+ $aExpr = $ast->getAExpr();
+ self::assertNotNull($aExpr);
+ $name = $aExpr->getName();
+ self::assertNotNull($name);
+ $operatorNode = $name->offsetGet(0);
+ $operatorString = $operatorNode->getString();
+ self::assertNotNull($operatorString);
+ self::assertSame('>', $operatorString->getSval());
+ }
+
+ public function test_comparison_gte_to_ast() : void
+ {
+ $comparison = new Comparison(
+ Column::name('score'),
+ ComparisonOperator::GTE,
+ Literal::int(100)
+ );
+
+ $ast = $comparison->toAst();
+
+ self::assertTrue($ast->hasAExpr());
+
+ $aExpr = $ast->getAExpr();
+ self::assertNotNull($aExpr);
+ $name = $aExpr->getName();
+ self::assertNotNull($name);
+ $operatorNode = $name->offsetGet(0);
+ $operatorString = $operatorNode->getString();
+ self::assertNotNull($operatorString);
+ self::assertSame('>=', $operatorString->getSval());
+ }
+
+ public function test_comparison_lt_to_ast() : void
+ {
+ $comparison = new Comparison(
+ Column::name('price'),
+ ComparisonOperator::LT,
+ Literal::float(99.99)
+ );
+
+ $ast = $comparison->toAst();
+
+ self::assertTrue($ast->hasAExpr());
+
+ $aExpr = $ast->getAExpr();
+ self::assertNotNull($aExpr);
+ $name = $aExpr->getName();
+ self::assertNotNull($name);
+ $operatorNode = $name->offsetGet(0);
+ $operatorString = $operatorNode->getString();
+ self::assertNotNull($operatorString);
+ self::assertSame('<', $operatorString->getSval());
+ }
+
+ public function test_comparison_lte_to_ast() : void
+ {
+ $comparison = new Comparison(
+ Column::name('quantity'),
+ ComparisonOperator::LTE,
+ Literal::int(10)
+ );
+
+ $ast = $comparison->toAst();
+
+ self::assertTrue($ast->hasAExpr());
+
+ $aExpr = $ast->getAExpr();
+ self::assertNotNull($aExpr);
+ $name = $aExpr->getName();
+ self::assertNotNull($name);
+ $operatorNode = $name->offsetGet(0);
+ $operatorString = $operatorNode->getString();
+ self::assertNotNull($operatorString);
+ self::assertSame('<=', $operatorString->getSval());
+ }
+
+ public function test_comparison_neq_to_ast() : void
+ {
+ $comparison = new Comparison(
+ Column::name('status'),
+ ComparisonOperator::NEQ,
+ Literal::string('deleted')
+ );
+
+ $ast = $comparison->toAst();
+
+ self::assertTrue($ast->hasAExpr());
+
+ $aExpr = $ast->getAExpr();
+ self::assertNotNull($aExpr);
+ $name = $aExpr->getName();
+ self::assertNotNull($name);
+ $operatorNode = $name->offsetGet(0);
+ $operatorString = $operatorNode->getString();
+ self::assertNotNull($operatorString);
+ self::assertSame('<>', $operatorString->getSval());
+ }
+
+ public function test_from_ast_reconstructs_comparison() : void
+ {
+ $original = new Comparison(
+ Column::name('id'),
+ ComparisonOperator::EQ,
+ Literal::int(42)
+ );
+
+ $ast = $original->toAst();
+ $reconstructed = Comparison::fromAst($ast);
+
+ self::assertInstanceOf(Comparison::class, $reconstructed);
+
+ $reconstructedAst = $reconstructed->toAst();
+ self::assertTrue($reconstructedAst->hasAExpr());
+
+ $aExpr = $reconstructedAst->getAExpr();
+ self::assertNotNull($aExpr);
+ self::assertSame(A_Expr_Kind::AEXPR_OP, $aExpr->getKind());
+ }
+
+ public function test_from_ast_throws_on_non_a_expr() : void
+ {
+ $this->expectException(InvalidAstException::class);
+ $this->expectExceptionMessage('Expected A_Expr node, got unknown');
+
+ $node = new Node();
+ Comparison::fromAst($node);
+ }
+
+ public function test_from_ast_throws_on_wrong_kind() : void
+ {
+ $this->expectException(InvalidAstException::class);
+ $this->expectExceptionMessage('Expected AEXPR_OP for Comparison');
+
+ $aExpr = new A_Expr();
+ $aExpr->setKind(A_Expr_Kind::AEXPR_IN);
+
+ $node = new Node();
+ $node->setAExpr($aExpr);
+
+ Comparison::fromAst($node);
+ }
+
+ public function test_not_returns_not_condition() : void
+ {
+ $comparison = new Comparison(
+ Column::name('active'),
+ ComparisonOperator::EQ,
+ Literal::bool(true)
+ );
+
+ $not = $comparison->not();
+
+ self::assertInstanceOf(NotCondition::class, $not);
+ }
+
+ public function test_or_returns_or_condition() : void
+ {
+ $cond1 = new Comparison(Column::name('x'), ComparisonOperator::EQ, Literal::int(1));
+ $cond2 = new Comparison(Column::name('y'), ComparisonOperator::EQ, Literal::int(2));
+
+ $or = $cond1->or($cond2);
+
+ self::assertInstanceOf(OrCondition::class, $or);
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/ExistsTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/ExistsTest.php
new file mode 100644
index 000000000..c7a25f1bd
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/ExistsTest.php
@@ -0,0 +1,85 @@
+ new SelectStmt()]);
+ $subquery2 = new Node(['select_stmt' => new SelectStmt()]);
+
+ $condition1 = new Exists($subquery1);
+ $condition2 = new Exists($subquery2);
+
+ $result = $condition1->and($condition2);
+
+ self::assertInstanceOf(AndCondition::class, $result);
+ }
+
+ public function test_converts_to_ast() : void
+ {
+ $subquery = new Node(['select_stmt' => new SelectStmt()]);
+ $condition = new Exists($subquery);
+
+ $node = $condition->toAst();
+
+ self::assertTrue($node->hasSubLink());
+
+ $subLink = $node->getSubLink();
+ self::assertNotNull($subLink);
+ self::assertSame(SubLinkType::EXISTS_SUBLINK, $subLink->getSubLinkType());
+ self::assertTrue($subLink->hasSubselect());
+ }
+
+ public function test_creates_exists_condition() : void
+ {
+ $subquery = new Node(['select_stmt' => new SelectStmt()]);
+
+ $condition = new Exists($subquery);
+
+ self::assertInstanceOf(Exists::class, $condition);
+ self::assertSame($subquery, $condition->subquery);
+ }
+
+ public function test_not_method_returns_not_condition() : void
+ {
+ $subquery = new Node(['select_stmt' => new SelectStmt()]);
+ $condition = new Exists($subquery);
+
+ $result = $condition->not();
+
+ self::assertInstanceOf(NotCondition::class, $result);
+ }
+
+ public function test_or_method_returns_or_condition() : void
+ {
+ $subquery1 = new Node(['select_stmt' => new SelectStmt()]);
+ $subquery2 = new Node(['select_stmt' => new SelectStmt()]);
+
+ $condition1 = new Exists($subquery1);
+ $condition2 = new Exists($subquery2);
+
+ $result = $condition1->or($condition2);
+
+ self::assertInstanceOf(OrCondition::class, $result);
+ }
+
+ public function test_reconstructs_from_ast() : void
+ {
+ $subquery = new Node(['select_stmt' => new SelectStmt()]);
+ $original = new Exists($subquery);
+
+ $node = $original->toAst();
+ $reconstructed = Exists::fromAst($node);
+
+ self::assertInstanceOf(Exists::class, $reconstructed);
+ self::assertInstanceOf(Node::class, $reconstructed->subquery);
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/InTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/InTest.php
new file mode 100644
index 000000000..b5409651d
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/InTest.php
@@ -0,0 +1,182 @@
+and($cond2);
+
+ self::assertInstanceOf(AndCondition::class, $and);
+ }
+
+ public function test_from_ast_reconstructs_in() : void
+ {
+ $original = new In(
+ Column::name('status'),
+ [
+ Literal::string('active'),
+ Literal::string('pending'),
+ Literal::string('completed'),
+ ]
+ );
+
+ $ast = $original->toAst();
+ $reconstructed = In::fromAst($ast);
+
+ self::assertInstanceOf(In::class, $reconstructed);
+ self::assertCount(3, $reconstructed->values);
+
+ $reconstructedAst = $reconstructed->toAst();
+ self::assertTrue($reconstructedAst->hasAExpr());
+
+ $aExpr = $reconstructedAst->getAExpr();
+ self::assertNotNull($aExpr);
+ self::assertSame(A_Expr_Kind::AEXPR_IN, $aExpr->getKind());
+ }
+
+ public function test_from_ast_throws_on_non_a_expr() : void
+ {
+ $this->expectException(InvalidAstException::class);
+ $this->expectExceptionMessage('Expected A_Expr node, got unknown');
+
+ $node = new Node();
+ In::fromAst($node);
+ }
+
+ public function test_from_ast_throws_on_wrong_kind() : void
+ {
+ $this->expectException(InvalidAstException::class);
+ $this->expectExceptionMessage('Expected AEXPR_IN for In condition');
+
+ $aExpr = new A_Expr();
+ $aExpr->setKind(A_Expr_Kind::AEXPR_OP);
+
+ $node = new Node();
+ $node->setAExpr($aExpr);
+
+ In::fromAst($node);
+ }
+
+ public function test_in_empty_values_to_ast() : void
+ {
+ $in = new In(
+ Column::name('id'),
+ []
+ );
+
+ $ast = $in->toAst();
+
+ self::assertInstanceOf(Node::class, $ast);
+ self::assertTrue($ast->hasAExpr());
+
+ $aExpr = $ast->getAExpr();
+ self::assertNotNull($aExpr);
+ self::assertSame(A_Expr_Kind::AEXPR_IN, $aExpr->getKind());
+
+ $rexpr = $aExpr->getRexpr();
+ self::assertNotNull($rexpr);
+ self::assertTrue($rexpr->hasList());
+
+ $list = $rexpr->getList();
+ self::assertNotNull($list);
+ $items = $list->getItems();
+ self::assertCount(0, $items);
+ }
+
+ public function test_in_multiple_values_to_ast() : void
+ {
+ $in = new In(
+ Column::name('category_id'),
+ [
+ Literal::int(1),
+ Literal::int(2),
+ Literal::int(3),
+ Literal::int(5),
+ ]
+ );
+
+ $ast = $in->toAst();
+
+ self::assertInstanceOf(Node::class, $ast);
+ self::assertTrue($ast->hasAExpr());
+
+ $aExpr = $ast->getAExpr();
+ self::assertNotNull($aExpr);
+ self::assertSame(A_Expr_Kind::AEXPR_IN, $aExpr->getKind());
+
+ $rexpr = $aExpr->getRexpr();
+ self::assertNotNull($rexpr);
+ self::assertTrue($rexpr->hasList());
+
+ $list = $rexpr->getList();
+ self::assertNotNull($list);
+ $items = $list->getItems();
+ self::assertCount(4, $items);
+ }
+
+ public function test_in_single_value_to_ast() : void
+ {
+ $in = new In(
+ Column::name('status'),
+ [Literal::string('active')]
+ );
+
+ $ast = $in->toAst();
+
+ self::assertTrue($ast->hasAExpr());
+
+ $aExpr = $ast->getAExpr();
+ self::assertNotNull($aExpr);
+ self::assertSame(A_Expr_Kind::AEXPR_IN, $aExpr->getKind());
+
+ $rexpr = $aExpr->getRexpr();
+ self::assertNotNull($rexpr);
+
+ $list = $rexpr->getList();
+ self::assertNotNull($list);
+ $items = $list->getItems();
+ self::assertCount(1, $items);
+ }
+
+ public function test_not_returns_not_condition() : void
+ {
+ $in = new In(
+ Column::name('id'),
+ [Literal::int(1), Literal::int(2)]
+ );
+
+ $not = $in->not();
+
+ self::assertInstanceOf(NotCondition::class, $not);
+ }
+
+ public function test_or_returns_or_condition() : void
+ {
+ $cond1 = new In(Column::name('x'), [Literal::int(1), Literal::int(2)]);
+ $cond2 = new In(Column::name('y'), [Literal::int(3), Literal::int(4)]);
+
+ $or = $cond1->or($cond2);
+
+ self::assertInstanceOf(OrCondition::class, $or);
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/IsDistinctFromTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/IsDistinctFromTest.php
new file mode 100644
index 000000000..0537d1a62
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/IsDistinctFromTest.php
@@ -0,0 +1,132 @@
+and($condition2);
+
+ self::assertInstanceOf(AndCondition::class, $result);
+ }
+
+ public function test_converts_is_distinct_from_to_ast() : void
+ {
+ $condition = new IsDistinctFrom(
+ Column::name('status'),
+ Literal::null(),
+ false
+ );
+
+ $node = $condition->toAst();
+
+ self::assertTrue($node->hasAExpr());
+
+ $aExpr = $node->getAExpr();
+ self::assertNotNull($aExpr);
+ self::assertSame(A_Expr_Kind::AEXPR_DISTINCT, $aExpr->getKind());
+ self::assertTrue($aExpr->hasLexpr());
+ self::assertTrue($aExpr->hasRexpr());
+ }
+
+ public function test_converts_is_not_distinct_from_to_ast() : void
+ {
+ $condition = new IsDistinctFrom(
+ Column::name('status'),
+ Literal::null(),
+ true
+ );
+
+ $node = $condition->toAst();
+
+ self::assertTrue($node->hasAExpr());
+
+ $aExpr = $node->getAExpr();
+ self::assertNotNull($aExpr);
+ self::assertSame(A_Expr_Kind::AEXPR_NOT_DISTINCT, $aExpr->getKind());
+ }
+
+ public function test_creates_is_distinct_from_condition() : void
+ {
+ $condition = new IsDistinctFrom(
+ Column::name('status'),
+ Literal::null(),
+ false
+ );
+
+ self::assertInstanceOf(IsDistinctFrom::class, $condition);
+ self::assertFalse($condition->negated);
+ }
+
+ public function test_creates_is_not_distinct_from_condition() : void
+ {
+ $condition = new IsDistinctFrom(
+ Column::name('status'),
+ Literal::null(),
+ true
+ );
+
+ self::assertInstanceOf(IsDistinctFrom::class, $condition);
+ self::assertTrue($condition->negated);
+ }
+
+ public function test_not_method_returns_not_condition() : void
+ {
+ $condition = new IsDistinctFrom(Column::name('status'), Literal::null(), false);
+
+ $result = $condition->not();
+
+ self::assertInstanceOf(NotCondition::class, $result);
+ }
+
+ public function test_or_method_returns_or_condition() : void
+ {
+ $condition1 = new IsDistinctFrom(Column::name('status'), Literal::null(), false);
+ $condition2 = new IsDistinctFrom(Column::name('value'), Literal::int(0), false);
+
+ $result = $condition1->or($condition2);
+
+ self::assertInstanceOf(OrCondition::class, $result);
+ }
+
+ public function test_reconstructs_is_distinct_from_from_ast() : void
+ {
+ $original = new IsDistinctFrom(
+ Column::name('status'),
+ Literal::null(),
+ false
+ );
+
+ $node = $original->toAst();
+ $reconstructed = IsDistinctFrom::fromAst($node);
+
+ self::assertInstanceOf(IsDistinctFrom::class, $reconstructed);
+ self::assertFalse($reconstructed->negated);
+ }
+
+ public function test_reconstructs_is_not_distinct_from_from_ast() : void
+ {
+ $original = new IsDistinctFrom(
+ Column::name('status'),
+ Literal::null(),
+ true
+ );
+
+ $node = $original->toAst();
+ $reconstructed = IsDistinctFrom::fromAst($node);
+
+ self::assertInstanceOf(IsDistinctFrom::class, $reconstructed);
+ self::assertTrue($reconstructed->negated);
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/IsNullTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/IsNullTest.php
new file mode 100644
index 000000000..56ee0d579
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/IsNullTest.php
@@ -0,0 +1,135 @@
+and($cond2);
+
+ self::assertInstanceOf(AndCondition::class, $and);
+ }
+
+ public function test_from_ast_reconstructs_is_not_null() : void
+ {
+ $original = new IsNull(
+ Column::name('email'),
+ true
+ );
+
+ $ast = $original->toAst();
+ $reconstructed = IsNull::fromAst($ast);
+
+ self::assertInstanceOf(IsNull::class, $reconstructed);
+ self::assertTrue($reconstructed->negated);
+
+ $reconstructedAst = $reconstructed->toAst();
+ self::assertTrue($reconstructedAst->hasNullTest());
+
+ $nullTest = $reconstructedAst->getNullTest();
+ self::assertNotNull($nullTest);
+ self::assertSame(NullTestType::IS_NOT_NULL, $nullTest->getNulltesttype());
+ }
+
+ public function test_from_ast_reconstructs_is_null() : void
+ {
+ $original = new IsNull(
+ Column::name('deleted_at')
+ );
+
+ $ast = $original->toAst();
+ $reconstructed = IsNull::fromAst($ast);
+
+ self::assertInstanceOf(IsNull::class, $reconstructed);
+ self::assertFalse($reconstructed->negated);
+
+ $reconstructedAst = $reconstructed->toAst();
+ self::assertTrue($reconstructedAst->hasNullTest());
+
+ $nullTest = $reconstructedAst->getNullTest();
+ self::assertNotNull($nullTest);
+ self::assertSame(NullTestType::IS_NULL, $nullTest->getNulltesttype());
+ }
+
+ public function test_from_ast_throws_on_non_null_test() : void
+ {
+ $this->expectException(InvalidAstException::class);
+ $this->expectExceptionMessage('Expected NullTest node, got unknown');
+
+ $node = new Node();
+ IsNull::fromAst($node);
+ }
+
+ public function test_is_not_null_to_ast() : void
+ {
+ $isNull = new IsNull(
+ Column::name('description'),
+ true
+ );
+
+ $ast = $isNull->toAst();
+
+ self::assertInstanceOf(Node::class, $ast);
+ self::assertTrue($ast->hasNullTest());
+
+ $nullTest = $ast->getNullTest();
+ self::assertNotNull($nullTest);
+ self::assertSame(NullTestType::IS_NOT_NULL, $nullTest->getNulltesttype());
+ self::assertNotNull($nullTest->getArg());
+ }
+
+ public function test_is_null_to_ast() : void
+ {
+ $isNull = new IsNull(
+ Column::name('deleted_at')
+ );
+
+ $ast = $isNull->toAst();
+
+ self::assertInstanceOf(Node::class, $ast);
+ self::assertTrue($ast->hasNullTest());
+
+ $nullTest = $ast->getNullTest();
+ self::assertNotNull($nullTest);
+ self::assertSame(NullTestType::IS_NULL, $nullTest->getNulltesttype());
+ self::assertNotNull($nullTest->getArg());
+ }
+
+ public function test_not_returns_not_condition() : void
+ {
+ $isNull = new IsNull(Column::name('value'));
+
+ $not = $isNull->not();
+
+ self::assertInstanceOf(NotCondition::class, $not);
+ }
+
+ public function test_or_returns_or_condition() : void
+ {
+ $cond1 = new IsNull(Column::name('x'));
+ $cond2 = new IsNull(Column::name('y'));
+
+ $or = $cond1->or($cond2);
+
+ self::assertInstanceOf(OrCondition::class, $or);
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/LikeTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/LikeTest.php
new file mode 100644
index 000000000..eaf4761d3
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/LikeTest.php
@@ -0,0 +1,132 @@
+and($condition2);
+
+ self::assertInstanceOf(AndCondition::class, $result);
+ }
+
+ public function test_converts_ilike_to_ast() : void
+ {
+ $condition = new Like(
+ Column::name('name'),
+ Literal::string('%test%'),
+ true
+ );
+
+ $node = $condition->toAst();
+
+ self::assertTrue($node->hasAExpr());
+
+ $aExpr = $node->getAExpr();
+ self::assertNotNull($aExpr);
+ self::assertSame(A_Expr_Kind::AEXPR_ILIKE, $aExpr->getKind());
+ }
+
+ public function test_converts_like_to_ast() : void
+ {
+ $condition = new Like(
+ Column::name('name'),
+ Literal::string('%test%'),
+ false
+ );
+
+ $node = $condition->toAst();
+
+ self::assertTrue($node->hasAExpr());
+
+ $aExpr = $node->getAExpr();
+ self::assertNotNull($aExpr);
+ self::assertSame(A_Expr_Kind::AEXPR_LIKE, $aExpr->getKind());
+ self::assertTrue($aExpr->hasLexpr());
+ self::assertTrue($aExpr->hasRexpr());
+ }
+
+ public function test_creates_ilike_condition() : void
+ {
+ $condition = new Like(
+ Column::name('name'),
+ Literal::string('%test%'),
+ true
+ );
+
+ self::assertInstanceOf(Like::class, $condition);
+ self::assertTrue($condition->caseInsensitive);
+ }
+
+ public function test_creates_like_condition() : void
+ {
+ $condition = new Like(
+ Column::name('name'),
+ Literal::string('%test%'),
+ false
+ );
+
+ self::assertInstanceOf(Like::class, $condition);
+ self::assertFalse($condition->caseInsensitive);
+ }
+
+ public function test_not_method_returns_not_condition() : void
+ {
+ $condition = new Like(Column::name('name'), Literal::string('%test%'), false);
+
+ $result = $condition->not();
+
+ self::assertInstanceOf(NotCondition::class, $result);
+ }
+
+ public function test_or_method_returns_or_condition() : void
+ {
+ $condition1 = new Like(Column::name('name'), Literal::string('%test%'), false);
+ $condition2 = new Like(Column::name('email'), Literal::string('%@example.com'), false);
+
+ $result = $condition1->or($condition2);
+
+ self::assertInstanceOf(OrCondition::class, $result);
+ }
+
+ public function test_reconstructs_ilike_from_ast() : void
+ {
+ $original = new Like(
+ Column::name('name'),
+ Literal::string('%test%'),
+ true
+ );
+
+ $node = $original->toAst();
+ $reconstructed = Like::fromAst($node);
+
+ self::assertInstanceOf(Like::class, $reconstructed);
+ self::assertTrue($reconstructed->caseInsensitive);
+ }
+
+ public function test_reconstructs_like_from_ast() : void
+ {
+ $original = new Like(
+ Column::name('name'),
+ Literal::string('%test%'),
+ false
+ );
+
+ $node = $original->toAst();
+ $reconstructed = Like::fromAst($node);
+
+ self::assertInstanceOf(Like::class, $reconstructed);
+ self::assertFalse($reconstructed->caseInsensitive);
+ }
+}
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
new file mode 100644
index 000000000..57f286dde
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/NotConditionTest.php
@@ -0,0 +1,177 @@
+and($cond2);
+
+ self::assertInstanceOf(AndCondition::class, $and);
+ }
+
+ public function test_double_negation() : void
+ {
+ $cond = new RawCondition('x = 1');
+ $not1 = new NotCondition($cond);
+ $not2 = $not1->not();
+
+ $ast = $not2->toAst();
+
+ self::assertTrue($ast->hasBoolExpr());
+
+ $boolExpr = $ast->getBoolExpr();
+ self::assertNotNull($boolExpr);
+ self::assertSame(BoolExprType::NOT_EXPR, $boolExpr->getBoolop());
+ self::assertCount(1, $boolExpr->getArgs());
+
+ $innerNode = $boolExpr->getArgs()[0];
+ self::assertTrue($innerNode->hasBoolExpr());
+
+ $innerBoolExpr = $innerNode->getBoolExpr();
+ self::assertNotNull($innerBoolExpr);
+ self::assertSame(BoolExprType::NOT_EXPR, $innerBoolExpr->getBoolop());
+ }
+
+ public function test_from_ast_reconstructs_not_condition() : void
+ {
+ $cond = new RawCondition('x = 1');
+ $original = new NotCondition($cond);
+ $ast = $original->toAst();
+
+ $reconstructed = NotCondition::fromAst($ast);
+
+ self::assertInstanceOf(NotCondition::class, $reconstructed);
+
+ $reconstructedAst = $reconstructed->toAst();
+ self::assertTrue($reconstructedAst->hasBoolExpr());
+
+ $boolExpr = $reconstructedAst->getBoolExpr();
+ self::assertNotNull($boolExpr);
+ self::assertSame(BoolExprType::NOT_EXPR, $boolExpr->getBoolop());
+ self::assertCount(1, $boolExpr->getArgs());
+ }
+
+ public function test_from_ast_throws_on_empty_args() : void
+ {
+ $this->expectException(InvalidAstException::class);
+ $this->expectExceptionMessage('NOT_EXPR must have exactly one argument, got 0');
+
+ $boolExpr = new BoolExpr();
+ $boolExpr->setBoolop(BoolExprType::NOT_EXPR);
+ $boolExpr->setArgs([]);
+
+ $node = new Node();
+ $node->setBoolExpr($boolExpr);
+
+ NotCondition::fromAst($node);
+ }
+
+ 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');
+
+ $boolExpr = new BoolExpr();
+ $boolExpr->setBoolop(BoolExprType::NOT_EXPR);
+ $boolExpr->setArgs([$cond1->toAst(), $cond2->toAst()]);
+
+ $node = new Node();
+ $node->setBoolExpr($boolExpr);
+
+ NotCondition::fromAst($node);
+ }
+
+ public function test_from_ast_throws_on_non_bool_expr() : void
+ {
+ $this->expectException(InvalidAstException::class);
+ $this->expectExceptionMessage('Expected BoolExpr node, got unknown');
+
+ $node = new Node();
+ NotCondition::fromAst($node);
+ }
+
+ public function test_from_ast_throws_on_wrong_bool_type() : void
+ {
+ $this->expectException(InvalidAstException::class);
+ $this->expectExceptionMessage('Expected BoolExpr with NOT_EXPR');
+
+ $boolExpr = new BoolExpr();
+ $boolExpr->setBoolop(BoolExprType::AND_EXPR);
+
+ $node = new Node();
+ $node->setBoolExpr($boolExpr);
+
+ NotCondition::fromAst($node);
+ }
+
+ public function test_not_negates_condition() : void
+ {
+ $cond = new RawCondition('x = 1');
+ $not = new NotCondition($cond);
+ $ast = $not->toAst();
+
+ self::assertTrue($ast->hasBoolExpr());
+
+ $boolExpr = $ast->getBoolExpr();
+ self::assertNotNull($boolExpr);
+ self::assertSame(BoolExprType::NOT_EXPR, $boolExpr->getBoolop());
+ self::assertCount(1, $boolExpr->getArgs());
+ }
+
+ public function test_not_returns_not_condition() : void
+ {
+ $cond = new RawCondition('x = 1');
+ $not = new NotCondition($cond);
+ $notNot = $not->not();
+
+ self::assertInstanceOf(NotCondition::class, $notNot);
+ }
+
+ public function test_or_returns_or_condition() : void
+ {
+ $cond1 = new RawCondition('x = 1');
+ $cond2 = new RawCondition('y = 2');
+
+ $not = new NotCondition($cond1);
+ $or = $not->or($cond2);
+
+ self::assertInstanceOf(OrCondition::class, $or);
+ }
+
+ public function test_to_ast_creates_bool_expr() : void
+ {
+ $cond = new RawCondition('x = 1');
+ $not = new NotCondition($cond);
+ $ast = $not->toAst();
+
+ self::assertInstanceOf(Node::class, $ast);
+ self::assertTrue($ast->hasBoolExpr());
+
+ $boolExpr = $ast->getBoolExpr();
+ self::assertNotNull($boolExpr);
+ self::assertSame(BoolExprType::NOT_EXPR, $boolExpr->getBoolop());
+ }
+}
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
new file mode 100644
index 000000000..daec5c418
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/OrConditionTest.php
@@ -0,0 +1,181 @@
+and($cond3);
+
+ self::assertInstanceOf(AndCondition::class, $and);
+ }
+
+ public function test_empty_or_condition() : void
+ {
+ $or = new OrCondition();
+ $ast = $or->toAst();
+
+ self::assertTrue($ast->hasBoolExpr());
+
+ $boolExpr = $ast->getBoolExpr();
+ self::assertNotNull($boolExpr);
+ self::assertSame(BoolExprType::OR_EXPR, $boolExpr->getBoolop());
+ self::assertCount(0, $boolExpr->getArgs());
+ }
+
+ public function test_from_ast_reconstructs_or_condition() : void
+ {
+ $cond1 = new RawCondition('x = 1');
+ $cond2 = new RawCondition('y = 2');
+
+ $original = new OrCondition($cond1, $cond2);
+ $ast = $original->toAst();
+
+ $reconstructed = OrCondition::fromAst($ast);
+
+ self::assertInstanceOf(OrCondition::class, $reconstructed);
+
+ $reconstructedAst = $reconstructed->toAst();
+ self::assertTrue($reconstructedAst->hasBoolExpr());
+
+ $boolExpr = $reconstructedAst->getBoolExpr();
+ self::assertNotNull($boolExpr);
+ self::assertCount(2, $boolExpr->getArgs());
+ }
+
+ public function test_from_ast_throws_on_non_bool_expr() : void
+ {
+ $this->expectException(InvalidAstException::class);
+ $this->expectExceptionMessage('Expected BoolExpr node, got unknown');
+
+ $node = new Node();
+ OrCondition::fromAst($node);
+ }
+
+ public function test_from_ast_throws_on_wrong_bool_type() : void
+ {
+ $this->expectException(InvalidAstException::class);
+ $this->expectExceptionMessage('Expected BoolExpr with OR_EXPR');
+
+ $boolExpr = new BoolExpr();
+ $boolExpr->setBoolop(BoolExprType::AND_EXPR);
+
+ $node = new Node();
+ $node->setBoolExpr($boolExpr);
+
+ OrCondition::fromAst($node);
+ }
+
+ public function test_not_returns_not_condition() : void
+ {
+ $cond1 = new RawCondition('x = 1');
+ $cond2 = new RawCondition('y = 2');
+
+ $or = new OrCondition($cond1, $cond2);
+ $not = $or->not();
+
+ self::assertInstanceOf(NotCondition::class, $not);
+ }
+
+ public function test_or_flattens_multiple_or_conditions() : void
+ {
+ $cond1 = new RawCondition('x = 1');
+ $cond2 = new RawCondition('y = 2');
+ $cond3 = new RawCondition('z = 3');
+
+ $or1 = new OrCondition($cond1, $cond2);
+ $or2 = $or1->or($cond3);
+
+ $ast = $or2->toAst();
+
+ self::assertTrue($ast->hasBoolExpr());
+
+ $boolExpr = $ast->getBoolExpr();
+ self::assertNotNull($boolExpr);
+ self::assertSame(BoolExprType::OR_EXPR, $boolExpr->getBoolop());
+ self::assertCount(3, $boolExpr->getArgs());
+ }
+
+ public function test_or_method_returns_new_instance() : void
+ {
+ $cond1 = new RawCondition('x = 1');
+ $cond2 = new RawCondition('y = 2');
+
+ $original = new OrCondition($cond1);
+ $modified = $original->or($cond2);
+
+ self::assertNotSame($original, $modified);
+ }
+
+ 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');
+
+ $or1 = new OrCondition($cond1, $cond2);
+ $or2 = new OrCondition($cond3, $cond4);
+ $combined = $or1->or($or2);
+
+ $ast = $combined->toAst();
+
+ self::assertTrue($ast->hasBoolExpr());
+
+ $boolExpr = $ast->getBoolExpr();
+ self::assertNotNull($boolExpr);
+ self::assertCount(4, $boolExpr->getArgs());
+ }
+
+ public function test_or_with_single_condition() : void
+ {
+ $cond1 = new RawCondition('x = 1');
+ $cond2 = new RawCondition('y = 2');
+
+ $or = new OrCondition($cond1, $cond2);
+ $ast = $or->toAst();
+
+ self::assertTrue($ast->hasBoolExpr());
+
+ $boolExpr = $ast->getBoolExpr();
+ self::assertNotNull($boolExpr);
+ self::assertSame(BoolExprType::OR_EXPR, $boolExpr->getBoolop());
+ self::assertCount(2, $boolExpr->getArgs());
+ }
+
+ public function test_to_ast_creates_bool_expr() : void
+ {
+ $cond1 = new RawCondition('x = 1');
+ $cond2 = new RawCondition('y = 2');
+
+ $or = new OrCondition($cond1, $cond2);
+ $ast = $or->toAst();
+
+ self::assertInstanceOf(Node::class, $ast);
+ self::assertTrue($ast->hasBoolExpr());
+
+ $boolExpr = $ast->getBoolExpr();
+ self::assertNotNull($boolExpr);
+ self::assertSame(BoolExprType::OR_EXPR, $boolExpr->getBoolop());
+ }
+}
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
new file mode 100644
index 000000000..c163c8ffa
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/RawConditionTest.php
@@ -0,0 +1,138 @@
+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/Unit/QueryBuilder/Condition/SimilarToTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/SimilarToTest.php
new file mode 100644
index 000000000..2a4fd436f
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Condition/SimilarToTest.php
@@ -0,0 +1,83 @@
+and($condition2);
+
+ self::assertInstanceOf(AndCondition::class, $result);
+ }
+
+ public function test_converts_to_ast() : void
+ {
+ $condition = new SimilarTo(
+ Column::name('code'),
+ Literal::string('[0-9]{3}-[0-9]{3}')
+ );
+
+ $node = $condition->toAst();
+
+ self::assertTrue($node->hasAExpr());
+
+ $aExpr = $node->getAExpr();
+ self::assertNotNull($aExpr);
+ self::assertSame(A_Expr_Kind::AEXPR_SIMILAR, $aExpr->getKind());
+ self::assertTrue($aExpr->hasLexpr());
+ self::assertTrue($aExpr->hasRexpr());
+ }
+
+ public function test_creates_similar_to_condition() : void
+ {
+ $condition = new SimilarTo(
+ Column::name('code'),
+ Literal::string('[0-9]{3}-[0-9]{3}')
+ );
+
+ self::assertInstanceOf(SimilarTo::class, $condition);
+ }
+
+ public function test_not_method_returns_not_condition() : void
+ {
+ $condition = new SimilarTo(Column::name('code'), Literal::string('[0-9]{3}'));
+
+ $result = $condition->not();
+
+ self::assertInstanceOf(NotCondition::class, $result);
+ }
+
+ public function test_or_method_returns_or_condition() : void
+ {
+ $condition1 = new SimilarTo(Column::name('code'), Literal::string('[0-9]{3}'));
+ $condition2 = new SimilarTo(Column::name('phone'), Literal::string('[0-9]{10}'));
+
+ $result = $condition1->or($condition2);
+
+ self::assertInstanceOf(OrCondition::class, $result);
+ }
+
+ public function test_reconstructs_from_ast() : void
+ {
+ $original = new SimilarTo(
+ Column::name('code'),
+ Literal::string('[0-9]{3}-[0-9]{3}')
+ );
+
+ $node = $original->toAst();
+ $reconstructed = SimilarTo::fromAst($node);
+
+ self::assertInstanceOf(SimilarTo::class, $reconstructed);
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Copy/CopyFromBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Copy/CopyFromBuilderTest.php
new file mode 100644
index 000000000..16596812a
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Copy/CopyFromBuilderTest.php
@@ -0,0 +1,373 @@
+table('users')
+ ->file('/tmp/users.csv')
+ ->format(CopyFormat::CSV)
+ ->withHeader();
+
+ $ast = $query->toAst();
+ self::assertInstanceOf(CopyStmt::class, $ast);
+ }
+
+ public function test_copy_format_enum_values() : void
+ {
+ self::assertSame('binary', CopyFormat::BINARY->value);
+ self::assertSame('csv', CopyFormat::CSV->value);
+ self::assertSame('text', CopyFormat::TEXT->value);
+ }
+
+ public function test_copy_from_basic_table() : void
+ {
+ $query = CopyFromBuilder::create()
+ ->table('users')
+ ->file('/tmp/users.csv');
+
+ $ast = $query->toAst();
+
+ self::assertTrue($ast->getIsFrom());
+ self::assertFalse($ast->getIsProgram());
+ self::assertSame('/tmp/users.csv', $ast->getFilename());
+
+ $relation = $ast->getRelation();
+ self::assertNotNull($relation);
+ self::assertSame('users', $relation->getRelname());
+ }
+
+ public function test_copy_from_deparsed_basic_table() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = CopyFromBuilder::create()
+ ->table('users')
+ ->file('/tmp/users.csv');
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame("COPY users FROM '/tmp/users.csv'", $deparsed);
+ }
+
+ public function test_copy_from_deparsed_binary_format() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = CopyFromBuilder::create()
+ ->table('users')
+ ->file('/tmp/users.bin')
+ ->format(CopyFormat::BINARY);
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame("COPY users FROM '/tmp/users.bin' WITH (FORMAT BINARY)", $deparsed);
+ }
+
+ public function test_copy_from_deparsed_from_program() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = CopyFromBuilder::create()
+ ->table('users')
+ ->program('gunzip -c /tmp/users.csv.gz');
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame("COPY users FROM PROGRAM 'gunzip -c /tmp/users.csv.gz'", $deparsed);
+ }
+
+ public function test_copy_from_deparsed_from_stdin() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = CopyFromBuilder::create()
+ ->table('users')
+ ->stdin();
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame('COPY users FROM STDIN', $deparsed);
+ }
+
+ public function test_copy_from_deparsed_with_columns() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = CopyFromBuilder::create()
+ ->table('users', 'id', 'name', 'email')
+ ->file('/tmp/users.csv');
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame("COPY users(id, name, email) FROM '/tmp/users.csv'", $deparsed);
+ }
+
+ public function test_copy_from_deparsed_with_csv_format() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = CopyFromBuilder::create()
+ ->table('users')
+ ->file('/tmp/users.csv')
+ ->format(CopyFormat::CSV);
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame("COPY users FROM '/tmp/users.csv' CSV", $deparsed);
+ }
+
+ public function test_copy_from_deparsed_with_delimiter() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = CopyFromBuilder::create()
+ ->table('users')
+ ->file('/tmp/users.csv')
+ ->format(CopyFormat::CSV)
+ ->delimiter(';');
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame("COPY users FROM '/tmp/users.csv' WITH (FORMAT CSV, DELIMITER ';')", $deparsed);
+ }
+
+ public function test_copy_from_deparsed_with_encoding() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = CopyFromBuilder::create()
+ ->table('users')
+ ->file('/tmp/users.csv')
+ ->encoding('UTF8');
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame("COPY users FROM '/tmp/users.csv' WITH (ENCODING 'UTF8')", $deparsed);
+ }
+
+ public function test_copy_from_deparsed_with_escape() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = CopyFromBuilder::create()
+ ->table('users')
+ ->file('/tmp/users.csv')
+ ->format(CopyFormat::CSV)
+ ->escape('\\');
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame("COPY users FROM '/tmp/users.csv' WITH (FORMAT CSV, ESCAPE E'\\\\')", $deparsed);
+ }
+
+ public function test_copy_from_deparsed_with_force_not_null() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = CopyFromBuilder::create()
+ ->table('users')
+ ->file('/tmp/users.csv')
+ ->format(CopyFormat::CSV)
+ ->forceNotNull('name', 'email');
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame("COPY users FROM '/tmp/users.csv' WITH (FORMAT CSV, FORCE_NOT_NULL (name, email))", $deparsed);
+ }
+
+ public function test_copy_from_deparsed_with_force_null() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = CopyFromBuilder::create()
+ ->table('users')
+ ->file('/tmp/users.csv')
+ ->format(CopyFormat::CSV)
+ ->forceNull('name', 'email');
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame("COPY users FROM '/tmp/users.csv' WITH (FORMAT CSV, FORCE_NULL (name, email))", $deparsed);
+ }
+
+ public function test_copy_from_deparsed_with_header() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = CopyFromBuilder::create()
+ ->table('users')
+ ->file('/tmp/users.csv')
+ ->format(CopyFormat::CSV)
+ ->withHeader();
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame("COPY users FROM '/tmp/users.csv' WITH (FORMAT CSV, HEADER true)", $deparsed);
+ }
+
+ public function test_copy_from_deparsed_with_null_string() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = CopyFromBuilder::create()
+ ->table('users')
+ ->file('/tmp/users.csv')
+ ->nullAs('\\N');
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame("COPY users FROM '/tmp/users.csv' WITH (NULL E'\\\\N')", $deparsed);
+ }
+
+ public function test_copy_from_deparsed_with_on_error_ignore() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = CopyFromBuilder::create()
+ ->table('users')
+ ->file('/tmp/users.csv')
+ ->onError(CopyOnError::IGNORE);
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame("COPY users FROM '/tmp/users.csv' WITH (on_error ignore)", $deparsed);
+ }
+
+ public function test_copy_from_deparsed_with_quote() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = CopyFromBuilder::create()
+ ->table('users')
+ ->file('/tmp/users.csv')
+ ->format(CopyFormat::CSV)
+ ->quote("'");
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame("COPY users FROM '/tmp/users.csv' WITH (FORMAT CSV, QUOTE '''')", $deparsed);
+ }
+
+ public function test_copy_from_deparsed_with_schema() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = CopyFromBuilder::create()
+ ->table('myschema.users')
+ ->file('/tmp/users.csv');
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame("COPY myschema.users FROM '/tmp/users.csv'", $deparsed);
+ }
+
+ public function test_copy_from_parses_schema_and_table() : void
+ {
+ $query = CopyFromBuilder::create()
+ ->table('myschema.users')
+ ->file('/tmp/users.csv');
+
+ $ast = $query->toAst();
+
+ $relation = $ast->getRelation();
+ self::assertNotNull($relation);
+ self::assertSame('users', $relation->getRelname());
+ self::assertSame('myschema', $relation->getSchemaname());
+ }
+
+ public function test_copy_on_error_enum_values() : void
+ {
+ self::assertSame('ignore', CopyOnError::IGNORE->value);
+ self::assertSame('stop', CopyOnError::STOP->value);
+ }
+
+ public function test_immutability_options() : void
+ {
+ $original = CopyFromBuilder::create()->table('users')->file('/tmp/users.csv');
+ $modified = $original->format(CopyFormat::CSV);
+
+ self::assertNotSame($original, $modified);
+ }
+
+ public function test_immutability_source() : void
+ {
+ $original = CopyFromBuilder::create()->table('users');
+ $modified = $original->file('/tmp/users.csv');
+
+ self::assertNotSame($original, $modified);
+ }
+
+ public function test_immutability_table() : void
+ {
+ $original = CopyFromBuilder::create();
+ $modified = $original->table('users');
+
+ self::assertNotSame($original, $modified);
+ }
+
+ public function test_to_ast_without_source_throws_exception() : void
+ {
+ $this->expectException(InvalidExpressionException::class);
+
+ CopyFromBuilder::create()
+ ->table('users')
+ ->toAst();
+ }
+
+ public function test_to_ast_without_table_throws_exception() : void
+ {
+ $this->expectException(InvalidExpressionException::class);
+
+ CopyFromBuilder::create()
+ ->file('/tmp/users.csv')
+ ->toAst();
+ }
+
+ private function deparse(CopyStmt $copyStmt) : string
+ {
+ $parser = new Parser();
+ $node = new Node();
+ $node->setCopyStmt($copyStmt);
+ $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/Unit/QueryBuilder/Copy/CopyToBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Copy/CopyToBuilderTest.php
new file mode 100644
index 000000000..3d29c035f
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Copy/CopyToBuilderTest.php
@@ -0,0 +1,382 @@
+table('users')
+ ->file('/tmp/users.csv')
+ ->format(CopyFormat::CSV)
+ ->withHeader();
+
+ $ast = $query->toAst();
+ self::assertInstanceOf(CopyStmt::class, $ast);
+ }
+
+ public function test_copy_to_basic_table() : void
+ {
+ $query = CopyToBuilder::create()
+ ->table('users')
+ ->file('/tmp/users.csv');
+
+ $ast = $query->toAst();
+
+ self::assertFalse($ast->getIsFrom());
+ self::assertFalse($ast->getIsProgram());
+ self::assertSame('/tmp/users.csv', $ast->getFilename());
+
+ $relation = $ast->getRelation();
+ self::assertNotNull($relation);
+ self::assertSame('users', $relation->getRelname());
+ }
+
+ public function test_copy_to_deparsed_basic_table() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = CopyToBuilder::create()
+ ->table('users')
+ ->file('/tmp/users.csv');
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame("COPY users TO '/tmp/users.csv'", $deparsed);
+ }
+
+ public function test_copy_to_deparsed_binary_format() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = CopyToBuilder::create()
+ ->table('users')
+ ->file('/tmp/users.bin')
+ ->format(CopyFormat::BINARY);
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame("COPY users TO '/tmp/users.bin' WITH (FORMAT BINARY)", $deparsed);
+ }
+
+ public function test_copy_to_deparsed_from_query() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $selectQuery = SelectBuilder::create()
+ ->select(Column::name('id'), Column::name('name'))
+ ->from(new Table('users'));
+
+ $query = CopyToBuilder::create()
+ ->query($selectQuery)
+ ->file('/tmp/users.csv');
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame("COPY (SELECT id, name FROM users) TO '/tmp/users.csv'", $deparsed);
+ }
+
+ public function test_copy_to_deparsed_to_program() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = CopyToBuilder::create()
+ ->table('users')
+ ->program('gzip > /tmp/users.csv.gz');
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame("COPY users TO PROGRAM 'gzip > /tmp/users.csv.gz'", $deparsed);
+ }
+
+ public function test_copy_to_deparsed_to_stdout() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = CopyToBuilder::create()
+ ->table('users')
+ ->stdout();
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame('COPY users TO STDOUT', $deparsed);
+ }
+
+ public function test_copy_to_deparsed_with_columns() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = CopyToBuilder::create()
+ ->table('users', 'id', 'name', 'email')
+ ->file('/tmp/users.csv');
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame("COPY users(id, name, email) TO '/tmp/users.csv'", $deparsed);
+ }
+
+ public function test_copy_to_deparsed_with_csv_format() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = CopyToBuilder::create()
+ ->table('users')
+ ->file('/tmp/users.csv')
+ ->format(CopyFormat::CSV);
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame("COPY users TO '/tmp/users.csv' CSV", $deparsed);
+ }
+
+ public function test_copy_to_deparsed_with_delimiter() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = CopyToBuilder::create()
+ ->table('users')
+ ->file('/tmp/users.csv')
+ ->format(CopyFormat::CSV)
+ ->delimiter(';');
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame("COPY users TO '/tmp/users.csv' WITH (FORMAT CSV, DELIMITER ';')", $deparsed);
+ }
+
+ public function test_copy_to_deparsed_with_encoding() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = CopyToBuilder::create()
+ ->table('users')
+ ->file('/tmp/users.csv')
+ ->encoding('UTF8');
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame("COPY users TO '/tmp/users.csv' WITH (ENCODING 'UTF8')", $deparsed);
+ }
+
+ public function test_copy_to_deparsed_with_escape() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = CopyToBuilder::create()
+ ->table('users')
+ ->file('/tmp/users.csv')
+ ->format(CopyFormat::CSV)
+ ->escape('\\');
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame("COPY users TO '/tmp/users.csv' WITH (FORMAT CSV, ESCAPE E'\\\\')", $deparsed);
+ }
+
+ public function test_copy_to_deparsed_with_force_quote_all() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = CopyToBuilder::create()
+ ->table('users')
+ ->file('/tmp/users.csv')
+ ->format(CopyFormat::CSV)
+ ->forceQuoteAll();
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame("COPY users TO '/tmp/users.csv' WITH (FORMAT CSV, FORCE_QUOTE *)", $deparsed);
+ }
+
+ public function test_copy_to_deparsed_with_force_quote_columns() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = CopyToBuilder::create()
+ ->table('users')
+ ->file('/tmp/users.csv')
+ ->format(CopyFormat::CSV)
+ ->forceQuote('name', 'email');
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame("COPY users TO '/tmp/users.csv' CSV FORCE QUOTE name, email", $deparsed);
+ }
+
+ public function test_copy_to_deparsed_with_header() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = CopyToBuilder::create()
+ ->table('users')
+ ->file('/tmp/users.csv')
+ ->format(CopyFormat::CSV)
+ ->withHeader();
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame("COPY users TO '/tmp/users.csv' WITH (FORMAT CSV, HEADER true)", $deparsed);
+ }
+
+ public function test_copy_to_deparsed_with_null_string() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = CopyToBuilder::create()
+ ->table('users')
+ ->file('/tmp/users.csv')
+ ->nullAs('\\N');
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame("COPY users TO '/tmp/users.csv' WITH (NULL E'\\\\N')", $deparsed);
+ }
+
+ public function test_copy_to_deparsed_with_quote() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = CopyToBuilder::create()
+ ->table('users')
+ ->file('/tmp/users.csv')
+ ->format(CopyFormat::CSV)
+ ->quote("'");
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame("COPY users TO '/tmp/users.csv' WITH (FORMAT CSV, QUOTE '''')", $deparsed);
+ }
+
+ public function test_copy_to_deparsed_with_schema() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = CopyToBuilder::create()
+ ->table('myschema.users')
+ ->file('/tmp/users.csv');
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame("COPY myschema.users TO '/tmp/users.csv'", $deparsed);
+ }
+
+ public function test_copy_to_parses_schema_and_table() : void
+ {
+ $query = CopyToBuilder::create()
+ ->table('myschema.users')
+ ->file('/tmp/users.csv');
+
+ $ast = $query->toAst();
+
+ $relation = $ast->getRelation();
+ self::assertNotNull($relation);
+ self::assertSame('users', $relation->getRelname());
+ self::assertSame('myschema', $relation->getSchemaname());
+ }
+
+ public function test_copy_to_with_query_has_no_relation() : void
+ {
+ $selectQuery = SelectBuilder::create()
+ ->select(Column::name('id'))
+ ->from(new Table('users'));
+
+ $query = CopyToBuilder::create()
+ ->query($selectQuery)
+ ->file('/tmp/users.csv');
+
+ $ast = $query->toAst();
+
+ self::assertFalse($ast->hasRelation());
+ self::assertTrue($ast->hasQuery());
+ }
+
+ public function test_immutability_destination() : void
+ {
+ $original = CopyToBuilder::create()->table('users');
+ $modified = $original->file('/tmp/users.csv');
+
+ self::assertNotSame($original, $modified);
+ }
+
+ public function test_immutability_options() : void
+ {
+ $original = CopyToBuilder::create()->table('users')->file('/tmp/users.csv');
+ $modified = $original->format(CopyFormat::CSV);
+
+ self::assertNotSame($original, $modified);
+ }
+
+ public function test_immutability_table() : void
+ {
+ $original = CopyToBuilder::create();
+ $modified = $original->table('users');
+
+ self::assertNotSame($original, $modified);
+ }
+
+ public function test_to_ast_without_destination_throws_exception() : void
+ {
+ $this->expectException(InvalidExpressionException::class);
+
+ CopyToBuilder::create()
+ ->table('users')
+ ->toAst();
+ }
+
+ public function test_to_ast_without_table_or_query_throws_exception() : void
+ {
+ $this->expectException(InvalidExpressionException::class);
+
+ CopyToBuilder::create()
+ ->file('/tmp/users.csv')
+ ->toAst();
+ }
+
+ private function deparse(CopyStmt $copyStmt) : string
+ {
+ $parser = new Parser();
+ $node = new Node();
+ $node->setCopyStmt($copyStmt);
+ $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/Unit/QueryBuilder/Delete/DeleteBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Delete/DeleteBuilderTest.php
new file mode 100644
index 000000000..82cdfa3e2
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Delete/DeleteBuilderTest.php
@@ -0,0 +1,717 @@
+from('users', 'u')
+ ->where(new Comparison(Column::tableColumn('u', 'active'), ComparisonOperator::EQ, Literal::bool(false)))
+ ->returning(Column::name('id'));
+
+ $ast = $query->toAst();
+ self::assertInstanceOf(DeleteStmt::class, $ast);
+ }
+
+ public function test_delete_can_skip_optional_steps() : void
+ {
+ $queryWithoutWhere = DeleteBuilder::create()
+ ->from('temp_data')
+ ->returningAll();
+
+ $ast = $queryWithoutWhere->toAst();
+ self::assertInstanceOf(DeleteStmt::class, $ast);
+ self::assertFalse($ast->hasWhereClause());
+
+ $returningList = $ast->getReturningList();
+ self::assertCount(1, $returningList);
+ }
+
+ public function test_delete_complex_query() : void
+ {
+ $selectStmt = new SelectStmt();
+ $selectNode = new Node();
+ $selectNode->setSelectStmt($selectStmt);
+
+ $cte = new CTE('cancelled_orders', $selectNode);
+ $withClause = new WithClause([$cte]);
+
+ $query = DeleteBuilder::with($withClause)
+ ->from('order_items', 'oi')
+ ->using((new Table('cancelled_orders'))->as('co'))
+ ->where(
+ new Comparison(
+ Column::tableColumn('oi', 'order_id'),
+ ComparisonOperator::EQ,
+ Column::tableColumn('co', 'id')
+ )
+ )
+ ->returning(
+ Column::tableColumn('oi', 'id'),
+ Column::tableColumn('oi', 'product_id'),
+ Column::tableColumn('oi', 'quantity')
+ );
+
+ $ast = $query->toAst();
+ self::assertInstanceOf(DeleteStmt::class, $ast);
+ self::assertTrue($ast->hasWithClause());
+
+ $usingClause = $ast->getUsingClause();
+ self::assertNotNull($usingClause);
+ self::assertCount(1, $usingClause);
+
+ self::assertTrue($ast->hasWhereClause());
+
+ $returningList = $ast->getReturningList();
+ self::assertNotNull($returningList);
+ self::assertCount(3, $returningList);
+ }
+
+ public function test_delete_only_from_is_valid() : void
+ {
+ $query = DeleteBuilder::create()
+ ->from('all_data');
+
+ $ast = $query->toAst();
+ self::assertInstanceOf(DeleteStmt::class, $ast);
+
+ $relation = $ast->getRelation();
+ self::assertNotNull($relation);
+ self::assertSame('all_data', $relation->getRelname());
+ self::assertFalse($ast->hasWhereClause());
+ self::assertCount(0, $ast->getReturningList());
+ self::assertCount(0, $ast->getUsingClause());
+ }
+
+ public function test_delete_returning_all() : void
+ {
+ $query = DeleteBuilder::create()
+ ->from('temp_data')
+ ->returningAll();
+
+ $ast = $query->toAst();
+ self::assertInstanceOf(DeleteStmt::class, $ast);
+
+ $returningList = $ast->getReturningList();
+ self::assertNotNull($returningList);
+ self::assertCount(1, $returningList);
+
+ $firstReturn = $returningList[0]->getResTarget();
+ self::assertNotNull($firstReturn);
+
+ $val = $firstReturn->getVal();
+ self::assertNotNull($val);
+
+ // Star.toAst() produces a ColumnRef with A_Star inside
+ self::assertTrue($val->hasColumnRef());
+ $columnRef = $val->getColumnRef();
+ self::assertNotNull($columnRef);
+ $fields = $columnRef->getFields();
+ self::assertNotNull($fields);
+ self::assertCount(1, $fields);
+ self::assertTrue($fields[0]->hasAStar());
+ }
+
+ public function test_delete_with_alias() : void
+ {
+ $query = DeleteBuilder::create()
+ ->from('users', 'u');
+
+ $ast = $query->toAst();
+ self::assertInstanceOf(DeleteStmt::class, $ast);
+
+ $relation = $ast->getRelation();
+ self::assertNotNull($relation);
+ self::assertSame('users', $relation->getRelname());
+
+ $alias = $relation->getAlias();
+ self::assertNotNull($alias);
+ self::assertSame('u', $alias->getAliasname());
+ }
+
+ public function test_delete_with_alias_and_where() : void
+ {
+ $query = DeleteBuilder::create()
+ ->from('users', 'u')
+ ->where(new Comparison(Column::tableColumn('u', 'id'), ComparisonOperator::EQ, Literal::int(1)));
+
+ $ast = $query->toAst();
+ self::assertInstanceOf(DeleteStmt::class, $ast);
+
+ $relation = $ast->getRelation();
+ self::assertNotNull($relation);
+ self::assertSame('users', $relation->getRelname());
+
+ $alias = $relation->getAlias();
+ self::assertNotNull($alias);
+ self::assertSame('u', $alias->getAliasname());
+ self::assertTrue($ast->hasWhereClause());
+ }
+
+ public function test_delete_with_alias_and_where_deparsed_output() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $delete = DeleteBuilder::create()
+ ->from('users', 'u')
+ ->where(new Comparison(Column::tableColumn('u', 'active'), ComparisonOperator::EQ, Literal::bool(false)));
+
+ $deparsed = $this->deparse($delete->toAst());
+ self::assertSame('DELETE FROM users u WHERE u.active = false', $deparsed);
+ }
+
+ public function test_delete_with_multiple_using_tables() : void
+ {
+ $query = DeleteBuilder::create()
+ ->from('order_items', 'oi')
+ ->using(
+ (new Table('orders'))->as('o'),
+ (new Table('customers'))->as('c')
+ )
+ ->where(
+ (new Comparison(Column::tableColumn('oi', 'order_id'), ComparisonOperator::EQ, Column::tableColumn('o', 'id')))
+ ->and(new Comparison(Column::tableColumn('o', 'customer_id'), ComparisonOperator::EQ, Column::tableColumn('c', 'id')))
+ ->and(new Comparison(Column::tableColumn('c', 'status'), ComparisonOperator::EQ, Literal::string('inactive')))
+ );
+
+ $ast = $query->toAst();
+ self::assertInstanceOf(DeleteStmt::class, $ast);
+
+ $usingClause = $ast->getUsingClause();
+ self::assertNotNull($usingClause);
+ self::assertCount(2, $usingClause);
+
+ $firstTable = $usingClause[0]->getRangeVar();
+ self::assertNotNull($firstTable);
+ self::assertSame('orders', $firstTable->getRelname());
+
+ $firstAlias = $firstTable->getAlias();
+ self::assertNotNull($firstAlias);
+ self::assertSame('o', $firstAlias->getAliasname());
+
+ $secondTable = $usingClause[1]->getRangeVar();
+ self::assertNotNull($secondTable);
+ self::assertSame('customers', $secondTable->getRelname());
+
+ $secondAlias = $secondTable->getAlias();
+ self::assertNotNull($secondAlias);
+ self::assertSame('c', $secondAlias->getAliasname());
+ }
+
+ public function test_delete_with_multiple_using_tables_deparsed_output() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $delete = DeleteBuilder::create()
+ ->from('order_items', 'oi')
+ ->using(
+ (new Table('orders'))->as('o'),
+ (new Table('customers'))->as('c')
+ )
+ ->where(
+ (new Comparison(Column::tableColumn('oi', 'order_id'), ComparisonOperator::EQ, Column::tableColumn('o', 'id')))
+ ->and(new Comparison(Column::tableColumn('o', 'customer_id'), ComparisonOperator::EQ, Column::tableColumn('c', 'id')))
+ );
+
+ $deparsed = $this->deparse($delete->toAst());
+ 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_returning() : void
+ {
+ $query = DeleteBuilder::create()
+ ->from('sessions')
+ ->where(new Comparison(Column::name('expires_at'), ComparisonOperator::LT, new FunctionCall(['now'])))
+ ->returning(Column::name('id'), Column::name('user_id'));
+
+ $ast = $query->toAst();
+ self::assertInstanceOf(DeleteStmt::class, $ast);
+
+ $returningList = $ast->getReturningList();
+ self::assertNotNull($returningList);
+ self::assertCount(2, $returningList);
+
+ $firstReturn = $returningList[0]->getResTarget();
+ self::assertNotNull($firstReturn);
+
+ $firstVal = $firstReturn->getVal();
+ self::assertNotNull($firstVal);
+ self::assertTrue($firstVal->hasColumnRef());
+
+ $secondReturn = $returningList[1]->getResTarget();
+ self::assertNotNull($secondReturn);
+
+ $secondVal = $secondReturn->getVal();
+ self::assertNotNull($secondVal);
+ self::assertTrue($secondVal->hasColumnRef());
+ }
+
+ public function test_delete_with_returning_deparsed_output() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $delete = DeleteBuilder::create()
+ ->from('sessions')
+ ->where(new Comparison(Column::name('expired'), ComparisonOperator::EQ, Literal::bool(true)))
+ ->returning(Column::name('id'));
+
+ $deparsed = $this->deparse($delete->toAst());
+ self::assertSame('DELETE FROM sessions WHERE expired = true RETURNING id', $deparsed);
+ }
+
+ public function test_delete_with_using() : void
+ {
+ $query = DeleteBuilder::create()
+ ->from('order_items', 'oi')
+ ->using(new Table('orders'))
+ ->where(
+ (new Comparison(Column::tableColumn('oi', 'order_id'), ComparisonOperator::EQ, Column::tableColumn('orders', 'id')))
+ );
+
+ $ast = $query->toAst();
+ self::assertInstanceOf(DeleteStmt::class, $ast);
+
+ $relation = $ast->getRelation();
+ self::assertNotNull($relation);
+ self::assertSame('order_items', $relation->getRelname());
+
+ $alias = $relation->getAlias();
+ self::assertNotNull($alias);
+ self::assertSame('oi', $alias->getAliasname());
+
+ $usingClause = $ast->getUsingClause();
+ self::assertNotNull($usingClause);
+ self::assertCount(1, $usingClause);
+
+ $usingTable = $usingClause[0]->getRangeVar();
+ self::assertNotNull($usingTable);
+ self::assertSame('orders', $usingTable->getRelname());
+ }
+
+ public function test_delete_with_using_and_aliased_table() : void
+ {
+ $query = DeleteBuilder::create()
+ ->from('order_items', 'oi')
+ ->using((new Table('orders'))->as('o'))
+ ->where(
+ (new Comparison(Column::tableColumn('oi', 'order_id'), ComparisonOperator::EQ, Column::tableColumn('o', 'id')))
+ ->and(new Comparison(Column::tableColumn('o', 'status'), ComparisonOperator::EQ, Literal::string('cancelled')))
+ );
+
+ $ast = $query->toAst();
+ self::assertInstanceOf(DeleteStmt::class, $ast);
+
+ $usingClause = $ast->getUsingClause();
+ self::assertNotNull($usingClause);
+ self::assertCount(1, $usingClause);
+
+ $usingTable = $usingClause[0]->getRangeVar();
+ self::assertNotNull($usingTable);
+ self::assertSame('orders', $usingTable->getRelname());
+ self::assertNotNull($usingTable->getAlias());
+ self::assertSame('o', $usingTable->getAlias()->getAliasname());
+ }
+
+ public function test_delete_with_using_deparsed_output() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $delete = DeleteBuilder::create()
+ ->from('order_items', 'oi')
+ ->using((new Table('orders'))->as('o'))
+ ->where(
+ (new Comparison(Column::tableColumn('oi', 'order_id'), ComparisonOperator::EQ, Column::tableColumn('o', 'id')))
+ ->and(new Comparison(Column::tableColumn('o', 'status'), ComparisonOperator::EQ, Literal::string('cancelled')))
+ );
+
+ $deparsed = $this->deparse($delete->toAst());
+ self::assertSame("DELETE FROM order_items oi USING orders o WHERE oi.order_id = o.id AND o.status = 'cancelled'", $deparsed);
+ }
+
+ public function test_delete_with_where() : void
+ {
+ $query = DeleteBuilder::create()
+ ->from('users')
+ ->where(new Comparison(Column::name('active'), ComparisonOperator::EQ, Literal::bool(false)));
+
+ $ast = $query->toAst();
+ self::assertInstanceOf(DeleteStmt::class, $ast);
+ self::assertTrue($ast->hasWhereClause());
+ self::assertNotNull($ast->getWhereClause());
+ }
+
+ public function test_delete_with_where_deparsed_output() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $delete = DeleteBuilder::create()
+ ->from('users')
+ ->where(new Comparison(Column::name('id'), ComparisonOperator::EQ, Literal::int(1)));
+
+ $deparsed = $this->deparse($delete->toAst());
+ self::assertSame('DELETE FROM users WHERE id = 1', $deparsed);
+ }
+
+ public function test_delete_with_with_clause() : void
+ {
+ $selectStmt = new SelectStmt();
+ $selectNode = new Node();
+ $selectNode->setSelectStmt($selectStmt);
+
+ $cte = new CTE('inactive_users', $selectNode);
+ $withClause = new WithClause([$cte]);
+
+ $query = DeleteBuilder::with($withClause)
+ ->from('user_sessions', 'us')
+ ->where(
+ new Comparison(
+ Column::tableColumn('us', 'user_id'),
+ ComparisonOperator::EQ,
+ Column::tableColumn('inactive_users', 'id')
+ )
+ );
+
+ $ast = $query->toAst();
+ self::assertInstanceOf(DeleteStmt::class, $ast);
+ self::assertTrue($ast->hasWithClause());
+
+ $withClauseProto = $ast->getWithClause();
+ self::assertNotNull($withClauseProto);
+
+ $ctes = $withClauseProto->getCtes();
+ self::assertNotNull($ctes);
+ self::assertCount(1, $ctes);
+
+ $firstCte = $ctes[0]->getCommonTableExpr();
+ self::assertNotNull($firstCte);
+ self::assertSame('inactive_users', $firstCte->getCtename());
+ }
+
+ public function test_delete_without_where_returning_all() : void
+ {
+ $query = DeleteBuilder::create()
+ ->from('temp_logs')
+ ->returningAll();
+
+ $ast = $query->toAst();
+ self::assertInstanceOf(DeleteStmt::class, $ast);
+
+ $relation = $ast->getRelation();
+ self::assertNotNull($relation);
+ self::assertSame('temp_logs', $relation->getRelname());
+ self::assertFalse($ast->hasWhereClause());
+
+ $returningList = $ast->getReturningList();
+ self::assertNotNull($returningList);
+ self::assertCount(1, $returningList);
+ }
+
+ public function test_from_ast_empty_relname_throws_exception() : void
+ {
+ $this->expectException(\Flow\PostgreSql\QueryBuilder\Exception\InvalidAstException::class);
+ $this->expectExceptionMessage('Missing required field "relname" in RangeVar node');
+
+ $deleteStmt = new DeleteStmt();
+ $deleteStmt->setRelation(new \Flow\PostgreSql\Protobuf\AST\RangeVar([
+ 'relname' => '',
+ ]));
+
+ $node = new Node();
+ $node->setDeleteStmt($deleteStmt);
+ DeleteBuilder::fromAst($node);
+ }
+
+ public function test_from_ast_missing_relation_throws_exception() : void
+ {
+ $this->expectException(\Flow\PostgreSql\QueryBuilder\Exception\InvalidAstException::class);
+ $this->expectExceptionMessage('Missing required field "relation" in DeleteStmt node');
+
+ $deleteStmt = new DeleteStmt();
+ $node = new Node();
+ $node->setDeleteStmt($deleteStmt);
+ DeleteBuilder::fromAst($node);
+ }
+
+ public function test_immutability_from() : void
+ {
+ $original = DeleteBuilder::create();
+ $modified = $original->from('users');
+
+ self::assertNotSame($original, $modified);
+ }
+
+ public function test_immutability_returning() : void
+ {
+ $original = DeleteBuilder::create()->from('users');
+ $modified = $original->returning(Column::name('id'));
+
+ self::assertNotSame($original, $modified);
+ }
+
+ public function test_immutability_returning_all() : void
+ {
+ $original = DeleteBuilder::create()->from('users');
+ $modified = $original->returningAll();
+
+ self::assertNotSame($original, $modified);
+ }
+
+ public function test_immutability_using() : void
+ {
+ $original = DeleteBuilder::create()->from('users');
+ $modified = $original->using(new Table('orders'));
+
+ self::assertNotSame($original, $modified);
+ }
+
+ public function test_immutability_where() : void
+ {
+ $original = DeleteBuilder::create()->from('users');
+ $modified = $original->where(new Comparison(Column::name('id'), ComparisonOperator::EQ, Literal::int(1)));
+
+ self::assertNotSame($original, $modified);
+ }
+
+ public function test_round_trip_complex() : void
+ {
+ $selectStmt = new SelectStmt();
+ $selectNode = new Node();
+ $selectNode->setSelectStmt($selectStmt);
+
+ $cte = new CTE('cancelled_orders', $selectNode);
+ $withClause = new WithClause([$cte]);
+
+ $original = DeleteBuilder::with($withClause)
+ ->from('order_items', 'oi')
+ ->using((new Table('cancelled_orders'))->as('co'))
+ ->where(
+ new Comparison(
+ Column::tableColumn('oi', 'order_id'),
+ ComparisonOperator::EQ,
+ Column::tableColumn('co', 'id')
+ )
+ )
+ ->returning(Column::name('id'), Column::name('product_id'));
+
+ $ast = $original->toAst();
+ $node = new Node();
+ $node->setDeleteStmt($ast);
+ $restored = DeleteBuilder::fromAst($node);
+
+ $restoredAst = $restored->toAst();
+
+ self::assertTrue($restoredAst->hasWithClause());
+
+ $withClauseProto = $restoredAst->getWithClause();
+ self::assertNotNull($withClauseProto);
+
+ $ctes = $withClauseProto->getCtes();
+ self::assertNotNull($ctes);
+ self::assertCount(1, $ctes);
+
+ $usingClause = $restoredAst->getUsingClause();
+ self::assertCount(1, $usingClause);
+
+ $returningList = $restoredAst->getReturningList();
+ self::assertCount(2, $returningList);
+ }
+
+ public function test_round_trip_simple() : void
+ {
+ $original = DeleteBuilder::create()
+ ->from('users');
+
+ $ast = $original->toAst();
+ $node = new Node();
+ $node->setDeleteStmt($ast);
+ $restored = DeleteBuilder::fromAst($node);
+
+ $restoredAst = $restored->toAst();
+
+ $originalRelation = $ast->getRelation();
+ self::assertNotNull($originalRelation);
+
+ $restoredRelation = $restoredAst->getRelation();
+ self::assertNotNull($restoredRelation);
+
+ self::assertSame($originalRelation->getRelname(), $restoredRelation->getRelname());
+ self::assertSame($ast->hasWhereClause(), $restoredAst->hasWhereClause());
+ }
+
+ public function test_round_trip_with_alias() : void
+ {
+ $original = DeleteBuilder::create()
+ ->from('users', 'u');
+
+ $ast = $original->toAst();
+ $node = new Node();
+ $node->setDeleteStmt($ast);
+ $restored = DeleteBuilder::fromAst($node);
+
+ $restoredAst = $restored->toAst();
+
+ $originalRelation = $ast->getRelation();
+ self::assertNotNull($originalRelation);
+
+ $restoredRelation = $restoredAst->getRelation();
+ self::assertNotNull($restoredRelation);
+
+ self::assertSame($originalRelation->getRelname(), $restoredRelation->getRelname());
+
+ $originalAlias = $originalRelation->getAlias();
+ self::assertNotNull($originalAlias);
+
+ $restoredAlias = $restoredRelation->getAlias();
+ self::assertNotNull($restoredAlias);
+
+ self::assertSame($originalAlias->getAliasname(), $restoredAlias->getAliasname());
+ }
+
+ public function test_round_trip_with_returning() : void
+ {
+ $original = DeleteBuilder::create()
+ ->from('users', 'u')
+ ->where(new Comparison(Column::tableColumn('u', 'id'), ComparisonOperator::EQ, Literal::int(1)))
+ ->returning(Column::name('id'));
+
+ $ast = $original->toAst();
+ $node = new Node();
+ $node->setDeleteStmt($ast);
+ $restored = DeleteBuilder::fromAst($node);
+
+ $restoredAst = $restored->toAst();
+ self::assertTrue($restoredAst->hasWhereClause());
+
+ $returningList = $restoredAst->getReturningList();
+ self::assertNotNull($returningList);
+ self::assertCount(1, $returningList);
+ }
+
+ public function test_round_trip_with_using() : void
+ {
+ $original = DeleteBuilder::create()
+ ->from('order_items', 'oi')
+ ->using((new Table('orders'))->as('o'))
+ ->where(
+ new Comparison(
+ Column::tableColumn('oi', 'order_id'),
+ ComparisonOperator::EQ,
+ Column::tableColumn('o', 'id')
+ )
+ );
+
+ $ast = $original->toAst();
+ $node = new Node();
+ $node->setDeleteStmt($ast);
+ $restored = DeleteBuilder::fromAst($node);
+
+ $restoredAst = $restored->toAst();
+
+ $usingClause = $restoredAst->getUsingClause();
+ self::assertNotNull($usingClause);
+ self::assertCount(1, $usingClause);
+
+ $usingTable = $usingClause[0]->getRangeVar();
+ self::assertNotNull($usingTable);
+ self::assertSame('orders', $usingTable->getRelname());
+
+ $usingAlias = $usingTable->getAlias();
+ self::assertNotNull($usingAlias);
+ self::assertSame('o', $usingAlias->getAliasname());
+ }
+
+ public function test_round_trip_with_where() : void
+ {
+ $original = DeleteBuilder::create()
+ ->from('users', 'u')
+ ->where(new Comparison(Column::tableColumn('u', 'id'), ComparisonOperator::EQ, Literal::int(1)));
+
+ $ast = $original->toAst();
+ $node = new Node();
+ $node->setDeleteStmt($ast);
+ $restored = DeleteBuilder::fromAst($node);
+
+ $restoredAst = $restored->toAst();
+ self::assertTrue($restoredAst->hasWhereClause());
+ self::assertNotNull($restoredAst->getWhereClause());
+ }
+
+ public function test_simple_delete() : void
+ {
+ $query = DeleteBuilder::create()
+ ->from('users');
+
+ $ast = $query->toAst();
+ self::assertInstanceOf(DeleteStmt::class, $ast);
+
+ $relation = $ast->getRelation();
+ self::assertNotNull($relation);
+ self::assertSame('users', $relation->getRelname());
+ self::assertNull($relation->getAlias());
+ }
+
+ public function test_simple_delete_deparsed_output() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $delete = DeleteBuilder::create()
+ ->from('users');
+
+ $deparsed = $this->deparse($delete->toAst());
+ self::assertSame('DELETE FROM users', $deparsed);
+ }
+
+ public function test_to_ast_without_table_throws_exception() : void
+ {
+ $this->expectException(\LogicException::class);
+ $this->expectExceptionMessage('Cannot create DeleteStmt without table name. Call from() first.');
+
+ $builder = DeleteBuilder::create();
+ \assert($builder instanceof DeleteFinalStep);
+ $builder->toAst();
+ }
+
+ private function deparse(DeleteStmt $deleteStmt) : string
+ {
+ $parser = new Parser();
+ $node = new Node(['delete_stmt' => $deleteStmt]);
+ $rawStmt = new RawStmt(['stmt' => $node]);
+ $parsed = $parser->parse('DELETE FROM dummy');
+ $parseResult = $parsed->raw();
+ $parseResult->setStmts([$rawStmt]);
+
+ return (new ParsedQuery($parseResult))->deparse();
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/AggregateCallTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/AggregateCallTest.php
new file mode 100644
index 000000000..1f12d8265
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/AggregateCallTest.php
@@ -0,0 +1,311 @@
+select($agg)
+ ->from(new Table('users'));
+
+ $parser = new Parser();
+ $ast = $select->toAst();
+ $node = new Node(['select_stmt' => $ast]);
+ $rawStmt = new RawStmt(['stmt' => $node]);
+ $parsed = $parser->parse('SELECT 1');
+ $parseResult = $parsed->raw();
+ $parseResult->setStmts([$rawStmt]);
+
+ $deparsed = (new \Flow\PostgreSql\ParsedQuery($parseResult))->deparse();
+
+ self::assertSame('SELECT count(*) FROM users', $deparsed);
+ }
+
+ public function test_aggregate_sum_deparsed_output() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $agg = new AggregateCall(['sum'], [Column::name('amount')], false, false);
+
+ $select = SelectBuilder::create()
+ ->select($agg)
+ ->from(new Table('orders'));
+
+ $parser = new Parser();
+ $ast = $select->toAst();
+ $node = new Node(['select_stmt' => $ast]);
+ $rawStmt = new RawStmt(['stmt' => $node]);
+ $parsed = $parser->parse('SELECT 1');
+ $parseResult = $parsed->raw();
+ $parseResult->setStmts([$rawStmt]);
+
+ $deparsed = (new \Flow\PostgreSql\ParsedQuery($parseResult))->deparse();
+
+ self::assertSame('SELECT sum(amount) FROM orders', $deparsed);
+ }
+
+ public function test_aggregate_with_distinct_deparsed_output() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $agg = new AggregateCall(['count'], [Column::name('user_id')], false, true);
+
+ $select = SelectBuilder::create()
+ ->select($agg)
+ ->from(new Table('sessions'));
+
+ $parser = new Parser();
+ $ast = $select->toAst();
+ $node = new Node(['select_stmt' => $ast]);
+ $rawStmt = new RawStmt(['stmt' => $node]);
+ $parsed = $parser->parse('SELECT 1');
+ $parseResult = $parsed->raw();
+ $parseResult->setStmts([$rawStmt]);
+
+ $deparsed = (new \Flow\PostgreSql\ParsedQuery($parseResult))->deparse();
+
+ self::assertSame('SELECT count(DISTINCT user_id) FROM sessions', $deparsed);
+ }
+
+ public function test_converts_aggregate_with_filter_to_ast() : void
+ {
+ $arg = Column::name('amount');
+ $filter = Literal::bool(true);
+ $agg = new AggregateCall(['sum'], [$arg], false, false, [], $filter);
+
+ $node = $agg->toAst();
+ $funcCall = $node->getFuncCall();
+
+ self::assertNotNull($funcCall);
+ self::assertNotNull($funcCall->getAggFilter());
+ }
+
+ public function test_converts_aggregate_with_order_by_to_ast() : void
+ {
+ $arg = Column::name('value');
+ $orderBy = new OrderBy(Column::name('sort_col'));
+ $agg = new AggregateCall(['array_agg'], [$arg], false, false, [$orderBy]);
+
+ $node = $agg->toAst();
+ $funcCall = $node->getFuncCall();
+
+ self::assertNotNull($funcCall);
+ $orderByNodes = $funcCall->getAggOrder();
+ self::assertNotNull($orderByNodes);
+ self::assertCount(1, $orderByNodes);
+ }
+
+ public function test_converts_count_star_to_ast() : void
+ {
+ $agg = new AggregateCall(['count'], [], true);
+
+ $node = $agg->toAst();
+ $funcCall = $node->getFuncCall();
+
+ self::assertNotNull($funcCall);
+ self::assertTrue($funcCall->getAggStar());
+ self::assertFalse($funcCall->getAggDistinct());
+ }
+
+ public function test_converts_distinct_aggregate_to_ast() : void
+ {
+ $arg = Column::name('value');
+ $agg = new AggregateCall(['count'], [$arg], false, true);
+
+ $node = $agg->toAst();
+ $funcCall = $node->getFuncCall();
+
+ self::assertNotNull($funcCall);
+ self::assertTrue($funcCall->getAggDistinct());
+ self::assertFalse($funcCall->getAggStar());
+ }
+
+ public function test_creates_aggregate_with_distinct() : void
+ {
+ $arg = Column::name('value');
+ $agg = new AggregateCall(['count'], [$arg], false, true);
+
+ self::assertTrue($agg->isDistinct());
+ }
+
+ public function test_creates_aggregate_with_filter() : void
+ {
+ $arg = Column::name('amount');
+ $filter = Column::name('status');
+ $agg = new AggregateCall(['sum'], [$arg], false, false, [], $filter);
+
+ self::assertNotNull($agg->getFilter());
+ }
+
+ public function test_creates_aggregate_with_order_by() : void
+ {
+ $arg = Column::name('value');
+ $orderBy = new OrderBy(Column::name('sort_col'), SortDirection::DESC);
+ $agg = new AggregateCall(['array_agg'], [$arg], false, false, [$orderBy]);
+
+ self::assertCount(1, $agg->getOrderBy());
+ }
+
+ public function test_creates_aliased_expression() : void
+ {
+ $agg = new AggregateCall(['count'], [], true);
+ $aliased = $agg->as('total');
+
+ self::assertSame('total', $aliased->getAlias());
+ self::assertSame($agg, $aliased->getExpression());
+ }
+
+ public function test_creates_count_star_aggregate() : void
+ {
+ $agg = new AggregateCall(['count'], [], true);
+
+ self::assertSame(['count'], $agg->getFuncName());
+ self::assertTrue($agg->isStar());
+ self::assertSame([], $agg->getArgs());
+ }
+
+ public function test_creates_sum_aggregate() : void
+ {
+ $arg = Column::name('amount');
+ $agg = new AggregateCall(['sum'], [$arg]);
+
+ self::assertSame(['sum'], $agg->getFuncName());
+ self::assertFalse($agg->isStar());
+ self::assertCount(1, $agg->getArgs());
+ }
+
+ public function test_recreates_count_star_from_ast() : void
+ {
+ $stringNode = new PBString();
+ $stringNode->setSval('count');
+
+ $nameNode = new Node();
+ $nameNode->setString($stringNode);
+
+ $funcCall = new FuncCall();
+ $funcCall->setFuncname([$nameNode]);
+ $funcCall->setAggStar(true);
+
+ $node = new Node();
+ $node->setFuncCall($funcCall);
+
+ $agg = AggregateCall::fromAst($node);
+
+ self::assertSame(['count'], $agg->getFuncName());
+ self::assertTrue($agg->isStar());
+ }
+
+ public function test_recreates_distinct_aggregate_from_ast() : void
+ {
+ $stringNode = new PBString();
+ $stringNode->setSval('count');
+
+ $nameNode = new Node();
+ $nameNode->setString($stringNode);
+
+ $funcCall = new FuncCall();
+ $funcCall->setFuncname([$nameNode]);
+ $funcCall->setAggDistinct(true);
+ $funcCall->setArgs([Literal::int(1)->toAst()]);
+
+ $node = new Node();
+ $node->setFuncCall($funcCall);
+
+ $agg = AggregateCall::fromAst($node);
+
+ self::assertTrue($agg->isDistinct());
+ }
+
+ public function test_round_trip_conversion_with_all_features() : void
+ {
+ $arg = Column::name('value');
+ $orderBy = new OrderBy(Column::name('sort_col'), SortDirection::DESC, NullsPosition::LAST);
+ $filter = Literal::bool(true);
+ $agg = new AggregateCall(['pg_catalog', 'array_agg'], [$arg], false, true, [$orderBy], $filter);
+
+ $node = $agg->toAst();
+ $restored = AggregateCall::fromAst($node);
+
+ self::assertSame($agg->getFuncName(), $restored->getFuncName());
+ self::assertTrue($restored->isDistinct());
+ self::assertCount(1, $restored->getOrderBy());
+ self::assertNotNull($restored->getFilter());
+ }
+
+ public function test_throws_exception_for_empty_function_name() : void
+ {
+ $this->expectException(InvalidExpressionException::class);
+
+ /** @phpstan-ignore argument.type (intentionally testing exception) */
+ new AggregateCall([], []);
+ }
+
+ public function test_throws_exception_for_star_with_arguments() : void
+ {
+ $this->expectException(InvalidExpressionException::class);
+
+ $arg = Literal::int(1);
+ new AggregateCall(['count'], [$arg], true);
+ }
+
+ public function test_with_distinct_creates_new_instance() : void
+ {
+ $arg = Column::name('value');
+ $agg = new AggregateCall(['count'], [$arg], false, false);
+
+ $newAgg = $agg->withDistinct();
+
+ self::assertNotSame($agg, $newAgg);
+ self::assertFalse($agg->isDistinct());
+ self::assertTrue($newAgg->isDistinct());
+ }
+
+ public function test_with_filter_creates_new_instance() : void
+ {
+ $arg = Column::name('value');
+ $agg = new AggregateCall(['count'], [$arg]);
+
+ $filter = Literal::bool(true);
+ $newAgg = $agg->withFilter($filter);
+
+ self::assertNotSame($agg, $newAgg);
+ self::assertNull($agg->getFilter());
+ self::assertNotNull($newAgg->getFilter());
+ }
+
+ public function test_with_order_by_creates_new_instance() : void
+ {
+ $arg = Column::name('value');
+ $agg = new AggregateCall(['array_agg'], [$arg]);
+
+ $orderBy = new OrderBy(Column::name('sort_col'));
+ $newAgg = $agg->withOrderBy($orderBy);
+
+ self::assertNotSame($agg, $newAgg);
+ self::assertSame([], $agg->getOrderBy());
+ self::assertCount(1, $newAgg->getOrderBy());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/AliasedExpressionTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/AliasedExpressionTest.php
new file mode 100644
index 000000000..ab56b5fa8
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/AliasedExpressionTest.php
@@ -0,0 +1,168 @@
+select($aliased)
+ ->from(new Table('users'));
+
+ $parser = new Parser();
+ $ast = $select->toAst();
+ $node = new Node(['select_stmt' => $ast]);
+ $rawStmt = new RawStmt(['stmt' => $node]);
+ $parsed = $parser->parse('SELECT 1');
+ $parseResult = $parsed->raw();
+ $parseResult->setStmts([$rawStmt]);
+
+ $deparsed = (new \Flow\PostgreSql\ParsedQuery($parseResult))->deparse();
+
+ self::assertSame('SELECT user_id AS id FROM users', $deparsed);
+ }
+
+ public function test_changes_alias() : void
+ {
+ $column = Column::name('users');
+ $aliased = AliasedExpression::create($column, 'u');
+ $newAliased = $aliased->as('user_table');
+
+ self::assertSame('user_table', $newAliased->getAlias());
+ self::assertSame($column, $newAliased->getExpression());
+ }
+
+ public function test_converts_to_ast() : void
+ {
+ $column = Column::name('users');
+ $aliased = AliasedExpression::create($column, 'u');
+ $node = $aliased->toAst();
+
+ $resTarget = $node->getResTarget();
+ self::assertNotNull($resTarget);
+ self::assertSame('u', $resTarget->getName());
+
+ $val = $resTarget->getVal();
+ self::assertNotNull($val);
+ self::assertNotNull($val->getColumnRef());
+ }
+
+ public function test_creates_aliased_column() : void
+ {
+ $column = Column::name('users');
+ $aliased = AliasedExpression::create($column, 'u');
+
+ self::assertSame($column, $aliased->getExpression());
+ self::assertSame('u', $aliased->getAlias());
+ }
+
+ public function test_creates_aliased_literal() : void
+ {
+ $literal = Literal::int(42);
+ $aliased = AliasedExpression::create($literal, 'answer');
+
+ self::assertSame($literal, $aliased->getExpression());
+ self::assertSame('answer', $aliased->getAlias());
+ }
+
+ public function test_rejects_empty_alias() : void
+ {
+ $this->expectException(InvalidExpressionException::class);
+
+ AliasedExpression::create(Column::name('test'), '');
+ }
+
+ public function test_roundtrip_column_conversion() : void
+ {
+ $column = Column::tableColumn('users', 'name');
+ $original = AliasedExpression::create($column, 'user_name');
+ $node = $original->toAst();
+ $reconstructed = AliasedExpression::fromAst($node);
+
+ self::assertSame($original->getAlias(), $reconstructed->getAlias());
+
+ $reconstructedColumn = $reconstructed->getExpression();
+ self::assertInstanceOf(Column::class, $reconstructedColumn);
+ self::assertEquals($column->parts(), $reconstructedColumn->parts());
+ }
+
+ public function test_roundtrip_literal_conversion() : void
+ {
+ $literal = Literal::string('hello');
+ $original = AliasedExpression::create($literal, 'greeting');
+ $node = $original->toAst();
+ $reconstructed = AliasedExpression::fromAst($node);
+
+ self::assertSame($original->getAlias(), $reconstructed->getAlias());
+
+ $reconstructedLiteral = $reconstructed->getExpression();
+ self::assertInstanceOf(Literal::class, $reconstructedLiteral);
+ self::assertEquals($literal->value(), $reconstructedLiteral->value());
+ }
+
+ public function test_roundtrip_parameter_conversion() : void
+ {
+ $param = Parameter::positional(1);
+ $original = AliasedExpression::create($param, 'p1');
+ $node = $original->toAst();
+ $reconstructed = AliasedExpression::fromAst($node);
+
+ self::assertSame($original->getAlias(), $reconstructed->getAlias());
+
+ $reconstructedParam = $reconstructed->getExpression();
+ self::assertInstanceOf(Parameter::class, $reconstructedParam);
+ self::assertEquals($param->number(), $reconstructedParam->number());
+ }
+
+ public function test_roundtrip_star_conversion() : void
+ {
+ $star = Star::fromTable('users');
+ $original = AliasedExpression::create($star, 'all_users');
+ $node = $original->toAst();
+ $reconstructed = AliasedExpression::fromAst($node);
+
+ self::assertSame($original->getAlias(), $reconstructed->getAlias());
+
+ $reconstructedStar = $reconstructed->getExpression();
+ self::assertInstanceOf(Star::class, $reconstructedStar);
+ self::assertEquals($star->table(), $reconstructedStar->table());
+ }
+
+ public function test_with_alias() : void
+ {
+ $column = Column::name('users');
+ $aliased = AliasedExpression::create($column, 'u');
+ $newAliased = $aliased->withAlias('user_table');
+
+ self::assertSame('user_table', $newAliased->getAlias());
+ self::assertSame($column, $newAliased->getExpression());
+ }
+
+ public function test_with_expression() : void
+ {
+ $column = Column::name('users');
+ $literal = Literal::int(42);
+ $aliased = AliasedExpression::create($column, 'test');
+ $newAliased = $aliased->withExpression($literal);
+
+ self::assertSame('test', $newAliased->getAlias());
+ self::assertSame($literal, $newAliased->getExpression());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/ArrayExpressionTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/ArrayExpressionTest.php
new file mode 100644
index 000000000..f65ffa4a3
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/ArrayExpressionTest.php
@@ -0,0 +1,114 @@
+as('my_array');
+
+ self::assertInstanceOf(AliasedExpression::class, $aliased);
+ }
+
+ public function test_elements_getter() : void
+ {
+ $elem1 = new MockExpression('value1');
+ $elem2 = new MockExpression('value2');
+ $elem3 = new MockExpression('value3');
+
+ $array = new ArrayExpression([$elem1, $elem2, $elem3]);
+
+ $elements = $array->elements();
+
+ self::assertCount(3, $elements);
+ self::assertSame($elem1, $elements[0]);
+ self::assertSame($elem2, $elements[1]);
+ self::assertSame($elem3, $elements[2]);
+ }
+
+ public function test_empty_array_expression() : void
+ {
+ $expr = new ArrayExpression([]);
+
+ $ast = $expr->toAst();
+
+ self::assertInstanceOf(Node::class, $ast);
+ self::assertTrue($ast->hasAArrayExpr());
+
+ $arrayExpr = $ast->getAArrayExpr();
+ self::assertNotNull($arrayExpr);
+ self::assertCount(0, $arrayExpr->getElements());
+ }
+
+ public function test_from_ast_throws_on_non_array_expr() : void
+ {
+ $this->expectException(InvalidAstException::class);
+ $this->expectExceptionMessage('Expected A_ArrayExpr node, got unknown');
+
+ $node = new Node();
+ ArrayExpression::fromAst($node);
+ }
+
+ public function test_from_ast_with_empty_elements() : void
+ {
+ $arrayExpr = new A_ArrayExpr();
+ $arrayExpr->setElements([]);
+
+ $node = new Node();
+ $node->setAArrayExpr($arrayExpr);
+
+ $result = ArrayExpression::fromAst($node);
+
+ self::assertCount(0, $result->elements());
+ }
+
+ public function test_to_ast_creates_array_expr() : void
+ {
+ $expr = new ArrayExpression([
+ new MockExpression('first'),
+ new MockExpression('second'),
+ new MockExpression('third'),
+ ]);
+
+ $ast = $expr->toAst();
+
+ self::assertInstanceOf(Node::class, $ast);
+ self::assertTrue($ast->hasAArrayExpr());
+
+ $arrayExpr = $ast->getAArrayExpr();
+ self::assertNotNull($arrayExpr);
+ $elements = $arrayExpr->getElements();
+
+ self::assertCount(3, $elements);
+ }
+
+ public function test_with_single_element() : void
+ {
+ $expr = new ArrayExpression([new MockExpression('single')]);
+
+ $ast = $expr->toAst();
+
+ self::assertTrue($ast->hasAArrayExpr());
+
+ $arrayExpr = $ast->getAArrayExpr();
+ self::assertNotNull($arrayExpr);
+ self::assertCount(1, $arrayExpr->getElements());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/BinaryExpressionTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/BinaryExpressionTest.php
new file mode 100644
index 000000000..f9bcc974d
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/BinaryExpressionTest.php
@@ -0,0 +1,190 @@
+as('sum');
+
+ self::assertInstanceOf(AliasedExpression::class, $aliased);
+ }
+
+ public function test_binary_expression_deparsed_output() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $expr = new BinaryExpression(
+ Column::name('price'),
+ '*',
+ Literal::float(1.1)
+ );
+
+ $select = SelectBuilder::create()
+ ->select($expr)
+ ->from(new Table('products'));
+
+ $parser = new Parser();
+ $ast = $select->toAst();
+ $node = new Node(['select_stmt' => $ast]);
+ $rawStmt = new RawStmt(['stmt' => $node]);
+ $parsed = $parser->parse('SELECT 1');
+ $parseResult = $parsed->raw();
+ $parseResult->setStmts([$rawStmt]);
+
+ $deparsed = (new \Flow\PostgreSql\ParsedQuery($parseResult))->deparse();
+
+ self::assertSame('SELECT price * 1.1 FROM products', $deparsed);
+ }
+
+ public function test_from_ast_throws_on_non_a_expr() : void
+ {
+ $this->expectException(InvalidAstException::class);
+ $this->expectExceptionMessage('Expected A_Expr node, got unknown');
+
+ $node = new Node();
+ BinaryExpression::fromAst($node);
+ }
+
+ public function test_from_ast_throws_on_wrong_kind() : void
+ {
+ $this->expectException(InvalidAstException::class);
+ $this->expectExceptionMessage('must be AEXPR_OP for binary expression');
+
+ $aExpr = new A_Expr();
+ $aExpr->setKind(A_Expr_Kind::AEXPR_DISTINCT);
+
+ $node = new Node();
+ $node->setAExpr($aExpr);
+
+ BinaryExpression::fromAst($node);
+ }
+
+ public function test_from_ast_throws_when_lexpr_missing() : void
+ {
+ $this->expectException(InvalidAstException::class);
+ $this->expectExceptionMessage('Missing required field "lexpr"');
+
+ $operatorNode = new Node();
+ $operatorString = new PBString();
+ $operatorString->setSval('+');
+ $operatorNode->setString($operatorString);
+
+ $aExpr = new A_Expr();
+ $aExpr->setKind(A_Expr_Kind::AEXPR_OP);
+ $aExpr->setName([$operatorNode]);
+ $aExpr->setRexpr(new Node());
+
+ $node = new Node();
+ $node->setAExpr($aExpr);
+
+ BinaryExpression::fromAst($node);
+ }
+
+ public function test_from_ast_throws_when_name_missing() : void
+ {
+ $this->expectException(InvalidAstException::class);
+ $this->expectExceptionMessage('Missing required field "name"');
+
+ $aExpr = new A_Expr();
+ $aExpr->setKind(A_Expr_Kind::AEXPR_OP);
+ $aExpr->setLexpr(new Node());
+ $aExpr->setRexpr(new Node());
+
+ $node = new Node();
+ $node->setAExpr($aExpr);
+
+ BinaryExpression::fromAst($node);
+ }
+
+ public function test_from_ast_throws_when_rexpr_missing() : void
+ {
+ $this->expectException(InvalidAstException::class);
+ $this->expectExceptionMessage('Missing required field "rexpr"');
+
+ $operatorNode = new Node();
+ $operatorString = new PBString();
+ $operatorString->setSval('+');
+ $operatorNode->setString($operatorString);
+
+ $aExpr = new A_Expr();
+ $aExpr->setKind(A_Expr_Kind::AEXPR_OP);
+ $aExpr->setName([$operatorNode]);
+ $aExpr->setLexpr(new Node());
+
+ $node = new Node();
+ $node->setAExpr($aExpr);
+
+ BinaryExpression::fromAst($node);
+ }
+
+ public function test_getters() : void
+ {
+ $left = new MockExpression();
+ $right = new MockExpression();
+
+ $expr = new BinaryExpression($left, '+', $right);
+
+ self::assertSame($left, $expr->left());
+ self::assertSame('+', $expr->operator());
+ self::assertSame($right, $expr->right());
+ }
+
+ public function test_to_ast_creates_a_expr() : void
+ {
+ $expr = new BinaryExpression(
+ new MockExpression(),
+ '+',
+ new MockExpression()
+ );
+
+ $ast = $expr->toAst();
+
+ self::assertInstanceOf(Node::class, $ast);
+ self::assertTrue($ast->hasAExpr());
+
+ $aExpr = $ast->getAExpr();
+ self::assertNotNull($aExpr);
+ self::assertSame(A_Expr_Kind::AEXPR_OP, $aExpr->getKind());
+
+ $name = $aExpr->getName();
+ self::assertNotNull($name);
+ self::assertCount(1, $name);
+
+ $operatorNode = $name[0];
+ self::assertTrue($operatorNode->hasString());
+
+ $operatorString = $operatorNode->getString();
+ self::assertNotNull($operatorString);
+ self::assertSame('+', $operatorString->getSval());
+
+ self::assertTrue($aExpr->hasLexpr());
+ self::assertTrue($aExpr->hasRexpr());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/CaseExpressionTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/CaseExpressionTest.php
new file mode 100644
index 000000000..5ae86e74a
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/CaseExpressionTest.php
@@ -0,0 +1,228 @@
+toAst();
+
+ self::assertNotNull($node->getCaseExpr());
+
+ $case = $node->getCaseExpr();
+ self::assertNull($case->getArg());
+ self::assertNotNull($case->getArgs());
+ self::assertCount(1, $case->getArgs());
+ self::assertNotNull($case->getDefresult());
+ }
+
+ public function test_converts_simple_case_to_ast() : void
+ {
+ $arg = Column::name('status');
+ $whenClause = new WhenClause(
+ Literal::int(1),
+ Literal::string('One')
+ );
+
+ $caseExpr = new CaseExpression($arg, [$whenClause]);
+
+ $node = $caseExpr->toAst();
+
+ self::assertNotNull($node->getCaseExpr());
+
+ $case = $node->getCaseExpr();
+ self::assertNotNull($case->getArg());
+ self::assertNotNull($case->getArgs());
+ self::assertCount(1, $case->getArgs());
+ self::assertNull($case->getDefresult());
+ }
+
+ public function test_creates_aliased_expression() : void
+ {
+ $whenClause = new WhenClause(Literal::bool(true), Literal::int(1));
+ $caseExpr = new CaseExpression(null, [$whenClause]);
+
+ $aliased = $caseExpr->as('my_case');
+
+ self::assertSame('my_case', $aliased->getAlias());
+ self::assertSame($caseExpr, $aliased->getExpression());
+ }
+
+ public function test_creates_searched_case_with_else() : void
+ {
+ $whenClause = new WhenClause(
+ Literal::bool(true),
+ Literal::string('yes')
+ );
+ $elseResult = Literal::string('no');
+
+ $caseExpr = new CaseExpression(null, [$whenClause], $elseResult);
+
+ self::assertNull($caseExpr->getArg());
+ self::assertCount(1, $caseExpr->getWhenClauses());
+ self::assertSame($elseResult, $caseExpr->getElseResult());
+ }
+
+ public function test_creates_searched_case_without_else() : void
+ {
+ $whenClause = new WhenClause(
+ Literal::bool(true),
+ Literal::string('yes')
+ );
+
+ $caseExpr = new CaseExpression(null, [$whenClause]);
+
+ self::assertNull($caseExpr->getArg());
+ self::assertCount(1, $caseExpr->getWhenClauses());
+ self::assertNull($caseExpr->getElseResult());
+ }
+
+ public function test_creates_simple_case() : void
+ {
+ $arg = Column::name('value');
+ $whenClause = new WhenClause(Literal::int(1), Literal::string('one'));
+
+ $caseExpr = new CaseExpression($arg, [$whenClause]);
+
+ self::assertSame($arg, $caseExpr->getArg());
+ self::assertCount(1, $caseExpr->getWhenClauses());
+ self::assertNull($caseExpr->getElseResult());
+ }
+
+ public function test_recreates_from_ast_with_multiple_when_clauses() : void
+ {
+ $caseWhen1 = new CaseWhen();
+ $caseWhen1->setExpr(Literal::int(1)->toAst());
+ $caseWhen1->setResult(Literal::string('one')->toAst());
+
+ $caseWhen2 = new CaseWhen();
+ $caseWhen2->setExpr(Literal::int(2)->toAst());
+ $caseWhen2->setResult(Literal::string('two')->toAst());
+
+ $whenNode1 = new Node();
+ $whenNode1->setCaseWhen($caseWhen1);
+
+ $whenNode2 = new Node();
+ $whenNode2->setCaseWhen($caseWhen2);
+
+ $caseExpr = new CaseExpr();
+ $caseExpr->setArgs([$whenNode1, $whenNode2]);
+ $caseExpr->setDefresult(Literal::string('other')->toAst());
+
+ $node = new Node();
+ $node->setCaseExpr($caseExpr);
+
+ $case = CaseExpression::fromAst($node);
+
+ self::assertNull($case->getArg());
+ self::assertCount(2, $case->getWhenClauses());
+ self::assertNotNull($case->getElseResult());
+ }
+
+ public function test_recreates_from_ast_with_simple_case() : void
+ {
+ $arg = Column::name('status');
+
+ $caseWhen = new CaseWhen();
+ $caseWhen->setExpr(Literal::int(1)->toAst());
+ $caseWhen->setResult(Literal::string('one')->toAst());
+
+ $whenNode = new Node();
+ $whenNode->setCaseWhen($caseWhen);
+
+ $caseExpr = new CaseExpr();
+ $caseExpr->setArg($arg->toAst());
+ $caseExpr->setArgs([$whenNode]);
+
+ $node = new Node();
+ $node->setCaseExpr($caseExpr);
+
+ $case = CaseExpression::fromAst($node);
+
+ self::assertNotNull($case->getArg());
+ self::assertCount(1, $case->getWhenClauses());
+ }
+
+ public function test_round_trip_conversion_with_searched_case() : void
+ {
+ $whenClause = new WhenClause(
+ Literal::bool(true),
+ Literal::int(1)
+ );
+
+ $caseExpr = new CaseExpression(null, [$whenClause], Literal::int(0));
+ $node = $caseExpr->toAst();
+ $restored = CaseExpression::fromAst($node);
+
+ self::assertNull($restored->getArg());
+ self::assertCount(1, $restored->getWhenClauses());
+ self::assertNotNull($restored->getElseResult());
+ }
+
+ public function test_round_trip_conversion_with_simple_case() : void
+ {
+ $arg = Column::name('value');
+ $whenClause = new WhenClause(Literal::int(1), Literal::string('one'));
+
+ $caseExpr = new CaseExpression($arg, [$whenClause]);
+ $node = $caseExpr->toAst();
+ $restored = CaseExpression::fromAst($node);
+
+ self::assertNotNull($restored->getArg());
+ self::assertCount(1, $restored->getWhenClauses());
+ self::assertNull($restored->getElseResult());
+ }
+
+ public function test_throws_exception_for_empty_when_clauses() : void
+ {
+ $this->expectException(InvalidExpressionException::class);
+
+ /** @phpstan-ignore argument.type (intentionally testing exception) */
+ new CaseExpression(null, []);
+ }
+
+ public function test_with_else_creates_new_instance() : void
+ {
+ $whenClause = new WhenClause(Literal::bool(true), Literal::int(1));
+ $caseExpr = new CaseExpression(null, [$whenClause]);
+
+ $newElse = Literal::int(0);
+ $newCase = $caseExpr->withElse($newElse);
+
+ self::assertNotSame($caseExpr, $newCase);
+ self::assertNull($caseExpr->getElseResult());
+ self::assertSame($newElse, $newCase->getElseResult());
+ }
+
+ public function test_with_when_creates_new_instance() : void
+ {
+ $whenClause1 = new WhenClause(Literal::bool(true), Literal::int(1));
+ $caseExpr = new CaseExpression(null, [$whenClause1]);
+
+ $whenClause2 = new WhenClause(Literal::bool(false), Literal::int(0));
+ $newCase = $caseExpr->withWhen($whenClause2);
+
+ self::assertNotSame($caseExpr, $newCase);
+ self::assertCount(1, $caseExpr->getWhenClauses());
+ self::assertCount(1, $newCase->getWhenClauses());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/CoalesceTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/CoalesceTest.php
new file mode 100644
index 000000000..e4a54a125
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/CoalesceTest.php
@@ -0,0 +1,137 @@
+as('first_non_null');
+
+ self::assertInstanceOf(AliasedExpression::class, $aliased);
+ }
+
+ public function test_coalesce_deparsed_output() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $expr = new Coalesce([Column::name('email'), Literal::string('no-email@example.com')]);
+
+ $select = SelectBuilder::create()
+ ->select($expr)
+ ->from(new Table('users'));
+
+ $parser = new Parser();
+ $ast = $select->toAst();
+ $node = new Node(['select_stmt' => $ast]);
+ $rawStmt = new RawStmt(['stmt' => $node]);
+ $parsed = $parser->parse('SELECT 1');
+ $parseResult = $parsed->raw();
+ $parseResult->setStmts([$rawStmt]);
+
+ $deparsed = (new \Flow\PostgreSql\ParsedQuery($parseResult))->deparse();
+
+ self::assertSame("SELECT COALESCE(email, 'no-email@example.com') FROM users", $deparsed);
+ }
+
+ public function test_constructor_throws_on_less_than_two_expressions() : void
+ {
+ $this->expectException(\InvalidArgumentException::class);
+ $this->expectExceptionMessage('COALESCE requires at least 2 expressions');
+
+ new Coalesce([new MockExpression()]);
+ }
+
+ public function test_expressions_getter() : void
+ {
+ $expr1 = new MockExpression();
+ $expr2 = new MockExpression();
+ $expr3 = new MockExpression();
+
+ $coalesce = new Coalesce([$expr1, $expr2, $expr3]);
+
+ $expressions = $coalesce->expressions();
+
+ self::assertCount(3, $expressions);
+ self::assertSame($expr1, $expressions[0]);
+ self::assertSame($expr2, $expressions[1]);
+ self::assertSame($expr3, $expressions[2]);
+ }
+
+ public function test_from_ast_throws_on_insufficient_args() : void
+ {
+ $this->expectException(InvalidAstException::class);
+ $this->expectExceptionMessage('must have at least 2 arguments');
+
+ $coalesceExpr = new CoalesceExpr();
+ $coalesceExpr->setArgs([new Node()]);
+
+ $node = new Node();
+ $node->setCoalesceExpr($coalesceExpr);
+
+ Coalesce::fromAst($node);
+ }
+
+ public function test_from_ast_throws_on_non_coalesce_expr() : void
+ {
+ $this->expectException(InvalidAstException::class);
+ $this->expectExceptionMessage('Expected CoalesceExpr node, got unknown');
+
+ $node = new Node();
+ Coalesce::fromAst($node);
+ }
+
+ public function test_to_ast_creates_coalesce_expr() : void
+ {
+ $expr = new Coalesce([
+ new MockExpression('first'),
+ new MockExpression('second'),
+ new MockExpression('third'),
+ ]);
+
+ $ast = $expr->toAst();
+
+ self::assertInstanceOf(Node::class, $ast);
+ self::assertTrue($ast->hasCoalesceExpr());
+
+ $coalesceExpr = $ast->getCoalesceExpr();
+ self::assertNotNull($coalesceExpr);
+ $args = $coalesceExpr->getArgs();
+
+ self::assertCount(3, $args);
+ }
+
+ public function test_with_minimum_expressions() : void
+ {
+ $expr = new Coalesce([new MockExpression(), new MockExpression()]);
+
+ $ast = $expr->toAst();
+
+ self::assertTrue($ast->hasCoalesceExpr());
+
+ $coalesceExpr = $ast->getCoalesceExpr();
+ self::assertNotNull($coalesceExpr);
+ self::assertCount(2, $coalesceExpr->getArgs());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/ColumnTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/ColumnTest.php
new file mode 100644
index 000000000..3d3b685c0
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/ColumnTest.php
@@ -0,0 +1,104 @@
+toAst();
+
+ $columnRef = $node->getColumnRef();
+ self::assertNotNull($columnRef);
+
+ $fields = $columnRef->getFields();
+ self::assertCount(2, $fields);
+
+ $firstField = $fields[0]->getString();
+ self::assertNotNull($firstField);
+ self::assertSame('users', $firstField->getSval());
+
+ $secondField = $fields[1]->getString();
+ self::assertNotNull($secondField);
+ self::assertSame('name', $secondField->getSval());
+ }
+
+ public function test_creates_aliased_expression() : void
+ {
+ $column = Column::name('users');
+ $aliased = $column->as('u');
+
+ self::assertInstanceOf(AliasedExpression::class, $aliased);
+ self::assertSame('u', $aliased->getAlias());
+ self::assertSame($column, $aliased->getExpression());
+ }
+
+ public function test_creates_column_from_name() : void
+ {
+ $column = Column::name('users');
+
+ self::assertSame(['users'], $column->parts());
+ self::assertSame('users', $column->columnName());
+ self::assertNull($column->tableName());
+ self::assertNull($column->schemaName());
+ }
+
+ public function test_creates_column_from_parts() : void
+ {
+ $column = Column::fromParts(['catalog', 'schema', 'table', 'column']);
+
+ self::assertSame(['catalog', 'schema', 'table', 'column'], $column->parts());
+ self::assertSame('column', $column->columnName());
+ }
+
+ public function test_creates_column_from_schema_table_and_name() : void
+ {
+ $column = Column::schemaTableColumn('public', 'users', 'id');
+
+ self::assertSame(['public', 'users', 'id'], $column->parts());
+ self::assertSame('id', $column->columnName());
+ self::assertSame('users', $column->tableName());
+ self::assertSame('public', $column->schemaName());
+ }
+
+ public function test_creates_column_from_table_and_name() : void
+ {
+ $column = Column::tableColumn('users', 'id');
+
+ self::assertSame(['users', 'id'], $column->parts());
+ self::assertSame('id', $column->columnName());
+ self::assertSame('users', $column->tableName());
+ self::assertNull($column->schemaName());
+ }
+
+ public function test_rejects_empty_part_string() : void
+ {
+ $this->expectException(InvalidExpressionException::class);
+
+ Column::fromParts(['valid', '']);
+ }
+
+ public function test_rejects_empty_parts() : void
+ {
+ $this->expectException(InvalidExpressionException::class);
+ $this->expectExceptionMessage('Column parts cannot be empty');
+
+ Column::fromParts([]);
+ }
+
+ public function test_roundtrip_conversion() : void
+ {
+ $original = Column::schemaTableColumn('public', 'users', 'id');
+ $node = $original->toAst();
+ $reconstructed = Column::fromAst($node);
+
+ self::assertEquals($original->parts(), $reconstructed->parts());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/FunctionCallTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/FunctionCallTest.php
new file mode 100644
index 000000000..6de718255
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/FunctionCallTest.php
@@ -0,0 +1,140 @@
+toAst();
+ $funcCall = $node->getFuncCall();
+ self::assertNotNull($funcCall);
+ $funcNameNodes = $funcCall->getFuncname();
+
+ self::assertCount(2, $funcNameNodes);
+ $firstString = $funcNameNodes[0]->getString();
+ self::assertNotNull($firstString);
+ self::assertSame('pg_catalog', $firstString->getSval());
+ $secondString = $funcNameNodes[1]->getString();
+ self::assertNotNull($secondString);
+ self::assertSame('sum', $secondString->getSval());
+ }
+
+ public function test_converts_to_ast() : void
+ {
+ $arg = Literal::int(42);
+ $func = new FunctionCall(['test_func'], [$arg]);
+
+ $node = $func->toAst();
+
+ $funcCall = $node->getFuncCall();
+ self::assertNotNull($funcCall);
+
+ $funcNameNodes = $funcCall->getFuncname();
+
+ self::assertCount(1, $funcNameNodes);
+ $firstString = $funcNameNodes[0]->getString();
+ self::assertNotNull($firstString);
+ self::assertSame('test_func', $firstString->getSval());
+
+ $argNodes = $funcCall->getArgs();
+ self::assertCount(1, $argNodes);
+ }
+
+ public function test_creates_aliased_expression() : void
+ {
+ $func = new FunctionCall(['test'], []);
+ $aliased = $func->as('my_alias');
+
+ self::assertSame('my_alias', $aliased->getAlias());
+ self::assertSame($func, $aliased->getExpression());
+ }
+
+ public function test_creates_function_call_with_arguments() : void
+ {
+ $arg1 = Literal::int(1);
+ $arg2 = Literal::string('test');
+
+ $func = new FunctionCall(['my_func'], [$arg1, $arg2]);
+
+ self::assertCount(2, $func->getArgs());
+ }
+
+ public function test_creates_function_call_with_schema() : void
+ {
+ $func = new FunctionCall(['pg_catalog', 'count'], []);
+
+ self::assertSame(['pg_catalog', 'count'], $func->getFuncName());
+ }
+
+ public function test_creates_simple_function_call() : void
+ {
+ $func = new FunctionCall(['my_func'], []);
+
+ self::assertSame(['my_func'], $func->getFuncName());
+ self::assertSame([], $func->getArgs());
+ }
+
+ public function test_recreates_from_ast() : void
+ {
+ $stringNode = new PBString();
+ $stringNode->setSval('my_func');
+
+ $nameNode = new Node();
+ $nameNode->setString($stringNode);
+
+ $funcCall = new FuncCall();
+ $funcCall->setFuncname([$nameNode]);
+ $funcCall->setArgs([]);
+
+ $node = new Node();
+ $node->setFuncCall($funcCall);
+
+ $func = FunctionCall::fromAst($node);
+
+ self::assertSame(['my_func'], $func->getFuncName());
+ self::assertSame([], $func->getArgs());
+ }
+
+ public function test_round_trip_conversion() : void
+ {
+ $arg1 = Literal::int(10);
+ $arg2 = Literal::string('value');
+ $func = new FunctionCall(['pg_catalog', 'concat'], [$arg1, $arg2]);
+
+ $node = $func->toAst();
+ $restored = FunctionCall::fromAst($node);
+
+ self::assertSame($func->getFuncName(), $restored->getFuncName());
+ self::assertCount(2, $restored->getArgs());
+ }
+
+ public function test_throws_exception_for_empty_function_name() : void
+ {
+ $this->expectException(InvalidExpressionException::class);
+
+ /** @phpstan-ignore argument.type (intentionally testing exception) */
+ new FunctionCall([], []);
+ }
+
+ public function test_with_args_creates_new_instance() : void
+ {
+ $func = new FunctionCall(['test'], []);
+ $arg = Literal::int(1);
+
+ $newFunc = $func->withArgs($arg);
+
+ self::assertNotSame($func, $newFunc);
+ self::assertSame([], $func->getArgs());
+ self::assertCount(1, $newFunc->getArgs());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/GreatestTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/GreatestTest.php
new file mode 100644
index 000000000..eb2f0ca00
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/GreatestTest.php
@@ -0,0 +1,126 @@
+as('max_value');
+
+ self::assertInstanceOf(AliasedExpression::class, $aliased);
+ }
+
+ public function test_constructor_throws_on_less_than_two_expressions() : void
+ {
+ $this->expectException(\InvalidArgumentException::class);
+ $this->expectExceptionMessage('GREATEST requires at least 2 expressions');
+
+ new Greatest([new MockExpression()]);
+ }
+
+ public function test_expressions_getter() : void
+ {
+ $expr1 = new MockExpression();
+ $expr2 = new MockExpression();
+ $expr3 = new MockExpression();
+
+ $greatest = new Greatest([$expr1, $expr2, $expr3]);
+
+ $expressions = $greatest->expressions();
+
+ self::assertCount(3, $expressions);
+ self::assertSame($expr1, $expressions[0]);
+ self::assertSame($expr2, $expressions[1]);
+ self::assertSame($expr3, $expressions[2]);
+ }
+
+ public function test_from_ast_throws_on_insufficient_args() : void
+ {
+ $this->expectException(InvalidAstException::class);
+ $this->expectExceptionMessage('must have at least 2 arguments');
+
+ $minMaxExpr = new MinMaxExpr();
+ $minMaxExpr->setOp(MinMaxOp::IS_GREATEST);
+ $minMaxExpr->setArgs([new Node()]);
+
+ $node = new Node();
+ $node->setMinMaxExpr($minMaxExpr);
+
+ Greatest::fromAst($node);
+ }
+
+ public function test_from_ast_throws_on_non_min_max_expr() : void
+ {
+ $this->expectException(InvalidAstException::class);
+ $this->expectExceptionMessage('Expected MinMaxExpr node, got unknown');
+
+ $node = new Node();
+ Greatest::fromAst($node);
+ }
+
+ public function test_from_ast_throws_on_wrong_op() : void
+ {
+ $this->expectException(InvalidAstException::class);
+ $this->expectExceptionMessage('must be IS_GREATEST');
+
+ $minMaxExpr = new MinMaxExpr();
+ $minMaxExpr->setOp(MinMaxOp::IS_LEAST);
+ $minMaxExpr->setArgs([new Node(), new Node()]);
+
+ $node = new Node();
+ $node->setMinMaxExpr($minMaxExpr);
+
+ Greatest::fromAst($node);
+ }
+
+ public function test_to_ast_creates_min_max_expr() : void
+ {
+ $expr = new Greatest([
+ new MockExpression('first'),
+ new MockExpression('second'),
+ new MockExpression('third'),
+ ]);
+
+ $ast = $expr->toAst();
+
+ self::assertInstanceOf(Node::class, $ast);
+ self::assertTrue($ast->hasMinMaxExpr());
+
+ $minMaxExpr = $ast->getMinMaxExpr();
+ self::assertNotNull($minMaxExpr);
+ self::assertSame(MinMaxOp::IS_GREATEST, $minMaxExpr->getOp());
+
+ $args = $minMaxExpr->getArgs();
+ self::assertCount(3, $args);
+ }
+
+ public function test_with_minimum_expressions() : void
+ {
+ $expr = new Greatest([new MockExpression(), new MockExpression()]);
+
+ $ast = $expr->toAst();
+
+ self::assertTrue($ast->hasMinMaxExpr());
+
+ $minMaxExpr = $ast->getMinMaxExpr();
+ self::assertNotNull($minMaxExpr);
+ self::assertCount(2, $minMaxExpr->getArgs());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/LeastTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/LeastTest.php
new file mode 100644
index 000000000..13287d436
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/LeastTest.php
@@ -0,0 +1,126 @@
+as('min_value');
+
+ self::assertInstanceOf(AliasedExpression::class, $aliased);
+ }
+
+ public function test_constructor_throws_on_less_than_two_expressions() : void
+ {
+ $this->expectException(\InvalidArgumentException::class);
+ $this->expectExceptionMessage('LEAST requires at least 2 expressions');
+
+ new Least([new MockExpression()]);
+ }
+
+ public function test_expressions_getter() : void
+ {
+ $expr1 = new MockExpression();
+ $expr2 = new MockExpression();
+ $expr3 = new MockExpression();
+
+ $least = new Least([$expr1, $expr2, $expr3]);
+
+ $expressions = $least->expressions();
+
+ self::assertCount(3, $expressions);
+ self::assertSame($expr1, $expressions[0]);
+ self::assertSame($expr2, $expressions[1]);
+ self::assertSame($expr3, $expressions[2]);
+ }
+
+ public function test_from_ast_throws_on_insufficient_args() : void
+ {
+ $this->expectException(InvalidAstException::class);
+ $this->expectExceptionMessage('must have at least 2 arguments');
+
+ $minMaxExpr = new MinMaxExpr();
+ $minMaxExpr->setOp(MinMaxOp::IS_LEAST);
+ $minMaxExpr->setArgs([new Node()]);
+
+ $node = new Node();
+ $node->setMinMaxExpr($minMaxExpr);
+
+ Least::fromAst($node);
+ }
+
+ public function test_from_ast_throws_on_non_min_max_expr() : void
+ {
+ $this->expectException(InvalidAstException::class);
+ $this->expectExceptionMessage('Expected MinMaxExpr node, got unknown');
+
+ $node = new Node();
+ Least::fromAst($node);
+ }
+
+ public function test_from_ast_throws_on_wrong_op() : void
+ {
+ $this->expectException(InvalidAstException::class);
+ $this->expectExceptionMessage('must be IS_LEAST');
+
+ $minMaxExpr = new MinMaxExpr();
+ $minMaxExpr->setOp(MinMaxOp::IS_GREATEST);
+ $minMaxExpr->setArgs([new Node(), new Node()]);
+
+ $node = new Node();
+ $node->setMinMaxExpr($minMaxExpr);
+
+ Least::fromAst($node);
+ }
+
+ public function test_to_ast_creates_min_max_expr() : void
+ {
+ $expr = new Least([
+ new MockExpression('first'),
+ new MockExpression('second'),
+ new MockExpression('third'),
+ ]);
+
+ $ast = $expr->toAst();
+
+ self::assertInstanceOf(Node::class, $ast);
+ self::assertTrue($ast->hasMinMaxExpr());
+
+ $minMaxExpr = $ast->getMinMaxExpr();
+ self::assertNotNull($minMaxExpr);
+ self::assertSame(MinMaxOp::IS_LEAST, $minMaxExpr->getOp());
+
+ $args = $minMaxExpr->getArgs();
+ self::assertCount(3, $args);
+ }
+
+ public function test_with_minimum_expressions() : void
+ {
+ $expr = new Least([new MockExpression(), new MockExpression()]);
+
+ $ast = $expr->toAst();
+
+ self::assertTrue($ast->hasMinMaxExpr());
+
+ $minMaxExpr = $ast->getMinMaxExpr();
+ self::assertNotNull($minMaxExpr);
+ self::assertCount(2, $minMaxExpr->getArgs());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/LiteralTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/LiteralTest.php
new file mode 100644
index 000000000..d4bcb135d
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/LiteralTest.php
@@ -0,0 +1,190 @@
+toAst();
+
+ $aConst = $node->getAConst();
+ self::assertNotNull($aConst);
+
+ $booleanObj = $aConst->getBoolval();
+ self::assertInstanceOf(Boolean::class, $booleanObj);
+ self::assertTrue($booleanObj->getBoolval());
+ }
+
+ public function test_converts_float_to_ast() : void
+ {
+ $literal = Literal::float(3.14);
+ $node = $literal->toAst();
+
+ $aConst = $node->getAConst();
+ self::assertNotNull($aConst);
+
+ $fval = $aConst->getFval();
+ self::assertNotNull($fval);
+ self::assertSame('3.14', $fval->getFval());
+ }
+
+ public function test_converts_int_to_ast() : void
+ {
+ $literal = Literal::int(123);
+ $node = $literal->toAst();
+
+ $aConst = $node->getAConst();
+ self::assertNotNull($aConst);
+ self::assertFalse($aConst->getIsnull());
+
+ $integerObj = $aConst->getIval();
+ self::assertInstanceOf(Integer::class, $integerObj);
+ self::assertSame(123, $integerObj->getIval());
+ }
+
+ public function test_converts_null_to_ast() : void
+ {
+ $literal = Literal::null();
+ $node = $literal->toAst();
+
+ $aConst = $node->getAConst();
+ self::assertNotNull($aConst);
+ self::assertTrue($aConst->getIsnull());
+ }
+
+ public function test_converts_string_to_ast() : void
+ {
+ $literal = Literal::string('test');
+ $node = $literal->toAst();
+
+ $aConst = $node->getAConst();
+ self::assertNotNull($aConst);
+
+ $sval = $aConst->getSval();
+ self::assertNotNull($sval);
+ self::assertSame('test', $sval->getSval());
+ }
+
+ public function test_creates_aliased_expression() : void
+ {
+ $literal = Literal::int(42);
+ $aliased = $literal->as('answer');
+
+ self::assertInstanceOf(AliasedExpression::class, $aliased);
+ self::assertSame('answer', $aliased->getAlias());
+ self::assertSame($literal, $aliased->getExpression());
+ }
+
+ public function test_creates_bool_literal() : void
+ {
+ $literal = Literal::bool(true);
+
+ self::assertTrue($literal->value());
+ self::assertTrue($literal->isBool());
+ self::assertFalse($literal->isString());
+ self::assertFalse($literal->isInt());
+ self::assertFalse($literal->isFloat());
+ self::assertFalse($literal->isNull());
+ }
+
+ public function test_creates_float_literal() : void
+ {
+ $literal = Literal::float(3.14);
+
+ self::assertSame(3.14, $literal->value());
+ self::assertTrue($literal->isFloat());
+ self::assertFalse($literal->isString());
+ self::assertFalse($literal->isInt());
+ self::assertFalse($literal->isBool());
+ self::assertFalse($literal->isNull());
+ }
+
+ public function test_creates_int_literal() : void
+ {
+ $literal = Literal::int(42);
+
+ self::assertSame(42, $literal->value());
+ self::assertTrue($literal->isInt());
+ self::assertFalse($literal->isString());
+ self::assertFalse($literal->isFloat());
+ self::assertFalse($literal->isBool());
+ self::assertFalse($literal->isNull());
+ }
+
+ public function test_creates_null_literal() : void
+ {
+ $literal = Literal::null();
+
+ self::assertNull($literal->value());
+ self::assertTrue($literal->isNull());
+ self::assertFalse($literal->isString());
+ self::assertFalse($literal->isInt());
+ self::assertFalse($literal->isFloat());
+ self::assertFalse($literal->isBool());
+ }
+
+ public function test_creates_string_literal() : void
+ {
+ $literal = Literal::string('hello');
+
+ self::assertSame('hello', $literal->value());
+ self::assertTrue($literal->isString());
+ self::assertFalse($literal->isInt());
+ self::assertFalse($literal->isFloat());
+ self::assertFalse($literal->isBool());
+ self::assertFalse($literal->isNull());
+ }
+
+ public function test_roundtrip_bool_conversion() : void
+ {
+ $original = Literal::bool(false);
+ $node = $original->toAst();
+ $reconstructed = Literal::fromAst($node);
+
+ self::assertEquals($original->value(), $reconstructed->value());
+ }
+
+ public function test_roundtrip_float_conversion() : void
+ {
+ $original = Literal::float(2.718);
+ $node = $original->toAst();
+ $reconstructed = Literal::fromAst($node);
+
+ self::assertEquals($original->value(), $reconstructed->value());
+ }
+
+ public function test_roundtrip_int_conversion() : void
+ {
+ $original = Literal::int(999);
+ $node = $original->toAst();
+ $reconstructed = Literal::fromAst($node);
+
+ self::assertEquals($original->value(), $reconstructed->value());
+ }
+
+ public function test_roundtrip_null_conversion() : void
+ {
+ $original = Literal::null();
+ $node = $original->toAst();
+ $reconstructed = Literal::fromAst($node);
+
+ self::assertTrue($reconstructed->isNull());
+ }
+
+ public function test_roundtrip_string_conversion() : void
+ {
+ $original = Literal::string('hello world');
+ $node = $original->toAst();
+ $reconstructed = Literal::fromAst($node);
+
+ self::assertEquals($original->value(), $reconstructed->value());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/MockExpression.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/MockExpression.php
new file mode 100644
index 000000000..9c1c4e455
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/MockExpression.php
@@ -0,0 +1,61 @@
+getAConst();
+
+ if ($aConst === null) {
+ throw new \RuntimeException('Expected A_Const node');
+ }
+
+ $sval = $aConst->getSval();
+
+ if ($sval === null) {
+ throw new \RuntimeException('Expected sval in A_Const');
+ }
+
+ return new self($sval->getSval());
+ }
+
+ public function as(string $alias) : AliasedExpression
+ {
+ return new AliasedExpression($this, $alias);
+ }
+
+ public function toAst() : Node
+ {
+ $sval = new PBString();
+ $sval->setSval($this->value);
+
+ $aConst = new A_Const();
+ $aConst->setSval($sval);
+ $aConst->setLocation(-1);
+
+ $node = new Node();
+ $node->setAConst($aConst);
+
+ return $node;
+ }
+
+ public function value() : string
+ {
+ return $this->value;
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/NullIfTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/NullIfTest.php
new file mode 100644
index 000000000..592159d25
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/NullIfTest.php
@@ -0,0 +1,85 @@
+as('nullable');
+
+ self::assertInstanceOf(AliasedExpression::class, $aliased);
+ }
+
+ public function test_from_ast_throws_on_non_a_expr() : void
+ {
+ $this->expectException(InvalidAstException::class);
+ $this->expectExceptionMessage('Expected A_Expr node, got unknown');
+
+ $node = new Node();
+ NullIf::fromAst($node);
+ }
+
+ public function test_from_ast_throws_on_wrong_a_expr_kind() : void
+ {
+ $this->expectException(InvalidAstException::class);
+ $this->expectExceptionMessage('Expected AEXPR_NULLIF for NullIf expression');
+
+ $aExpr = new A_Expr();
+ $aExpr->setKind(A_Expr_Kind::AEXPR_OP);
+ $aExpr->setLexpr(new Node());
+ $aExpr->setRexpr(new Node());
+
+ $node = new Node();
+ $node->setAExpr($aExpr);
+
+ NullIf::fromAst($node);
+ }
+
+ public function test_getters() : void
+ {
+ $first = new MockExpression('first');
+ $second = new MockExpression('second');
+
+ $expr = new NullIf($first, $second);
+
+ self::assertSame($first, $expr->first());
+ self::assertSame($second, $expr->second());
+ }
+
+ public function test_to_ast_creates_a_expr_with_aexpr_nullif() : void
+ {
+ $expr = new NullIf(
+ new MockExpression('value1'),
+ new MockExpression('value2')
+ );
+
+ $ast = $expr->toAst();
+
+ self::assertInstanceOf(Node::class, $ast);
+ self::assertTrue($ast->hasAExpr());
+
+ $aExpr = $ast->getAExpr();
+ self::assertNotNull($aExpr);
+ self::assertSame(A_Expr_Kind::AEXPR_NULLIF, $aExpr->getKind());
+
+ self::assertNotNull($aExpr->getLexpr());
+ self::assertNotNull($aExpr->getRexpr());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/ParameterTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/ParameterTest.php
new file mode 100644
index 000000000..3cfbc37c0
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/ParameterTest.php
@@ -0,0 +1,69 @@
+toAst();
+
+ $paramRef = $node->getParamRef();
+ self::assertNotNull($paramRef);
+ self::assertSame(3, $paramRef->getNumber());
+ }
+
+ public function test_creates_aliased_expression() : void
+ {
+ $param = Parameter::positional(1);
+ $aliased = $param->as('p');
+
+ self::assertInstanceOf(AliasedExpression::class, $aliased);
+ self::assertSame('p', $aliased->getAlias());
+ self::assertSame($param, $aliased->getExpression());
+ }
+
+ public function test_creates_parameter_with_higher_number() : void
+ {
+ $param = Parameter::positional(42);
+
+ self::assertSame(42, $param->number());
+ }
+
+ public function test_creates_positional_parameter() : void
+ {
+ $param = Parameter::positional(1);
+
+ self::assertSame(1, $param->number());
+ }
+
+ public function test_rejects_negative_parameter() : void
+ {
+ $this->expectException(InvalidExpressionException::class);
+
+ Parameter::positional(-1);
+ }
+
+ public function test_rejects_zero_parameter() : void
+ {
+ $this->expectException(InvalidExpressionException::class);
+
+ Parameter::positional(0);
+ }
+
+ public function test_roundtrip_conversion() : void
+ {
+ $original = Parameter::positional(5);
+ $node = $original->toAst();
+ $reconstructed = Parameter::fromAst($node);
+
+ self::assertEquals($original->number(), $reconstructed->number());
+ }
+}
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
new file mode 100644
index 000000000..e752c8e9f
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/RawExpressionTest.php
@@ -0,0 +1,133 @@
+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/RowExpressionTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/RowExpressionTest.php
new file mode 100644
index 000000000..5485b61b7
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/RowExpressionTest.php
@@ -0,0 +1,144 @@
+args();
+
+ self::assertCount(3, $args);
+ self::assertSame($arg1, $args[0]);
+ self::assertSame($arg2, $args[1]);
+ self::assertSame($arg3, $args[2]);
+ }
+
+ public function test_as_returns_aliased_expression() : void
+ {
+ $expr = new RowExpression([new MockExpression()]);
+
+ $aliased = $expr->as('my_row');
+
+ self::assertInstanceOf(AliasedExpression::class, $aliased);
+ }
+
+ public function test_constructor_throws_on_empty_args() : void
+ {
+ $this->expectException(\InvalidArgumentException::class);
+ $this->expectExceptionMessage('RowExpression requires at least 1 expression');
+
+ new RowExpression([]);
+ }
+
+ public function test_explicit_row_format() : void
+ {
+ $expr = new RowExpression([new MockExpression()], true);
+
+ $ast = $expr->toAst();
+
+ self::assertTrue($ast->hasRowExpr());
+
+ $rowExpr = $ast->getRowExpr();
+ self::assertNotNull($rowExpr);
+ self::assertSame(CoercionForm::COERCE_EXPLICIT_CALL, $rowExpr->getRowFormat());
+ }
+
+ public function test_from_ast_throws_on_empty_args() : void
+ {
+ $this->expectException(InvalidAstException::class);
+ $this->expectExceptionMessage('must have at least 1 argument');
+
+ $rowExpr = new RowExpr();
+ $rowExpr->setArgs([]);
+
+ $node = new Node();
+ $node->setRowExpr($rowExpr);
+
+ RowExpression::fromAst($node);
+ }
+
+ public function test_from_ast_throws_on_non_row_expr() : void
+ {
+ $this->expectException(InvalidAstException::class);
+ $this->expectExceptionMessage('Expected RowExpr node, got unknown');
+
+ $node = new Node();
+ RowExpression::fromAst($node);
+ }
+
+ public function test_implicit_row_format() : void
+ {
+ $expr = new RowExpression([new MockExpression()], false);
+
+ $ast = $expr->toAst();
+
+ self::assertTrue($ast->hasRowExpr());
+
+ $rowExpr = $ast->getRowExpr();
+ self::assertNotNull($rowExpr);
+ self::assertSame(CoercionForm::COERCE_IMPLICIT_CAST, $rowExpr->getRowFormat());
+ }
+
+ public function test_is_explicit_row_getter() : void
+ {
+ $explicitRow = new RowExpression([new MockExpression()], true);
+ $implicitRow = new RowExpression([new MockExpression()], false);
+
+ self::assertTrue($explicitRow->isExplicitRow());
+ self::assertFalse($implicitRow->isExplicitRow());
+ }
+
+ public function test_to_ast_creates_row_expr() : void
+ {
+ $expr = new RowExpression([
+ new MockExpression('first'),
+ new MockExpression('second'),
+ new MockExpression('third'),
+ ]);
+
+ $ast = $expr->toAst();
+
+ self::assertInstanceOf(Node::class, $ast);
+ self::assertTrue($ast->hasRowExpr());
+
+ $rowExpr = $ast->getRowExpr();
+ self::assertNotNull($rowExpr);
+ $args = $rowExpr->getArgs();
+
+ self::assertCount(3, $args);
+ }
+
+ public function test_with_single_argument() : void
+ {
+ $expr = new RowExpression([new MockExpression('single')]);
+
+ $ast = $expr->toAst();
+
+ self::assertTrue($ast->hasRowExpr());
+
+ $rowExpr = $ast->getRowExpr();
+ self::assertNotNull($rowExpr);
+ self::assertCount(1, $rowExpr->getArgs());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/StarTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/StarTest.php
new file mode 100644
index 000000000..37b018b76
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/StarTest.php
@@ -0,0 +1,91 @@
+toAst();
+
+ $columnRef = $node->getColumnRef();
+ self::assertNotNull($columnRef);
+
+ $fields = $columnRef->getFields();
+ self::assertCount(1, $fields);
+
+ $starField = $fields[0]->getAStar();
+ self::assertNotNull($starField);
+ }
+
+ public function test_converts_qualified_star_to_ast() : void
+ {
+ $star = Star::fromTable('users');
+ $node = $star->toAst();
+
+ $columnRef = $node->getColumnRef();
+ self::assertNotNull($columnRef);
+
+ $fields = $columnRef->getFields();
+ self::assertCount(2, $fields);
+
+ $tableField = $fields[0]->getString();
+ self::assertNotNull($tableField);
+ self::assertSame('users', $tableField->getSval());
+
+ $starField = $fields[1]->getAStar();
+ self::assertNotNull($starField);
+ }
+
+ public function test_creates_aliased_expression() : void
+ {
+ $star = Star::all();
+ $aliased = $star->as('all_columns');
+
+ self::assertInstanceOf(AliasedExpression::class, $aliased);
+ self::assertSame('all_columns', $aliased->getAlias());
+ self::assertSame($star, $aliased->getExpression());
+ }
+
+ public function test_creates_plain_star() : void
+ {
+ $star = Star::all();
+
+ self::assertNull($star->table());
+ self::assertFalse($star->isQualified());
+ }
+
+ public function test_creates_qualified_star() : void
+ {
+ $star = Star::fromTable('users');
+
+ self::assertSame('users', $star->table());
+ self::assertTrue($star->isQualified());
+ }
+
+ public function test_roundtrip_plain_star_conversion() : void
+ {
+ $original = Star::all();
+ $node = $original->toAst();
+ $reconstructed = Star::fromAst($node);
+
+ self::assertEquals($original->table(), $reconstructed->table());
+ self::assertFalse($reconstructed->isQualified());
+ }
+
+ public function test_roundtrip_qualified_star_conversion() : void
+ {
+ $original = Star::fromTable('products');
+ $node = $original->toAst();
+ $reconstructed = Star::fromAst($node);
+
+ self::assertEquals($original->table(), $reconstructed->table());
+ self::assertTrue($reconstructed->isQualified());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/SubqueryTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/SubqueryTest.php
new file mode 100644
index 000000000..3176d4c78
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/SubqueryTest.php
@@ -0,0 +1,103 @@
+setSelectStmt($selectStmt);
+
+ $subquery = new Subquery($selectNode);
+ $node = $subquery->toAst();
+
+ $subLink = $node->getSubLink();
+ self::assertNotNull($subLink);
+ self::assertSame(SubLinkType::EXPR_SUBLINK, $subLink->getSubLinkType());
+ self::assertNotNull($subLink->getSubselect());
+ }
+
+ public function test_creates_aliased_expression() : void
+ {
+ $selectStmt = new SelectStmt();
+ $selectNode = new Node();
+ $selectNode->setSelectStmt($selectStmt);
+
+ $subquery = new Subquery($selectNode);
+ $aliased = $subquery->as('subq');
+
+ self::assertSame('subq', $aliased->getAlias());
+ self::assertSame($subquery, $aliased->getExpression());
+ }
+
+ public function test_creates_subquery() : void
+ {
+ $selectStmt = new SelectStmt();
+ $selectNode = new Node();
+ $selectNode->setSelectStmt($selectStmt);
+
+ $subquery = new Subquery($selectNode);
+
+ self::assertSame($selectNode, $subquery->getSelectStatement());
+ }
+
+ public function test_recreates_from_ast() : void
+ {
+ $selectStmt = new SelectStmt();
+ $selectNode = new Node();
+ $selectNode->setSelectStmt($selectStmt);
+
+ $subLink = new SubLink();
+ $subLink->setSubLinkType(SubLinkType::EXPR_SUBLINK);
+ $subLink->setSubselect($selectNode);
+
+ $node = new Node();
+ $node->setSubLink($subLink);
+
+ $subquery = Subquery::fromAst($node);
+
+ self::assertInstanceOf(Subquery::class, $subquery);
+ self::assertInstanceOf(Node::class, $subquery->getSelectStatement());
+ }
+
+ public function test_round_trip_conversion() : void
+ {
+ $selectStmt = new SelectStmt();
+ $selectNode = new Node();
+ $selectNode->setSelectStmt($selectStmt);
+
+ $subquery = new Subquery($selectNode);
+ $node = $subquery->toAst();
+ $restored = Subquery::fromAst($node);
+
+ self::assertInstanceOf(Subquery::class, $restored);
+ }
+
+ public function test_throws_exception_for_non_expr_sublink_type() : void
+ {
+ $this->expectException(InvalidAstException::class);
+ $this->expectExceptionMessage('expected EXPR_SUBLINK');
+
+ $selectStmt = new SelectStmt();
+ $selectNode = new Node();
+ $selectNode->setSelectStmt($selectStmt);
+
+ $subLink = new SubLink();
+ $subLink->setSubLinkType(SubLinkType::EXISTS_SUBLINK);
+ $subLink->setSubselect($selectNode);
+
+ $node = new Node();
+ $node->setSubLink($subLink);
+
+ Subquery::fromAst($node);
+ }
+}
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
new file mode 100644
index 000000000..fae7f71f1
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/TypeCastTest.php
@@ -0,0 +1,203 @@
+toAst();
+ $restored = TypeCast::fromAst($node);
+
+ self::assertSame(['varchar'], $restored->getTypeName());
+ self::assertInstanceOf(TypeCast::class, $restored->getExpression());
+ }
+
+ public function test_converts_to_ast() : void
+ {
+ $expr = Literal::string('123');
+ $cast = new TypeCast($expr, ['integer']);
+
+ $node = $cast->toAst();
+
+ $typeCast = $node->getTypeCast();
+ self::assertNotNull($typeCast);
+ self::assertNotNull($typeCast->getArg());
+
+ $typeName = $typeCast->getTypeName();
+ self::assertNotNull($typeName);
+
+ $namesNodes = $typeName->getNames();
+ self::assertCount(1, $namesNodes);
+ $stringNode = $namesNodes[0]->getString();
+ self::assertNotNull($stringNode);
+ self::assertSame('integer', $stringNode->getSval());
+ }
+
+ public function test_converts_type_cast_with_schema_to_ast() : void
+ {
+ $expr = Column::name('id');
+ $cast = new TypeCast($expr, ['pg_catalog', 'text']);
+
+ $node = $cast->toAst();
+ $typeCast = $node->getTypeCast();
+ self::assertNotNull($typeCast);
+ $typeName = $typeCast->getTypeName();
+ self::assertNotNull($typeName);
+ $namesNodes = $typeName->getNames();
+
+ self::assertCount(2, $namesNodes);
+ $firstString = $namesNodes[0]->getString();
+ self::assertNotNull($firstString);
+ self::assertSame('pg_catalog', $firstString->getSval());
+ $secondString = $namesNodes[1]->getString();
+ self::assertNotNull($secondString);
+ self::assertSame('text', $secondString->getSval());
+ }
+
+ public function test_creates_aliased_expression() : void
+ {
+ $expr = Literal::int(42);
+ $cast = new TypeCast($expr, ['varchar']);
+ $aliased = $cast->as('casted_value');
+
+ self::assertSame('casted_value', $aliased->getAlias());
+ self::assertSame($cast, $aliased->getExpression());
+ }
+
+ public function test_creates_simple_type_cast() : void
+ {
+ $expr = Literal::int(42);
+ $cast = new TypeCast($expr, ['varchar']);
+
+ self::assertSame(['varchar'], $cast->getTypeName());
+ self::assertSame($expr, $cast->getExpression());
+ }
+
+ public function test_creates_type_cast_with_schema() : void
+ {
+ $expr = Column::name('value');
+ $cast = new TypeCast($expr, ['pg_catalog', 'int4']);
+
+ self::assertSame(['pg_catalog', 'int4'], $cast->getTypeName());
+ }
+
+ public function test_recreates_from_ast() : void
+ {
+ $stringNode = new PBString();
+ $stringNode->setSval('varchar');
+
+ $nameNode = new Node();
+ $nameNode->setString($stringNode);
+
+ $typeName = new TypeName();
+ $typeName->setNames([$nameNode]);
+
+ $argNode = Literal::int(42)->toAst();
+
+ $typeCast = new AstTypeCast();
+ $typeCast->setArg($argNode);
+ $typeCast->setTypeName($typeName);
+
+ $node = new Node();
+ $node->setTypeCast($typeCast);
+
+ $cast = TypeCast::fromAst($node);
+
+ self::assertSame(['varchar'], $cast->getTypeName());
+ }
+
+ public function test_recreates_type_cast_with_schema_from_ast() : void
+ {
+ $schemaNode = new PBString();
+ $schemaNode->setSval('pg_catalog');
+ $schemaNameNode = new Node();
+ $schemaNameNode->setString($schemaNode);
+
+ $typeNode = new PBString();
+ $typeNode->setSval('int4');
+ $typeNameNode = new Node();
+ $typeNameNode->setString($typeNode);
+
+ $typeName = new TypeName();
+ $typeName->setNames([$schemaNameNode, $typeNameNode]);
+
+ $argNode = Column::name('value')->toAst();
+
+ $typeCast = new AstTypeCast();
+ $typeCast->setArg($argNode);
+ $typeCast->setTypeName($typeName);
+
+ $node = new Node();
+ $node->setTypeCast($typeCast);
+
+ $cast = TypeCast::fromAst($node);
+
+ self::assertSame(['pg_catalog', 'int4'], $cast->getTypeName());
+ }
+
+ public function test_round_trip_conversion() : void
+ {
+ $expr = Column::name('amount');
+ $cast = new TypeCast($expr, ['pg_catalog', 'numeric']);
+
+ $node = $cast->toAst();
+ $restored = TypeCast::fromAst($node);
+
+ self::assertSame($cast->getTypeName(), $restored->getTypeName());
+ }
+
+ public function test_throws_exception_for_empty_type_name() : void
+ {
+ $this->expectException(InvalidExpressionException::class);
+
+ $expr = Literal::int(1);
+ /** @phpstan-ignore argument.type (intentionally testing exception) */
+ new TypeCast($expr, []);
+ }
+
+ public function test_with_expression_creates_new_instance() : void
+ {
+ $expr1 = Literal::int(1);
+ $expr2 = Literal::int(2);
+ $cast = new TypeCast($expr1, ['integer']);
+
+ $newCast = $cast->withExpression($expr2);
+
+ self::assertNotSame($cast, $newCast);
+ self::assertSame($expr1, $cast->getExpression());
+ self::assertSame($expr2, $newCast->getExpression());
+ }
+
+ public function test_with_type_name_creates_new_instance() : void
+ {
+ $expr = Literal::int(1);
+ $cast = new TypeCast($expr, ['integer']);
+
+ $newCast = $cast->withTypeName('varchar');
+
+ self::assertNotSame($cast, $newCast);
+ self::assertSame(['integer'], $cast->getTypeName());
+ self::assertSame(['varchar'], $newCast->getTypeName());
+ }
+
+ public function test_with_type_name_throws_exception_for_empty_array() : void
+ {
+ $this->expectException(InvalidExpressionException::class);
+
+ $expr = Literal::int(1);
+ $cast = new TypeCast($expr, ['integer']);
+
+ $cast->withTypeName();
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/WhenClauseTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/WhenClauseTest.php
new file mode 100644
index 000000000..f71f111a9
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/WhenClauseTest.php
@@ -0,0 +1,67 @@
+toAst();
+
+ self::assertNotNull($node->getCaseWhen());
+
+ $caseWhen = $node->getCaseWhen();
+ self::assertNotNull($caseWhen->getExpr());
+ self::assertNotNull($caseWhen->getResult());
+ }
+
+ public function test_creates_when_clause() : void
+ {
+ $condition = Literal::bool(true);
+ $result = Literal::string('yes');
+
+ $whenClause = new WhenClause($condition, $result);
+
+ self::assertSame($condition, $whenClause->getCondition());
+ self::assertSame($result, $whenClause->getResult());
+ }
+
+ public function test_recreates_from_ast() : void
+ {
+ $condition = Literal::int(1);
+ $result = Literal::string('one');
+
+ $caseWhen = new CaseWhen();
+ $caseWhen->setExpr($condition->toAst());
+ $caseWhen->setResult($result->toAst());
+
+ $node = new Node();
+ $node->setCaseWhen($caseWhen);
+
+ $whenClause = WhenClause::fromAst($node);
+
+ self::assertInstanceOf(WhenClause::class, $whenClause);
+ }
+
+ public function test_round_trip_conversion() : void
+ {
+ $condition = Literal::bool(false);
+ $result = Literal::int(0);
+
+ $whenClause = new WhenClause($condition, $result);
+ $node = $whenClause->toAst();
+ $restored = WhenClause::fromAst($node);
+
+ self::assertInstanceOf(WhenClause::class, $restored);
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/WindowFunctionTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/WindowFunctionTest.php
new file mode 100644
index 000000000..18152da72
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Expression/WindowFunctionTest.php
@@ -0,0 +1,180 @@
+toAst();
+
+ self::assertNotNull($node->getFuncCall());
+
+ $funcCall = $node->getFuncCall();
+ self::assertNotNull($funcCall->getOver());
+
+ $over = $funcCall->getOver();
+ self::assertNotNull($over->getPartitionClause());
+ self::assertCount(1, $over->getPartitionClause());
+ self::assertNotNull($over->getOrderClause());
+ self::assertCount(1, $over->getOrderClause());
+ }
+
+ public function test_converts_to_ast_with_minimal_window() : void
+ {
+ $windowFunc = new WindowFunction(['rank']);
+
+ $node = $windowFunc->toAst();
+
+ self::assertNotNull($node->getFuncCall());
+
+ $funcCall = $node->getFuncCall();
+ self::assertNotNull($funcCall->getOver());
+ }
+
+ public function test_creates_aliased_expression() : void
+ {
+ $windowFunc = new WindowFunction(['row_number']);
+ $aliased = $windowFunc->as('rn');
+
+ self::assertSame('rn', $aliased->getAlias());
+ self::assertSame($windowFunc, $aliased->getExpression());
+ }
+
+ public function test_creates_window_function_with_all_components() : void
+ {
+ $windowFunc = new WindowFunction(
+ ['rank'],
+ [Column::name('score')],
+ [Column::name('category')],
+ [new OrderBy(Column::name('score'), SortDirection::DESC)]
+ );
+
+ self::assertSame(['rank'], $windowFunc->getFuncName());
+ self::assertCount(1, $windowFunc->getArgs());
+ self::assertCount(1, $windowFunc->getPartitionBy());
+ self::assertCount(1, $windowFunc->getOrderBy());
+ }
+
+ public function test_creates_window_function_with_schema() : void
+ {
+ $windowFunc = new WindowFunction(['pg_catalog', 'row_number']);
+
+ self::assertSame(['pg_catalog', 'row_number'], $windowFunc->getFuncName());
+ self::assertSame([], $windowFunc->getArgs());
+ self::assertSame([], $windowFunc->getPartitionBy());
+ self::assertSame([], $windowFunc->getOrderBy());
+ }
+
+ public function test_creates_window_function_without_partition_or_order() : void
+ {
+ $windowFunc = new WindowFunction(['row_number']);
+
+ self::assertSame(['row_number'], $windowFunc->getFuncName());
+ self::assertSame([], $windowFunc->getArgs());
+ self::assertSame([], $windowFunc->getPartitionBy());
+ self::assertSame([], $windowFunc->getOrderBy());
+ }
+
+ public function test_recreates_from_ast() : void
+ {
+ $funcNameNode = new Node();
+ $funcNameNode->setString((new PBString())->setSval('row_number'));
+
+ $partitionNode = Column::name('category')->toAst();
+ $orderByNode = (new OrderBy(Column::name('created_at')))->toAst();
+
+ $windowDef = new WindowDef();
+ $windowDef->setPartitionClause([$partitionNode]);
+ $windowDef->setOrderClause([$orderByNode]);
+
+ $funcCall = new FuncCall();
+ $funcCall->setFuncname([$funcNameNode]);
+ $funcCall->setOver($windowDef);
+
+ $node = new Node();
+ $node->setFuncCall($funcCall);
+
+ $windowFunc = WindowFunction::fromAst($node);
+
+ self::assertSame(['row_number'], $windowFunc->getFuncName());
+ self::assertCount(1, $windowFunc->getPartitionBy());
+ self::assertCount(1, $windowFunc->getOrderBy());
+ }
+
+ public function test_round_trip_conversion() : void
+ {
+ $windowFunc = new WindowFunction(
+ ['rank'],
+ [],
+ [Column::name('department')],
+ [new OrderBy(Column::name('salary'), SortDirection::DESC)]
+ );
+
+ $node = $windowFunc->toAst();
+ $restored = WindowFunction::fromAst($node);
+
+ self::assertSame($windowFunc->getFuncName(), $restored->getFuncName());
+ self::assertCount(1, $restored->getPartitionBy());
+ self::assertCount(1, $restored->getOrderBy());
+ }
+
+ public function test_throws_exception_for_empty_function_name() : void
+ {
+ $this->expectException(InvalidExpressionException::class);
+
+ /** @phpstan-ignore argument.type (intentionally testing exception) */
+ new WindowFunction([]);
+ }
+
+ public function test_with_args_creates_new_instance() : void
+ {
+ $windowFunc = new WindowFunction(['lag']);
+ $arg = Column::name('value');
+
+ $newFunc = $windowFunc->withArgs($arg);
+
+ self::assertNotSame($windowFunc, $newFunc);
+ self::assertSame([], $windowFunc->getArgs());
+ self::assertCount(1, $newFunc->getArgs());
+ }
+
+ public function test_with_order_by_creates_new_instance() : void
+ {
+ $windowFunc = new WindowFunction(['rank']);
+ $orderBy = new OrderBy(Column::name('score'));
+
+ $newFunc = $windowFunc->withOrderBy($orderBy);
+
+ self::assertNotSame($windowFunc, $newFunc);
+ self::assertSame([], $windowFunc->getOrderBy());
+ self::assertCount(1, $newFunc->getOrderBy());
+ }
+
+ public function test_with_partition_by_creates_new_instance() : void
+ {
+ $windowFunc = new WindowFunction(['row_number']);
+ $partition = Column::name('category');
+
+ $newFunc = $windowFunc->withPartitionBy($partition);
+
+ self::assertNotSame($windowFunc, $newFunc);
+ self::assertSame([], $windowFunc->getPartitionBy());
+ self::assertCount(1, $newFunc->getPartitionBy());
+ }
+}
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
new file mode 100644
index 000000000..3a304793e
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Insert/InsertBuilderTest.php
@@ -0,0 +1,642 @@
+into('users')
+ ->columns('email', 'name', 'age')
+ ->values(Literal::string('john@example.com'), Literal::string('John'), Literal::int(30))
+ ->values(Literal::string('jane@example.com'), Literal::string('Jane'), Literal::int(25))
+ ->onConflictDoUpdate(
+ ConflictTarget::columns(['email']),
+ [
+ 'name' => Column::name('excluded.name'),
+ 'age' => Column::name('excluded.age'),
+ 'updated_at' => new FunctionCall(['now']),
+ ]
+ )
+ ->where(new IsNull(Column::name('users.deleted_at')))
+ ->returning(Column::name('id'), Column::name('email'), Column::name('updated_at'));
+
+ $ast = $query->toAst();
+
+ self::assertInstanceOf(InsertStmt::class, $ast);
+ self::assertNotNull($ast->getOnConflictClause());
+ self::assertNotNull($ast->getReturningList());
+ self::assertCount(3, $ast->getReturningList());
+ }
+
+ public function test_immutability_on_columns() : void
+ {
+ $step1 = InsertBuilder::create()->into('users');
+ $step2 = $step1->columns('name', 'email');
+
+ self::assertNotSame($step1, $step2);
+ }
+
+ public function test_immutability_on_on_conflict() : void
+ {
+ $step1 = InsertBuilder::create()
+ ->into('users')
+ ->columns('email')
+ ->values(Literal::string('john@example.com'));
+ $step2 = $step1->onConflictDoNothing();
+
+ self::assertNotSame($step1, $step2);
+ }
+
+ public function test_immutability_on_returning() : void
+ {
+ $step1 = InsertBuilder::create()
+ ->into('users')
+ ->columns('name')
+ ->values(Literal::string('John'));
+ $step2 = $step1->returning(Column::name('id'));
+
+ self::assertNotSame($step1, $step2);
+ }
+
+ public function test_immutability_on_values() : void
+ {
+ $step1 = InsertBuilder::create()
+ ->into('users')
+ ->columns('name');
+ $step2 = $step1->values(Literal::string('John'));
+
+ self::assertNotSame($step1, $step2);
+ }
+
+ public function test_insert_default_values() : void
+ {
+ $query = InsertBuilder::create()
+ ->into('logs')
+ ->defaultValues();
+
+ $ast = $query->toAst();
+
+ self::assertInstanceOf(InsertStmt::class, $ast);
+
+ // DEFAULT VALUES produces an INSERT with no selectStmt at all
+ // This is the correct PostgreSQL AST representation for DEFAULT VALUES
+ $selectStmtNode = $ast->getSelectStmt();
+ self::assertNull($selectStmtNode);
+ }
+
+ public function test_insert_multiple_rows() : void
+ {
+ $query = InsertBuilder::create()
+ ->into('users')
+ ->columns('name', 'email')
+ ->values(Literal::string('John'), Literal::string('john@example.com'))
+ ->values(Literal::string('Jane'), Literal::string('jane@example.com'));
+
+ $ast = $query->toAst();
+
+ self::assertInstanceOf(InsertStmt::class, $ast);
+ $selectStmt = $ast->getSelectStmt()?->getSelectStmt();
+ self::assertNotNull($selectStmt);
+ $valuesLists = $selectStmt->getValuesLists();
+ self::assertNotNull($valuesLists);
+ self::assertCount(2, $valuesLists);
+ }
+
+ public function test_insert_multiple_rows_deparsed_output() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $insert = InsertBuilder::create()
+ ->into('users')
+ ->columns('name', 'email')
+ ->values(Literal::string('John'), Literal::string('john@example.com'))
+ ->values(Literal::string('Jane'), Literal::string('jane@example.com'));
+
+ $deparsed = $this->deparse($insert->toAst());
+ self::assertSame("INSERT INTO users (name, email) VALUES ('John', 'john@example.com'), ('Jane', 'jane@example.com')", $deparsed);
+ }
+
+ public function test_insert_on_conflict_do_nothing() : void
+ {
+ $query = InsertBuilder::create()
+ ->into('users')
+ ->columns('email', 'name')
+ ->values(Literal::string('john@example.com'), Literal::string('John'))
+ ->onConflictDoNothing(ConflictTarget::columns(['email']));
+
+ $ast = $query->toAst();
+
+ self::assertInstanceOf(InsertStmt::class, $ast);
+ self::assertNotNull($ast->getOnConflictClause());
+ }
+
+ public function test_insert_on_conflict_do_nothing_without_target() : void
+ {
+ $query = InsertBuilder::create()
+ ->into('users')
+ ->columns('email', 'name')
+ ->values(Literal::string('john@example.com'), Literal::string('John'))
+ ->onConflictDoNothing();
+
+ $ast = $query->toAst();
+
+ self::assertInstanceOf(InsertStmt::class, $ast);
+ self::assertNotNull($ast->getOnConflictClause());
+ }
+
+ public function test_insert_on_conflict_do_update() : void
+ {
+ $query = InsertBuilder::create()
+ ->into('users')
+ ->columns('email', 'name')
+ ->values(Literal::string('john@example.com'), Literal::string('John'))
+ ->onConflictDoUpdate(
+ ConflictTarget::columns(['email']),
+ ['name' => Column::name('excluded.name')]
+ );
+
+ $ast = $query->toAst();
+
+ self::assertInstanceOf(InsertStmt::class, $ast);
+ $onConflict = $ast->getOnConflictClause();
+ self::assertNotNull($onConflict);
+ self::assertNotNull($onConflict->getTargetList());
+ self::assertCount(1, $onConflict->getTargetList());
+ }
+
+ public function test_insert_on_conflict_do_update_with_where() : void
+ {
+ $query = InsertBuilder::create()
+ ->into('users')
+ ->columns('email', 'name')
+ ->values(Literal::string('john@example.com'), Literal::string('John'))
+ ->onConflictDoUpdate(
+ ConflictTarget::columns(['email']),
+ ['name' => Column::name('excluded.name')]
+ )
+ ->where(new IsNull(Column::name('deleted_at')));
+
+ $ast = $query->toAst();
+
+ self::assertInstanceOf(InsertStmt::class, $ast);
+ $onConflict = $ast->getOnConflictClause();
+ self::assertNotNull($onConflict);
+ self::assertNotNull($onConflict->getWhereClause());
+ }
+
+ public function test_insert_on_conflict_on_constraint() : void
+ {
+ $query = InsertBuilder::create()
+ ->into('users')
+ ->columns('email', 'name')
+ ->values(Literal::string('john@example.com'), Literal::string('John'))
+ ->onConflictDoNothing(ConflictTarget::constraint('users_email_key'));
+
+ $ast = $query->toAst();
+
+ self::assertInstanceOf(InsertStmt::class, $ast);
+ self::assertNotNull($ast->getOnConflictClause());
+ }
+
+ public function test_insert_on_conflict_with_clause() : void
+ {
+ $target = ConflictTarget::columns(['email']);
+ $onConflict = OnConflictClause::doUpdate($target, ['name' => Column::name('excluded.name')]);
+
+ $query = InsertBuilder::create()
+ ->into('users')
+ ->columns('email', 'name')
+ ->values(Literal::string('john@example.com'), Literal::string('John'))
+ ->onConflict($onConflict);
+
+ $ast = $query->toAst();
+
+ self::assertInstanceOf(InsertStmt::class, $ast);
+ self::assertNotNull($ast->getOnConflictClause());
+ }
+
+ public function test_insert_returning() : void
+ {
+ $query = InsertBuilder::create()
+ ->into('users')
+ ->columns('name', 'email')
+ ->values(Literal::string('John'), Literal::string('john@example.com'))
+ ->returning(Column::name('id'), Column::name('created_at'));
+
+ $ast = $query->toAst();
+
+ self::assertInstanceOf(InsertStmt::class, $ast);
+ $returning = $ast->getReturningList();
+ self::assertNotNull($returning);
+ self::assertCount(2, $returning);
+ }
+
+ public function test_insert_returning_all() : void
+ {
+ $query = InsertBuilder::create()
+ ->into('users')
+ ->columns('name', 'email')
+ ->values(Literal::string('John'), Literal::string('john@example.com'))
+ ->returningAll();
+
+ $ast = $query->toAst();
+
+ self::assertInstanceOf(InsertStmt::class, $ast);
+ $returning = $ast->getReturningList();
+ self::assertNotNull($returning);
+ self::assertCount(1, $returning);
+ }
+
+ public function test_insert_with_alias() : void
+ {
+ $query = InsertBuilder::create()
+ ->into('users', 'u')
+ ->columns('name')
+ ->values(Literal::string('John'));
+
+ $ast = $query->toAst();
+
+ $relation = $ast->getRelation();
+ self::assertNotNull($relation);
+ self::assertSame('users', $relation->getRelname());
+
+ $alias = $relation->getAlias();
+ self::assertNotNull($alias);
+ self::assertSame('u', $alias->getAliasname());
+ }
+
+ public function test_insert_with_function_values() : void
+ {
+ $query = InsertBuilder::create()
+ ->into('users')
+ ->columns('name', 'email', 'created_at')
+ ->values(
+ Literal::string('John'),
+ Literal::string('john@example.com'),
+ new FunctionCall(['now'])
+ );
+
+ $ast = $query->toAst();
+
+ self::assertInstanceOf(InsertStmt::class, $ast);
+ }
+
+ public function test_insert_with_function_values_deparsed_output() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $insert = InsertBuilder::create()
+ ->into('logs')
+ ->columns('message', 'created_at')
+ ->values(Literal::string('test message'), new FunctionCall(['now']));
+
+ $deparsed = $this->deparse($insert->toAst());
+ self::assertSame("INSERT INTO logs (message, created_at) VALUES ('test message', now())", $deparsed);
+ }
+
+ public function test_insert_with_on_conflict_do_nothing_deparsed_output() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $insert = InsertBuilder::create()
+ ->into('users')
+ ->columns('email', 'name')
+ ->values(Literal::string('john@example.com'), Literal::string('John'))
+ ->onConflictDoNothing(ConflictTarget::columns(['email']));
+
+ $deparsed = $this->deparse($insert->toAst());
+ 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_update_deparsed_output() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $insert = InsertBuilder::create()
+ ->into('users')
+ ->columns('email', 'name')
+ ->values(Literal::string('john@example.com'), Literal::string('John'))
+ ->onConflictDoUpdate(
+ ConflictTarget::columns(['email']),
+ ['name' => Column::tableColumn('excluded', 'name')]
+ );
+
+ $deparsed = $this->deparse($insert->toAst());
+ 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_returning_deparsed_output() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $insert = InsertBuilder::create()
+ ->into('users')
+ ->columns('name')
+ ->values(Literal::string('John'))
+ ->returning(Column::name('id'));
+
+ $deparsed = $this->deparse($insert->toAst());
+ self::assertSame("INSERT INTO users (name) VALUES ('John') RETURNING id", $deparsed);
+ }
+
+ public function test_insert_with_schema() : void
+ {
+ $query = InsertBuilder::create()
+ ->into('public.users')
+ ->columns('name')
+ ->values(Literal::string('John'));
+
+ $ast = $query->toAst();
+
+ $relation = $ast->getRelation();
+ self::assertNotNull($relation);
+ self::assertSame('users', $relation->getRelname());
+ self::assertSame('public', $relation->getSchemaname());
+ }
+
+ public function test_insert_with_schema_deparsed_output() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $insert = InsertBuilder::create()
+ ->into('public.users')
+ ->columns('name')
+ ->values(Literal::string('John'));
+
+ $deparsed = $this->deparse($insert->toAst());
+ self::assertSame("INSERT INTO public.users (name) VALUES ('John')", $deparsed);
+ }
+
+ public function test_insert_without_columns() : void
+ {
+ $query = InsertBuilder::create()
+ ->into('users')
+ ->defaultValues();
+
+ $ast = $query->toAst();
+
+ self::assertInstanceOf(InsertStmt::class, $ast);
+ $cols = $ast->getCols();
+ self::assertTrue($cols === null || \count($cols) === 0);
+ }
+
+ public function test_insert_without_explicit_columns() : void
+ {
+ $query = InsertBuilder::create()
+ ->into('users')
+ ->values(Literal::string('John'), Literal::string('john@example.com'));
+
+ $ast = $query->toAst();
+
+ self::assertInstanceOf(InsertStmt::class, $ast);
+ $cols = $ast->getCols();
+ self::assertTrue($cols === null || \count($cols) === 0);
+ self::assertNotNull($ast->getSelectStmt());
+ }
+
+ public function test_round_trip_default_values() : void
+ {
+ $original = InsertBuilder::create()
+ ->into('logs')
+ ->defaultValues();
+
+ $ast = $original->toAst();
+ $node = new Node();
+ $node->setInsertStmt($ast);
+ $restored = InsertBuilder::fromAst($node);
+
+ $restoredAst = $restored->toAst();
+
+ $relation = $restoredAst->getRelation();
+ self::assertNotNull($relation);
+ self::assertSame('logs', $relation->getRelname());
+
+ // DEFAULT VALUES has no selectStmt - this is correct PostgreSQL AST
+ self::assertNull($restoredAst->getSelectStmt());
+ }
+
+ public function test_round_trip_multiple_rows() : void
+ {
+ $original = InsertBuilder::create()
+ ->into('users')
+ ->columns('name', 'email')
+ ->values(Literal::string('John'), Literal::string('john@example.com'))
+ ->values(Literal::string('Jane'), Literal::string('jane@example.com'))
+ ->values(Literal::string('Bob'), Literal::string('bob@example.com'));
+
+ $ast = $original->toAst();
+ $node = new Node();
+ $node->setInsertStmt($ast);
+ $restored = InsertBuilder::fromAst($node);
+
+ $restoredAst = $restored->toAst();
+
+ $selectStmt = $restoredAst->getSelectStmt()?->getSelectStmt();
+ self::assertNotNull($selectStmt);
+ $valuesLists = $selectStmt->getValuesLists();
+ self::assertNotNull($valuesLists);
+ self::assertCount(3, $valuesLists);
+ }
+
+ public function test_round_trip_returning_all() : void
+ {
+ $original = InsertBuilder::create()
+ ->into('users')
+ ->columns('name')
+ ->values(Literal::string('John'))
+ ->returningAll();
+
+ $ast = $original->toAst();
+ $node = new Node();
+ $node->setInsertStmt($ast);
+ $restored = InsertBuilder::fromAst($node);
+
+ $restoredAst = $restored->toAst();
+
+ $returning = $restoredAst->getReturningList();
+ self::assertNotNull($returning);
+ self::assertCount(1, $returning);
+ }
+
+ public function test_round_trip_simple() : void
+ {
+ $original = InsertBuilder::create()
+ ->into('users')
+ ->columns('name', 'email')
+ ->values(Literal::string('John'), Literal::string('john@example.com'));
+
+ $ast = $original->toAst();
+ $node = new Node();
+ $node->setInsertStmt($ast);
+ $restored = InsertBuilder::fromAst($node);
+
+ $restoredAst = $restored->toAst();
+
+ $originalRelation = $ast->getRelation();
+ self::assertNotNull($originalRelation);
+
+ $restoredRelation = $restoredAst->getRelation();
+ self::assertNotNull($restoredRelation);
+
+ self::assertSame($originalRelation->getRelname(), $restoredRelation->getRelname());
+ self::assertCount(2, $restoredAst->getCols());
+ }
+
+ public function test_round_trip_with_on_conflict() : void
+ {
+ $original = InsertBuilder::create()
+ ->into('users')
+ ->columns('email', 'name')
+ ->values(Literal::string('john@example.com'), Literal::string('John'))
+ ->onConflictDoUpdate(
+ ConflictTarget::columns(['email']),
+ ['name' => Column::name('excluded.name')]
+ );
+
+ $ast = $original->toAst();
+ $node = new Node();
+ $node->setInsertStmt($ast);
+ $restored = InsertBuilder::fromAst($node);
+
+ $restoredAst = $restored->toAst();
+
+ self::assertNotNull($restoredAst->getOnConflictClause());
+ self::assertNotNull($restoredAst->getOnConflictClause()->getTargetList());
+ }
+
+ public function test_round_trip_with_returning() : void
+ {
+ $original = InsertBuilder::create()
+ ->into('users')
+ ->columns('name', 'email')
+ ->values(Literal::string('John'), Literal::string('john@example.com'))
+ ->returning(Column::name('id'));
+
+ $ast = $original->toAst();
+ $node = new Node();
+ $node->setInsertStmt($ast);
+ $restored = InsertBuilder::fromAst($node);
+
+ $restoredAst = $restored->toAst();
+
+ self::assertNotNull($restoredAst->getReturningList());
+ self::assertCount(1, $restoredAst->getReturningList());
+ }
+
+ public function test_round_trip_with_schema_and_alias() : void
+ {
+ $original = InsertBuilder::create()
+ ->into('public.users', 'u')
+ ->columns('name')
+ ->values(Literal::string('John'));
+
+ $ast = $original->toAst();
+ $node = new Node();
+ $node->setInsertStmt($ast);
+ $restored = InsertBuilder::fromAst($node);
+
+ $restoredAst = $restored->toAst();
+
+ $relation = $restoredAst->getRelation();
+ self::assertNotNull($relation);
+ self::assertSame('users', $relation->getRelname());
+ self::assertSame('public', $relation->getSchemaname());
+
+ $alias = $relation->getAlias();
+ self::assertNotNull($alias);
+ self::assertSame('u', $alias->getAliasname());
+ }
+
+ public function test_round_trip_with_where_clause() : void
+ {
+ $original = InsertBuilder::create()
+ ->into('users')
+ ->columns('email', 'name')
+ ->values(Literal::string('john@example.com'), Literal::string('John'))
+ ->onConflictDoUpdate(
+ ConflictTarget::columns(['email']),
+ ['name' => Column::name('excluded.name')]
+ )
+ ->where(new IsNull(Column::name('deleted_at')));
+
+ $ast = $original->toAst();
+ $node = new Node();
+ $node->setInsertStmt($ast);
+ $restored = InsertBuilder::fromAst($node);
+
+ $restoredAst = $restored->toAst();
+
+ self::assertNotNull($restoredAst->getOnConflictClause());
+ self::assertNotNull($restoredAst->getOnConflictClause()->getWhereClause());
+ }
+
+ public function test_simple_insert() : void
+ {
+ $query = InsertBuilder::create()
+ ->into('users')
+ ->columns('name', 'email')
+ ->values(Literal::string('John'), Literal::string('john@example.com'));
+
+ $ast = $query->toAst();
+
+ self::assertInstanceOf(InsertStmt::class, $ast);
+ self::assertNotNull($ast->getRelation());
+ self::assertSame('users', $ast->getRelation()->getRelname());
+ self::assertNotNull($ast->getCols());
+ self::assertCount(2, $ast->getCols());
+ self::assertNotNull($ast->getSelectStmt());
+ }
+
+ public function test_simple_insert_deparsed_output() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $insert = InsertBuilder::create()
+ ->into('users')
+ ->columns('name', 'email')
+ ->values(Literal::string('John'), Literal::string('john@example.com'));
+
+ $deparsed = $this->deparse($insert->toAst());
+ self::assertSame("INSERT INTO users (name, email) VALUES ('John', 'john@example.com')", $deparsed);
+ }
+
+ private function deparse(InsertStmt $insertStmt) : string
+ {
+ $parser = new Parser();
+ $node = new Node();
+ $node->setInsertStmt($insertStmt);
+ $rawStmt = new RawStmt();
+ $rawStmt->setStmt($node);
+ $parsed = $parser->parse('INSERT INTO dummy VALUES (1)');
+ $parseResult = $parsed->raw();
+ $parseResult->setStmts([$rawStmt]);
+
+ return (new ParsedQuery($parseResult))->deparse();
+ }
+}
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
new file mode 100644
index 000000000..ffd67f240
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Merge/MergeBuilderTest.php
@@ -0,0 +1,629 @@
+into('users')
+ ->using('new_users', 'n')
+ ->on(new Comparison(Column::tableColumn('users', 'id'), ComparisonOperator::EQ, Column::tableColumn('n', 'id')))
+ ->whenMatched()
+ ->thenUpdate(['name' => Column::tableColumn('n', 'name')]);
+
+ $ast = $query->toAst();
+ self::assertInstanceOf(MergeStmt::class, $ast);
+ }
+
+ public function test_immutability_into() : void
+ {
+ $original = MergeBuilder::create();
+ $modified = $original->into('users');
+
+ self::assertNotSame($original, $modified);
+ }
+
+ public function test_immutability_on() : void
+ {
+ $original = MergeBuilder::create()->into('users')->using('source', 's');
+ $modified = $original->on(new Comparison(Column::name('id'), ComparisonOperator::EQ, Column::name('id')));
+
+ self::assertNotSame($original, $modified);
+ }
+
+ public function test_immutability_using() : void
+ {
+ $original = MergeBuilder::create()->into('users');
+ $modified = $original->using('source', 's');
+
+ self::assertNotSame($original, $modified);
+ }
+
+ public function test_immutability_when_clause() : void
+ {
+ $builder = MergeBuilder::create()
+ ->into('users')
+ ->using('source', 's')
+ ->on(new Comparison(Column::name('id'), ComparisonOperator::EQ, Column::name('id')));
+
+ $original = $builder->whenMatched()->thenUpdate(['name' => Literal::string('test')]);
+ $modified = $original->whenNotMatched()->thenDoNothing();
+
+ self::assertNotSame($original, $modified);
+ }
+
+ public function test_merge_action_type_enum_values() : void
+ {
+ self::assertSame(5, MergeActionType::DELETE->value);
+ self::assertSame(8, MergeActionType::DO_NOTHING->value);
+ self::assertSame(4, MergeActionType::INSERT->value);
+ self::assertSame(3, MergeActionType::UPDATE->value);
+ }
+
+ public function test_merge_deparsed_simple_update() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $merge = MergeBuilder::create()
+ ->into('target')
+ ->using('source', 's')
+ ->on(new Comparison(Column::tableColumn('target', 'id'), ComparisonOperator::EQ, Column::tableColumn('s', 'id')))
+ ->whenMatched()
+ ->thenUpdate(['value' => Column::tableColumn('s', 'value')]);
+
+ $deparsed = $this->deparse($merge->toAst());
+ self::assertSame('MERGE INTO target USING source s ON target.id = s.id WHEN MATCHED THEN UPDATE SET value = s.value', $deparsed);
+ }
+
+ public function test_merge_deparsed_with_alias() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $merge = MergeBuilder::create()
+ ->into('target', 't')
+ ->using('source', 's')
+ ->on(new Comparison(Column::tableColumn('t', 'id'), ComparisonOperator::EQ, Column::tableColumn('s', 'id')))
+ ->whenMatched()
+ ->thenDelete();
+
+ $deparsed = $this->deparse($merge->toAst());
+ self::assertSame('MERGE INTO target t USING source s ON t.id = s.id WHEN MATCHED THEN DELETE', $deparsed);
+ }
+
+ public function test_merge_into_parses_schema_and_table() : void
+ {
+ $query = MergeBuilder::create()
+ ->into('myschema.users', 'u')
+ ->using('source', 's')
+ ->on(new Comparison(Column::tableColumn('u', 'id'), ComparisonOperator::EQ, Column::tableColumn('s', 'id')))
+ ->whenMatched()
+ ->thenDoNothing();
+
+ $ast = $query->toAst();
+
+ $relation = $ast->getRelation();
+ self::assertNotNull($relation);
+ self::assertSame('users', $relation->getRelname());
+ self::assertSame('myschema', $relation->getSchemaname());
+
+ $alias = $relation->getAlias();
+ self::assertNotNull($alias);
+ self::assertSame('u', $alias->getAliasname());
+ }
+
+ public function test_merge_match_kind_enum_values() : void
+ {
+ self::assertSame(1, MergeMatchKind::MATCHED->value);
+ self::assertSame(2, MergeMatchKind::NOT_MATCHED_BY_SOURCE->value);
+ self::assertSame(3, MergeMatchKind::NOT_MATCHED_BY_TARGET->value);
+ }
+
+ public function test_merge_when_clause_data_structure() : void
+ {
+ $condition = new Comparison(Column::name('id'), ComparisonOperator::EQ, Literal::int(1));
+ $assignments = ['name' => Literal::string('test')];
+ $columns = ['id', 'name'];
+ $values = [Literal::int(1), Literal::string('test')];
+
+ $data = new MergeWhenClauseData(
+ MergeMatchKind::MATCHED,
+ MergeActionType::UPDATE,
+ $condition,
+ $assignments,
+ $columns,
+ $values
+ );
+
+ self::assertSame(MergeMatchKind::MATCHED, $data->matchKind);
+ self::assertSame(MergeActionType::UPDATE, $data->actionType);
+ self::assertSame($condition, $data->condition);
+ self::assertSame($assignments, $data->assignments);
+ self::assertSame($columns, $data->insertColumns);
+ self::assertSame($values, $data->insertValues);
+ }
+
+ public function test_merge_when_matched_delete() : void
+ {
+ $query = MergeBuilder::create()
+ ->into('target')
+ ->using('source', 's')
+ ->on(new Comparison(Column::name('id'), ComparisonOperator::EQ, Column::name('id')))
+ ->whenMatched()
+ ->thenDelete();
+
+ $ast = $query->toAst();
+
+ $whenClauses = $ast->getMergeWhenClauses();
+ self::assertCount(1, $whenClauses);
+
+ $whenClause = $whenClauses[0]->getMergeWhenClause();
+ self::assertNotNull($whenClause);
+ self::assertSame(MergeMatchKind::MATCHED->value, $whenClause->getMatchKind());
+ self::assertSame(MergeActionType::DELETE->value, $whenClause->getCommandType());
+ }
+
+ public function test_merge_when_matched_do_nothing() : void
+ {
+ $query = MergeBuilder::create()
+ ->into('target')
+ ->using('source', 's')
+ ->on(new Comparison(Column::name('id'), ComparisonOperator::EQ, Column::name('id')))
+ ->whenMatched()
+ ->thenDoNothing();
+
+ $ast = $query->toAst();
+
+ $whenClauses = $ast->getMergeWhenClauses();
+ self::assertCount(1, $whenClauses);
+
+ $whenClause = $whenClauses[0]->getMergeWhenClause();
+ self::assertNotNull($whenClause);
+ self::assertSame(MergeMatchKind::MATCHED->value, $whenClause->getMatchKind());
+ self::assertSame(MergeActionType::DO_NOTHING->value, $whenClause->getCommandType());
+ }
+
+ public function test_merge_when_matched_returns_correct_instance() : void
+ {
+ $builder = MergeBuilder::create()
+ ->into('users')
+ ->using('source', 's')
+ ->on(new Comparison(Column::name('id'), ComparisonOperator::EQ, Column::name('id')));
+
+ $whenMatched = $builder->whenMatched();
+ self::assertInstanceOf(MergeWhenMatched::class, $whenMatched);
+ }
+
+ public function test_merge_when_matched_update() : void
+ {
+ $query = MergeBuilder::create()
+ ->into('target')
+ ->using('source', 's')
+ ->on(new Comparison(Column::name('id'), ComparisonOperator::EQ, Column::name('id')))
+ ->whenMatched()
+ ->thenUpdate([
+ 'name' => Column::tableColumn('s', 'name'),
+ 'value' => Column::tableColumn('s', 'value'),
+ ]);
+
+ $ast = $query->toAst();
+
+ $whenClauses = $ast->getMergeWhenClauses();
+ self::assertCount(1, $whenClauses);
+
+ $whenClause = $whenClauses[0]->getMergeWhenClause();
+ self::assertNotNull($whenClause);
+ self::assertSame(MergeMatchKind::MATCHED->value, $whenClause->getMatchKind());
+ self::assertSame(MergeActionType::UPDATE->value, $whenClause->getCommandType());
+
+ $targetList = $whenClause->getTargetList();
+ self::assertCount(2, $targetList);
+ }
+
+ public function test_merge_when_matched_with_condition() : void
+ {
+ $query = MergeBuilder::create()
+ ->into('target')
+ ->using('source', 's')
+ ->on(new Comparison(Column::name('id'), ComparisonOperator::EQ, Column::name('id')))
+ ->whenMatchedAnd(new Comparison(Column::tableColumn('s', 'status'), ComparisonOperator::EQ, Literal::string('active')))
+ ->thenUpdate(['status' => Column::tableColumn('s', 'status')]);
+
+ $ast = $query->toAst();
+
+ $whenClauses = $ast->getMergeWhenClauses();
+ self::assertCount(1, $whenClauses);
+
+ $whenClause = $whenClauses[0]->getMergeWhenClause();
+ self::assertNotNull($whenClause);
+ self::assertTrue($whenClause->hasCondition());
+ self::assertNotNull($whenClause->getCondition());
+ }
+
+ public function test_merge_when_not_matched_by_source() : void
+ {
+ $query = MergeBuilder::create()
+ ->into('target')
+ ->using('source', 's')
+ ->on(new Comparison(Column::name('id'), ComparisonOperator::EQ, Column::name('id')))
+ ->whenNotMatchedBySource()
+ ->thenDelete();
+
+ $ast = $query->toAst();
+
+ $whenClauses = $ast->getMergeWhenClauses();
+ self::assertCount(1, $whenClauses);
+
+ $whenClause = $whenClauses[0]->getMergeWhenClause();
+ self::assertNotNull($whenClause);
+ self::assertSame(MergeMatchKind::NOT_MATCHED_BY_SOURCE->value, $whenClause->getMatchKind());
+ self::assertSame(MergeActionType::DELETE->value, $whenClause->getCommandType());
+ }
+
+ public function test_merge_when_not_matched_by_source_with_condition() : void
+ {
+ $query = MergeBuilder::create()
+ ->into('target')
+ ->using('source', 's')
+ ->on(new Comparison(Column::name('id'), ComparisonOperator::EQ, Column::name('id')))
+ ->whenNotMatchedBySourceAnd(new Comparison(Column::tableColumn('target', 'deleted'), ComparisonOperator::EQ, Literal::bool(false)))
+ ->thenUpdate(['deleted' => Literal::bool(true)]);
+
+ $ast = $query->toAst();
+
+ $whenClauses = $ast->getMergeWhenClauses();
+ self::assertCount(1, $whenClauses);
+
+ $whenClause = $whenClauses[0]->getMergeWhenClause();
+ self::assertNotNull($whenClause);
+ self::assertSame(MergeMatchKind::NOT_MATCHED_BY_SOURCE->value, $whenClause->getMatchKind());
+ self::assertTrue($whenClause->hasCondition());
+ }
+
+ public function test_merge_when_not_matched_do_nothing() : void
+ {
+ $query = MergeBuilder::create()
+ ->into('target')
+ ->using('source', 's')
+ ->on(new Comparison(Column::name('id'), ComparisonOperator::EQ, Column::name('id')))
+ ->whenNotMatched()
+ ->thenDoNothing();
+
+ $ast = $query->toAst();
+
+ $whenClauses = $ast->getMergeWhenClauses();
+ self::assertCount(1, $whenClauses);
+
+ $whenClause = $whenClauses[0]->getMergeWhenClause();
+ self::assertNotNull($whenClause);
+ self::assertSame(MergeMatchKind::NOT_MATCHED_BY_TARGET->value, $whenClause->getMatchKind());
+ self::assertSame(MergeActionType::DO_NOTHING->value, $whenClause->getCommandType());
+ }
+
+ public function test_merge_when_not_matched_insert() : void
+ {
+ $query = MergeBuilder::create()
+ ->into('target')
+ ->using('source', 's')
+ ->on(new Comparison(Column::name('id'), ComparisonOperator::EQ, Column::name('id')))
+ ->whenNotMatched()
+ ->thenInsert(
+ ['id', 'name', 'value'],
+ [Column::tableColumn('s', 'id'), Column::tableColumn('s', 'name'), Column::tableColumn('s', 'value')]
+ );
+
+ $ast = $query->toAst();
+
+ $whenClauses = $ast->getMergeWhenClauses();
+ self::assertCount(1, $whenClauses);
+
+ $whenClause = $whenClauses[0]->getMergeWhenClause();
+ self::assertNotNull($whenClause);
+ self::assertSame(MergeMatchKind::NOT_MATCHED_BY_TARGET->value, $whenClause->getMatchKind());
+ self::assertSame(MergeActionType::INSERT->value, $whenClause->getCommandType());
+
+ $targetList = $whenClause->getTargetList();
+ self::assertCount(3, $targetList);
+
+ $values = $whenClause->getValues();
+ self::assertCount(3, $values);
+ }
+
+ public function test_merge_when_not_matched_insert_values() : void
+ {
+ $query = MergeBuilder::create()
+ ->into('target')
+ ->using('source', 's')
+ ->on(new Comparison(Column::name('id'), ComparisonOperator::EQ, Column::name('id')))
+ ->whenNotMatched()
+ ->thenInsertValues([
+ 'id' => Column::tableColumn('s', 'id'),
+ 'name' => Column::tableColumn('s', 'name'),
+ ]);
+
+ $ast = $query->toAst();
+
+ $whenClauses = $ast->getMergeWhenClauses();
+ self::assertCount(1, $whenClauses);
+
+ $whenClause = $whenClauses[0]->getMergeWhenClause();
+ self::assertNotNull($whenClause);
+ self::assertSame(MergeActionType::INSERT->value, $whenClause->getCommandType());
+
+ $targetList = $whenClause->getTargetList();
+ self::assertCount(2, $targetList);
+
+ $values = $whenClause->getValues();
+ self::assertCount(2, $values);
+ }
+
+ public function test_merge_when_not_matched_returns_correct_instance() : void
+ {
+ $builder = MergeBuilder::create()
+ ->into('users')
+ ->using('source', 's')
+ ->on(new Comparison(Column::name('id'), ComparisonOperator::EQ, Column::name('id')));
+
+ $whenNotMatched = $builder->whenNotMatched();
+ self::assertInstanceOf(MergeWhenNotMatched::class, $whenNotMatched);
+ }
+
+ public function test_merge_when_not_matched_with_condition() : void
+ {
+ $query = MergeBuilder::create()
+ ->into('target')
+ ->using('source', 's')
+ ->on(new Comparison(Column::name('id'), ComparisonOperator::EQ, Column::name('id')))
+ ->whenNotMatchedAnd(new Comparison(Column::tableColumn('s', 'type'), ComparisonOperator::EQ, Literal::string('new')))
+ ->thenInsertValues(['id' => Column::tableColumn('s', 'id')]);
+
+ $ast = $query->toAst();
+
+ $whenClauses = $ast->getMergeWhenClauses();
+ self::assertCount(1, $whenClauses);
+
+ $whenClause = $whenClauses[0]->getMergeWhenClause();
+ self::assertNotNull($whenClause);
+ self::assertTrue($whenClause->hasCondition());
+ }
+
+ public function test_merge_with_multiple_when_clauses() : void
+ {
+ $query = MergeBuilder::create()
+ ->into('target')
+ ->using('source', 's')
+ ->on(new Comparison(Column::name('id'), ComparisonOperator::EQ, Column::name('id')))
+ ->whenMatched()
+ ->thenUpdate(['value' => Column::tableColumn('s', 'value')])
+ ->whenNotMatched()
+ ->thenInsertValues(['id' => Column::tableColumn('s', 'id'), 'value' => Column::tableColumn('s', 'value')]);
+
+ $ast = $query->toAst();
+
+ $whenClauses = $ast->getMergeWhenClauses();
+ self::assertCount(2, $whenClauses);
+
+ $firstClause = $whenClauses[0]->getMergeWhenClause();
+ self::assertNotNull($firstClause);
+ self::assertSame(MergeMatchKind::MATCHED->value, $firstClause->getMatchKind());
+ self::assertSame(MergeActionType::UPDATE->value, $firstClause->getCommandType());
+
+ $secondClause = $whenClauses[1]->getMergeWhenClause();
+ self::assertNotNull($secondClause);
+ self::assertSame(MergeMatchKind::NOT_MATCHED_BY_TARGET->value, $secondClause->getMatchKind());
+ self::assertSame(MergeActionType::INSERT->value, $secondClause->getCommandType());
+ }
+
+ public function test_merge_with_source_subquery() : void
+ {
+ $subquery = SelectBuilder::create()
+ ->select(Column::name('id'), Column::name('name'))
+ ->from(new Table('raw_data'));
+
+ $query = MergeBuilder::create()
+ ->into('target')
+ ->using($subquery, 'src')
+ ->on(new Comparison(Column::name('id'), ComparisonOperator::EQ, Column::name('id')))
+ ->whenMatched()
+ ->thenDoNothing();
+
+ $ast = $query->toAst();
+
+ $sourceRelation = $ast->getSourceRelation();
+ self::assertNotNull($sourceRelation);
+ self::assertTrue($sourceRelation->hasRangeSubselect());
+
+ $rangeSubselect = $sourceRelation->getRangeSubselect();
+ self::assertNotNull($rangeSubselect);
+ self::assertTrue($rangeSubselect->hasSubquery());
+
+ $alias = $rangeSubselect->getAlias();
+ self::assertNotNull($alias);
+ self::assertSame('src', $alias->getAliasname());
+ }
+
+ public function test_merge_with_source_table() : void
+ {
+ $query = MergeBuilder::create()
+ ->into('target')
+ ->using('source_table', 'src')
+ ->on(new Comparison(Column::name('id'), ComparisonOperator::EQ, Column::name('id')))
+ ->whenMatched()
+ ->thenDoNothing();
+
+ $ast = $query->toAst();
+
+ $sourceRelation = $ast->getSourceRelation();
+ self::assertNotNull($sourceRelation);
+ self::assertTrue($sourceRelation->hasRangeVar());
+
+ $rangeVar = $sourceRelation->getRangeVar();
+ self::assertNotNull($rangeVar);
+ self::assertSame('source_table', $rangeVar->getRelname());
+
+ $alias = $rangeVar->getAlias();
+ self::assertNotNull($alias);
+ self::assertSame('src', $alias->getAliasname());
+ }
+
+ public function test_merge_with_table_alias() : void
+ {
+ $query = MergeBuilder::create()
+ ->into('users', 'u')
+ ->using('source', 's')
+ ->on(new Comparison(Column::tableColumn('u', 'id'), ComparisonOperator::EQ, Column::tableColumn('s', 'id')))
+ ->whenMatched()
+ ->thenDoNothing();
+
+ $ast = $query->toAst();
+
+ $relation = $ast->getRelation();
+ self::assertNotNull($relation);
+ self::assertSame('users', $relation->getRelname());
+
+ $alias = $relation->getAlias();
+ self::assertNotNull($alias);
+ self::assertSame('u', $alias->getAliasname());
+ }
+
+ public function test_merge_with_with_clause() : void
+ {
+ $selectStmt = new SelectStmt();
+ $selectNode = new Node();
+ $selectNode->setSelectStmt($selectStmt);
+
+ $cte = new CTE('staged_data', $selectNode);
+ $withClause = new WithClause([$cte]);
+
+ $query = MergeBuilder::with($withClause)
+ ->into('target')
+ ->using('staged_data', 's')
+ ->on(new Comparison(Column::name('id'), ComparisonOperator::EQ, Column::name('id')))
+ ->whenMatched()
+ ->thenUpdate(['name' => Column::tableColumn('s', 'name')]);
+
+ $ast = $query->toAst();
+
+ self::assertTrue($ast->hasWithClause());
+ $withClauseProto = $ast->getWithClause();
+ self::assertNotNull($withClauseProto);
+
+ $ctes = $withClauseProto->getCtes();
+ self::assertNotNull($ctes);
+ self::assertCount(1, $ctes);
+
+ $firstCte = $ctes[0]->getCommonTableExpr();
+ self::assertNotNull($firstCte);
+ self::assertSame('staged_data', $firstCte->getCtename());
+ }
+
+ public function test_merge_without_table_alias() : void
+ {
+ $query = MergeBuilder::create()
+ ->into('users')
+ ->using('source', 's')
+ ->on(new Comparison(Column::tableColumn('users', 'id'), ComparisonOperator::EQ, Column::tableColumn('s', 'id')))
+ ->whenMatched()
+ ->thenDoNothing();
+
+ $ast = $query->toAst();
+
+ $relation = $ast->getRelation();
+ self::assertNotNull($relation);
+ self::assertSame('users', $relation->getRelname());
+ self::assertFalse($relation->hasAlias());
+ }
+
+ public function test_to_ast_without_join_condition_throws_exception() : void
+ {
+ $this->expectException(InvalidExpressionException::class);
+
+ $builder = MergeBuilder::create()
+ ->into('users')
+ ->using('source', 's');
+
+ \assert($builder instanceof MergeFinalStep);
+ $builder->toAst();
+ }
+
+ public function test_to_ast_without_source_alias_throws_exception() : void
+ {
+ $this->expectException(InvalidExpressionException::class);
+
+ MergeBuilder::create()
+ ->into('users')
+ ->using('source', '')
+ ->on(new Comparison(Column::name('id'), ComparisonOperator::EQ, Column::name('id')))
+ ->whenMatched()
+ ->thenDoNothing()
+ ->toAst();
+ }
+
+ public function test_to_ast_without_source_throws_exception() : void
+ {
+ $this->expectException(InvalidExpressionException::class);
+
+ $builder = MergeBuilder::create()->into('users');
+ \assert($builder instanceof MergeFinalStep);
+ $builder->toAst();
+ }
+
+ public function test_to_ast_without_table_throws_exception() : void
+ {
+ $this->expectException(InvalidExpressionException::class);
+
+ $builder = MergeBuilder::create();
+ \assert($builder instanceof MergeFinalStep);
+ $builder->toAst();
+ }
+
+ public function test_to_ast_without_when_clauses_throws_exception() : void
+ {
+ $this->expectException(InvalidExpressionException::class);
+
+ $builder = MergeBuilder::create()
+ ->into('users')
+ ->using('source', 's')
+ ->on(new Comparison(Column::name('id'), ComparisonOperator::EQ, Column::name('id')));
+
+ $builder->toAst();
+ }
+
+ private function deparse(MergeStmt $mergeStmt) : string
+ {
+ $parser = new Parser();
+ $node = new Node();
+ $node->setMergeStmt($mergeStmt);
+ $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/Unit/QueryBuilder/QualifiedIdentifierTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/QualifiedIdentifierTest.php
new file mode 100644
index 000000000..6da01199f
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/QualifiedIdentifierTest.php
@@ -0,0 +1,130 @@
+parts());
+ self::assertSame('users', $identifier->name());
+ self::assertSame('public', $identifier->schema());
+ }
+
+ public function test_parse_both_quoted() : void
+ {
+ $identifier = QualifiedIdentifier::parse('"my.schema"."my.table"');
+
+ self::assertSame(['my.schema', 'my.table'], $identifier->parts());
+ self::assertSame('my.table', $identifier->name());
+ self::assertSame('my.schema', $identifier->schema());
+ }
+
+ public function test_parse_empty_string() : void
+ {
+ $identifier = QualifiedIdentifier::parse('');
+
+ self::assertSame([''], $identifier->parts());
+ self::assertSame('', $identifier->name());
+ }
+
+ public function test_parse_identifier_with_underscores() : void
+ {
+ $identifier = QualifiedIdentifier::parse('my_schema.my_table');
+
+ self::assertSame(['my_schema', 'my_table'], $identifier->parts());
+ }
+
+ public function test_parse_quoted_identifier_with_dots() : void
+ {
+ $identifier = QualifiedIdentifier::parse('"my.table.with.dots"');
+
+ self::assertSame(['my.table.with.dots'], $identifier->parts());
+ self::assertSame('my.table.with.dots', $identifier->name());
+ self::assertNull($identifier->schema());
+ self::assertFalse($identifier->hasSchema());
+ }
+
+ public function test_parse_quoted_schema_with_name() : void
+ {
+ $identifier = QualifiedIdentifier::parse('"my.schema".users');
+
+ self::assertSame(['my.schema', 'users'], $identifier->parts());
+ self::assertSame('users', $identifier->name());
+ self::assertSame('my.schema', $identifier->schema());
+ }
+
+ public function test_parse_regular_identifier_not_quoted() : void
+ {
+ $identifier = QualifiedIdentifier::parse('simple_table');
+
+ self::assertSame(['simple_table'], $identifier->parts());
+ }
+
+ public function test_parse_schema_qualified_name() : void
+ {
+ $identifier = QualifiedIdentifier::parse('public.users');
+
+ self::assertSame(['public', 'users'], $identifier->parts());
+ self::assertSame('users', $identifier->name());
+ self::assertSame('public', $identifier->schema());
+ self::assertTrue($identifier->hasSchema());
+ self::assertSame(2, $identifier->count());
+ }
+
+ public function test_parse_schema_with_quoted_name() : void
+ {
+ $identifier = QualifiedIdentifier::parse('public."my.table"');
+
+ self::assertSame(['public', 'my.table'], $identifier->parts());
+ self::assertSame('my.table', $identifier->name());
+ self::assertSame('public', $identifier->schema());
+ self::assertTrue($identifier->hasSchema());
+ }
+
+ public function test_parse_simple_name() : void
+ {
+ $identifier = QualifiedIdentifier::parse('users');
+
+ self::assertSame(['users'], $identifier->parts());
+ self::assertSame('users', $identifier->name());
+ self::assertNull($identifier->schema());
+ self::assertFalse($identifier->hasSchema());
+ self::assertSame(1, $identifier->count());
+ }
+
+ public function test_parse_three_part_identifier() : void
+ {
+ $identifier = QualifiedIdentifier::parse('myschema.mytable.mycolumn');
+
+ self::assertSame(['myschema', 'mytable', 'mycolumn'], $identifier->parts());
+ self::assertSame('mycolumn', $identifier->name());
+ self::assertSame('myschema', $identifier->schema());
+ self::assertSame('mytable', $identifier->table());
+ self::assertSame('mycolumn', $identifier->column());
+ self::assertSame(3, $identifier->count());
+ }
+
+ public function test_table_for_single_part_identifier() : void
+ {
+ $identifier = QualifiedIdentifier::parse('email');
+
+ self::assertNull($identifier->table());
+ self::assertSame('email', $identifier->column());
+ }
+
+ public function test_table_for_two_part_identifier() : void
+ {
+ $identifier = QualifiedIdentifier::parse('users.email');
+
+ self::assertSame('users', $identifier->table());
+ self::assertSame('email', $identifier->column());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/AlterSequence/AlterSequenceBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/AlterSequence/AlterSequenceBuilderTest.php
new file mode 100644
index 000000000..d60ab7a4c
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/AlterSequence/AlterSequenceBuilderTest.php
@@ -0,0 +1,530 @@
+sequence('user_id_seq')
+ ->asType('smallint');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterSeqStmt::class, $ast);
+
+ $optionFound = false;
+
+ foreach ($ast->getOptions() as $option) {
+ $defElem = $option->getDefElem();
+
+ if ($defElem?->getDefname() === 'as') {
+ $optionFound = true;
+ self::assertTrue($defElem->hasArg());
+ }
+ }
+ self::assertTrue($optionFound);
+ }
+
+ public function test_alter_sequence_cache() : void
+ {
+ $builder = AlterSequenceBuilder::create()
+ ->sequence('user_id_seq')
+ ->cache(20);
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterSeqStmt::class, $ast);
+
+ $optionFound = false;
+
+ foreach ($ast->getOptions() as $option) {
+ $defElem = $option->getDefElem();
+
+ if ($defElem?->getDefname() === 'cache') {
+ $optionFound = true;
+ /** @phpstan-ignore method.nonObject (protobuf PHPDoc incorrectly returns int instead of Integer class) */
+ self::assertSame(20, $defElem->getArg()?->getInteger()?->getIval());
+ }
+ }
+ self::assertTrue($optionFound);
+ }
+
+ public function test_alter_sequence_cycle() : void
+ {
+ $builder = AlterSequenceBuilder::create()
+ ->sequence('user_id_seq')
+ ->cycle();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterSeqStmt::class, $ast);
+
+ $optionFound = false;
+
+ foreach ($ast->getOptions() as $option) {
+ $defElem = $option->getDefElem();
+
+ if ($defElem?->getDefname() === 'cycle') {
+ $optionFound = true;
+ /** @phpstan-ignore method.nonObject (protobuf PHPDoc incorrectly returns bool instead of Boolean class) */
+ self::assertTrue($defElem->getArg()?->getBoolean()?->getBoolval());
+ }
+ }
+ self::assertTrue($optionFound);
+ }
+
+ public function test_alter_sequence_if_exists() : void
+ {
+ $builder = AlterSequenceBuilder::ifExists()
+ ->sequence('user_id_seq')
+ ->incrementBy(10);
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterSeqStmt::class, $ast);
+ self::assertTrue($ast->getMissingOk());
+ }
+
+ public function test_alter_sequence_increment_by() : void
+ {
+ $builder = AlterSequenceBuilder::create()
+ ->sequence('user_id_seq')
+ ->incrementBy(10);
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterSeqStmt::class, $ast);
+ self::assertNotEmpty($ast->getOptions());
+
+ $optionFound = false;
+
+ foreach ($ast->getOptions() as $option) {
+ $defElem = $option->getDefElem();
+
+ if ($defElem?->getDefname() === 'increment') {
+ $optionFound = true;
+ /** @phpstan-ignore method.nonObject (protobuf PHPDoc incorrectly returns int instead of Integer class) */
+ self::assertSame(10, $defElem->getArg()?->getInteger()?->getIval());
+ }
+ }
+ self::assertTrue($optionFound);
+ }
+
+ public function test_alter_sequence_max_value() : void
+ {
+ $builder = AlterSequenceBuilder::create()
+ ->sequence('user_id_seq')
+ ->maxValue(9999999);
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterSeqStmt::class, $ast);
+
+ $optionFound = false;
+
+ foreach ($ast->getOptions() as $option) {
+ $defElem = $option->getDefElem();
+
+ if ($defElem?->getDefname() === 'maxvalue') {
+ $optionFound = true;
+ /** @phpstan-ignore method.nonObject (protobuf PHPDoc incorrectly returns int instead of Integer class) */
+ self::assertSame(9999999, $defElem->getArg()?->getInteger()?->getIval());
+ }
+ }
+ self::assertTrue($optionFound);
+ }
+
+ public function test_alter_sequence_min_value() : void
+ {
+ $builder = AlterSequenceBuilder::create()
+ ->sequence('user_id_seq')
+ ->minValue(1);
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterSeqStmt::class, $ast);
+
+ $optionFound = false;
+
+ foreach ($ast->getOptions() as $option) {
+ $defElem = $option->getDefElem();
+
+ if ($defElem?->getDefname() === 'minvalue') {
+ $optionFound = true;
+ /** @phpstan-ignore method.nonObject (protobuf PHPDoc incorrectly returns int instead of Integer class) */
+ self::assertSame(1, $defElem->getArg()?->getInteger()?->getIval());
+ }
+ }
+ self::assertTrue($optionFound);
+ }
+
+ public function test_alter_sequence_no_cycle() : void
+ {
+ $builder = AlterSequenceBuilder::create()
+ ->sequence('user_id_seq')
+ ->noCycle();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterSeqStmt::class, $ast);
+
+ $optionFound = false;
+
+ foreach ($ast->getOptions() as $option) {
+ $defElem = $option->getDefElem();
+
+ if ($defElem?->getDefname() === 'cycle') {
+ $optionFound = true;
+ /** @phpstan-ignore method.nonObject (protobuf PHPDoc incorrectly returns bool instead of Boolean class) */
+ self::assertFalse($defElem->getArg()?->getBoolean()?->getBoolval());
+ }
+ }
+ self::assertTrue($optionFound);
+ }
+
+ public function test_alter_sequence_no_max_value() : void
+ {
+ $builder = AlterSequenceBuilder::create()
+ ->sequence('user_id_seq')
+ ->noMaxValue();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterSeqStmt::class, $ast);
+
+ $optionFound = false;
+
+ foreach ($ast->getOptions() as $option) {
+ $defElem = $option->getDefElem();
+
+ if ($defElem?->getDefname() === 'maxvalue') {
+ $optionFound = true;
+ self::assertFalse($defElem->hasArg());
+ }
+ }
+ self::assertTrue($optionFound);
+ }
+
+ public function test_alter_sequence_no_min_value() : void
+ {
+ $builder = AlterSequenceBuilder::create()
+ ->sequence('user_id_seq')
+ ->noMinValue();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterSeqStmt::class, $ast);
+
+ $optionFound = false;
+
+ foreach ($ast->getOptions() as $option) {
+ $defElem = $option->getDefElem();
+
+ if ($defElem?->getDefname() === 'minvalue') {
+ $optionFound = true;
+ self::assertFalse($defElem->hasArg());
+ }
+ }
+ self::assertTrue($optionFound);
+ }
+
+ public function test_alter_sequence_owned_by() : void
+ {
+ $builder = AlterSequenceBuilder::create()
+ ->sequence('user_id_seq')
+ ->ownedBy('users', 'id');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterSeqStmt::class, $ast);
+
+ $optionFound = false;
+
+ foreach ($ast->getOptions() as $option) {
+ $defElem = $option->getDefElem();
+
+ if ($defElem?->getDefname() === 'owned_by') {
+ $optionFound = true;
+ $list = $defElem->getArg()?->getList();
+ self::assertNotNull($list);
+ self::assertCount(2, $list->getItems());
+ self::assertSame('users', $list->getItems()[0]->getString()?->getSval());
+ self::assertSame('id', $list->getItems()[1]->getString()?->getSval());
+ }
+ }
+ self::assertTrue($optionFound);
+ }
+
+ public function test_alter_sequence_owned_by_none() : void
+ {
+ $builder = AlterSequenceBuilder::create()
+ ->sequence('user_id_seq')
+ ->ownedByNone();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterSeqStmt::class, $ast);
+
+ $optionFound = false;
+
+ foreach ($ast->getOptions() as $option) {
+ $defElem = $option->getDefElem();
+
+ if ($defElem?->getDefname() === 'owned_by') {
+ $optionFound = true;
+ $list = $defElem->getArg()?->getList();
+ self::assertNotNull($list);
+ self::assertCount(1, $list->getItems());
+ self::assertSame('none', $list->getItems()[0]->getString()?->getSval());
+ }
+ }
+ self::assertTrue($optionFound);
+ }
+
+ public function test_alter_sequence_owner_to() : void
+ {
+ $builder = AlterSequenceBuilder::create()
+ ->sequence('user_id_seq')
+ ->ownerTo('new_owner');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterTableStmt::class, $ast);
+ self::assertSame(ObjectType::OBJECT_SEQUENCE, $ast->getObjtype());
+ self::assertSame('user_id_seq', $ast->getRelation()?->getRelname());
+ self::assertCount(1, $ast->getCmds());
+ self::assertSame(AlterTableType::AT_ChangeOwner, $ast->getCmds()[0]->getAlterTableCmd()?->getSubtype());
+ }
+
+ public function test_alter_sequence_owner_to_if_exists() : void
+ {
+ $builder = AlterSequenceBuilder::ifExists()
+ ->sequence('user_id_seq')
+ ->ownerTo('new_owner');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterTableStmt::class, $ast);
+ self::assertTrue($ast->getMissingOk());
+ }
+
+ public function test_alter_sequence_rename_to() : void
+ {
+ $builder = AlterSequenceBuilder::create()
+ ->sequence('old_seq')
+ ->renameTo('new_seq');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(RenameStmt::class, $ast);
+ self::assertSame(ObjectType::OBJECT_SEQUENCE, $ast->getRenameType());
+ self::assertSame('old_seq', $ast->getRelation()?->getRelname());
+ self::assertSame('new_seq', $ast->getNewname());
+ }
+
+ public function test_alter_sequence_rename_to_if_exists() : void
+ {
+ $builder = AlterSequenceBuilder::ifExists()
+ ->sequence('old_seq')
+ ->renameTo('new_seq');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(RenameStmt::class, $ast);
+ self::assertTrue($ast->getMissingOk());
+ }
+
+ public function test_alter_sequence_restart() : void
+ {
+ $builder = AlterSequenceBuilder::create()
+ ->sequence('user_id_seq')
+ ->restart();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterSeqStmt::class, $ast);
+ /** @phpstan-ignore method.nonObject (protobuf returns nullable but we know it's set) */
+ self::assertSame('user_id_seq', $ast->getSequence()->getRelname());
+ self::assertNotEmpty($ast->getOptions());
+
+ $optionFound = false;
+
+ foreach ($ast->getOptions() as $option) {
+ $defElem = $option->getDefElem();
+
+ if ($defElem?->getDefname() === 'restart') {
+ $optionFound = true;
+ self::assertFalse($defElem->hasArg());
+ }
+ }
+ self::assertTrue($optionFound);
+ }
+
+ public function test_alter_sequence_restart_with_value() : void
+ {
+ $builder = AlterSequenceBuilder::create()
+ ->sequence('user_id_seq')
+ ->restartWith(1000);
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterSeqStmt::class, $ast);
+
+ $optionFound = false;
+
+ foreach ($ast->getOptions() as $option) {
+ $defElem = $option->getDefElem();
+
+ if ($defElem?->getDefname() === 'restart') {
+ $optionFound = true;
+ /** @phpstan-ignore method.nonObject (protobuf PHPDoc incorrectly returns int instead of Integer class) */
+ self::assertSame(1000, $defElem->getArg()?->getInteger()?->getIval());
+ }
+ }
+ self::assertTrue($optionFound);
+ }
+
+ public function test_alter_sequence_set_logged() : void
+ {
+ $builder = AlterSequenceBuilder::create()
+ ->sequence('user_id_seq')
+ ->setLogged();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterTableStmt::class, $ast);
+ self::assertSame(ObjectType::OBJECT_SEQUENCE, $ast->getObjtype());
+ self::assertCount(1, $ast->getCmds());
+ self::assertSame(AlterTableType::AT_SetLogged, $ast->getCmds()[0]->getAlterTableCmd()?->getSubtype());
+ }
+
+ public function test_alter_sequence_set_logged_if_exists() : void
+ {
+ $builder = AlterSequenceBuilder::ifExists()
+ ->sequence('user_id_seq')
+ ->setLogged();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterTableStmt::class, $ast);
+ self::assertTrue($ast->getMissingOk());
+ }
+
+ public function test_alter_sequence_set_schema() : void
+ {
+ $builder = AlterSequenceBuilder::create()
+ ->sequence('user_id_seq')
+ ->setSchema('new_schema');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterObjectSchemaStmt::class, $ast);
+ self::assertSame(ObjectType::OBJECT_SEQUENCE, $ast->getObjectType());
+ self::assertSame('user_id_seq', $ast->getRelation()?->getRelname());
+ self::assertSame('new_schema', $ast->getNewschema());
+ }
+
+ public function test_alter_sequence_set_schema_if_exists() : void
+ {
+ $builder = AlterSequenceBuilder::ifExists()
+ ->sequence('user_id_seq')
+ ->setSchema('new_schema');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterObjectSchemaStmt::class, $ast);
+ self::assertTrue($ast->getMissingOk());
+ }
+
+ public function test_alter_sequence_set_unlogged() : void
+ {
+ $builder = AlterSequenceBuilder::create()
+ ->sequence('user_id_seq')
+ ->setUnlogged();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterTableStmt::class, $ast);
+ self::assertSame(ObjectType::OBJECT_SEQUENCE, $ast->getObjtype());
+ self::assertCount(1, $ast->getCmds());
+ self::assertSame(AlterTableType::AT_SetUnLogged, $ast->getCmds()[0]->getAlterTableCmd()?->getSubtype());
+ }
+
+ public function test_alter_sequence_start_with() : void
+ {
+ $builder = AlterSequenceBuilder::create()
+ ->sequence('user_id_seq')
+ ->startWith(100);
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterSeqStmt::class, $ast);
+
+ $optionFound = false;
+
+ foreach ($ast->getOptions() as $option) {
+ $defElem = $option->getDefElem();
+
+ if ($defElem?->getDefname() === 'start') {
+ $optionFound = true;
+ /** @phpstan-ignore method.nonObject (protobuf PHPDoc incorrectly returns int instead of Integer class) */
+ self::assertSame(100, $defElem->getArg()?->getInteger()?->getIval());
+ }
+ }
+ self::assertTrue($optionFound);
+ }
+
+ public function test_alter_sequence_with_multiple_options() : void
+ {
+ $builder = AlterSequenceBuilder::create()
+ ->sequence('user_id_seq')
+ ->incrementBy(10)
+ ->minValue(1)
+ ->maxValue(1000000)
+ ->cache(5);
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterSeqStmt::class, $ast);
+ self::assertCount(4, $ast->getOptions());
+ }
+
+ public function test_alter_sequence_with_schema() : void
+ {
+ $builder = AlterSequenceBuilder::create()
+ ->sequence('user_id_seq', 'public')
+ ->incrementBy(10);
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterSeqStmt::class, $ast);
+ /** @phpstan-ignore method.nonObject (protobuf returns nullable but we know it's set) */
+ self::assertSame('user_id_seq', $ast->getSequence()->getRelname());
+ /** @phpstan-ignore method.nonObject (protobuf returns nullable but we know it's set) */
+ self::assertSame('public', $ast->getSequence()->getSchemaname());
+ }
+
+ public function test_immutability() : void
+ {
+ $original = AlterSequenceBuilder::create()->sequence('test_seq');
+ $modified = $original->incrementBy(10);
+
+ self::assertEmpty($original->toAst()->getOptions());
+ self::assertNotEmpty($modified->toAst()->getOptions());
+ }
+}
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
new file mode 100644
index 000000000..6451c2dad
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/AlterTable/AlterTableBuilderTest.php
@@ -0,0 +1,269 @@
+addColumn(ColumnDefinition::create('email', DataType::varchar(255))->notNull());
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterTableStmt::class, $ast);
+ self::assertCount(1, $ast->getCmds());
+ self::assertSame(AlterTableType::AT_AddColumn, $ast->getCmds()[0]->getAlterTableCmd()->getSubtype());
+ self::assertTrue($ast->getCmds()[0]->getAlterTableCmd()->hasDef());
+ }
+
+ public function test_add_constraint() : void
+ {
+ $builder = AlterTableBuilder::create('users')
+ ->addConstraint(PrimaryKeyConstraint::create('id'));
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterTableStmt::class, $ast);
+ self::assertCount(1, $ast->getCmds());
+ self::assertSame(AlterTableType::AT_AddConstraint, $ast->getCmds()[0]->getAlterTableCmd()->getSubtype());
+ }
+
+ public function test_add_foreign_key_constraint() : void
+ {
+ $builder = AlterTableBuilder::create('orders')
+ ->addConstraint(ForeignKeyConstraint::create(['user_id'], 'users', ['id']));
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterTableStmt::class, $ast);
+ self::assertCount(1, $ast->getCmds());
+ self::assertSame(AlterTableType::AT_AddConstraint, $ast->getCmds()[0]->getAlterTableCmd()->getSubtype());
+ }
+
+ public function test_add_unique_constraint() : void
+ {
+ $builder = AlterTableBuilder::create('users')
+ ->addConstraint(UniqueConstraint::create('email'));
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterTableStmt::class, $ast);
+ self::assertCount(1, $ast->getCmds());
+ self::assertSame(AlterTableType::AT_AddConstraint, $ast->getCmds()[0]->getAlterTableCmd()->getSubtype());
+ }
+
+ public function test_alter_column_drop_default() : void
+ {
+ $builder = AlterTableBuilder::create('users')
+ ->alterColumnDropDefault('status');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterTableStmt::class, $ast);
+ self::assertCount(1, $ast->getCmds());
+ self::assertSame(AlterTableType::AT_ColumnDefault, $ast->getCmds()[0]->getAlterTableCmd()->getSubtype());
+ self::assertSame('status', $ast->getCmds()[0]->getAlterTableCmd()->getName());
+ self::assertFalse($ast->getCmds()[0]->getAlterTableCmd()->hasDef());
+ }
+
+ public function test_alter_column_drop_not_null() : void
+ {
+ $builder = AlterTableBuilder::create('users')
+ ->alterColumnDropNotNull('email');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterTableStmt::class, $ast);
+ self::assertCount(1, $ast->getCmds());
+ self::assertSame(AlterTableType::AT_DropNotNull, $ast->getCmds()[0]->getAlterTableCmd()->getSubtype());
+ self::assertSame('email', $ast->getCmds()[0]->getAlterTableCmd()->getName());
+ }
+
+ public function test_alter_column_set_default() : void
+ {
+ $builder = AlterTableBuilder::create('users')
+ ->alterColumnSetDefault('status', "'active'");
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterTableStmt::class, $ast);
+ self::assertCount(1, $ast->getCmds());
+ self::assertSame(AlterTableType::AT_ColumnDefault, $ast->getCmds()[0]->getAlterTableCmd()->getSubtype());
+ self::assertSame('status', $ast->getCmds()[0]->getAlterTableCmd()->getName());
+ self::assertTrue($ast->getCmds()[0]->getAlterTableCmd()->hasDef());
+ }
+
+ public function test_alter_column_set_not_null() : void
+ {
+ $builder = AlterTableBuilder::create('users')
+ ->alterColumnSetNotNull('email');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterTableStmt::class, $ast);
+ self::assertCount(1, $ast->getCmds());
+ self::assertSame(AlterTableType::AT_SetNotNull, $ast->getCmds()[0]->getAlterTableCmd()->getSubtype());
+ self::assertSame('email', $ast->getCmds()[0]->getAlterTableCmd()->getName());
+ }
+
+ public function test_alter_column_type() : void
+ {
+ $builder = AlterTableBuilder::create('users')
+ ->alterColumnType('name', DataType::text());
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterTableStmt::class, $ast);
+ self::assertCount(1, $ast->getCmds());
+ self::assertSame(AlterTableType::AT_AlterColumnType, $ast->getCmds()[0]->getAlterTableCmd()->getSubtype());
+ self::assertSame('name', $ast->getCmds()[0]->getAlterTableCmd()->getName());
+ }
+
+ public function test_alter_table_if_exists() : void
+ {
+ $builder = AlterTableBuilder::create('users')
+ ->ifExists()
+ ->addColumn(ColumnDefinition::create('email', DataType::varchar(255)));
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterTableStmt::class, $ast);
+ self::assertTrue($ast->getMissingOk());
+ }
+
+ public function test_alter_table_with_schema() : void
+ {
+ $builder = AlterTableBuilder::create('users', 'public')
+ ->addColumn(ColumnDefinition::create('email', DataType::varchar(255)));
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterTableStmt::class, $ast);
+ self::assertSame('public', $ast->getRelation()->getSchemaname());
+ self::assertSame('users', $ast->getRelation()->getRelname());
+ }
+
+ public function test_drop_column() : void
+ {
+ $builder = AlterTableBuilder::create('users')
+ ->dropColumn('temp_column');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterTableStmt::class, $ast);
+ self::assertCount(1, $ast->getCmds());
+ self::assertSame(AlterTableType::AT_DropColumn, $ast->getCmds()[0]->getAlterTableCmd()->getSubtype());
+ self::assertSame('temp_column', $ast->getCmds()[0]->getAlterTableCmd()->getName());
+ }
+
+ public function test_drop_column_cascade() : void
+ {
+ $builder = AlterTableBuilder::create('users')
+ ->dropColumn('temp_column', cascade: true);
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterTableStmt::class, $ast);
+ self::assertSame(DropBehavior::DROP_CASCADE, $ast->getCmds()[0]->getAlterTableCmd()->getBehavior());
+ }
+
+ public function test_drop_column_if_exists() : void
+ {
+ $builder = AlterTableBuilder::create('users')
+ ->dropColumnIfExists('temp_column');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterTableStmt::class, $ast);
+ self::assertCount(1, $ast->getCmds());
+ self::assertSame(AlterTableType::AT_DropColumn, $ast->getCmds()[0]->getAlterTableCmd()->getSubtype());
+ self::assertTrue($ast->getCmds()[0]->getAlterTableCmd()->getMissingOk());
+ }
+
+ public function test_drop_constraint() : void
+ {
+ $builder = AlterTableBuilder::create('users')
+ ->dropConstraint('users_email_key');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterTableStmt::class, $ast);
+ self::assertCount(1, $ast->getCmds());
+ self::assertSame(AlterTableType::AT_DropConstraint, $ast->getCmds()[0]->getAlterTableCmd()->getSubtype());
+ self::assertSame('users_email_key', $ast->getCmds()[0]->getAlterTableCmd()->getName());
+ }
+
+ public function test_drop_constraint_cascade() : void
+ {
+ $builder = AlterTableBuilder::create('users')
+ ->dropConstraint('users_email_key', cascade: true);
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterTableStmt::class, $ast);
+ self::assertSame(DropBehavior::DROP_CASCADE, $ast->getCmds()[0]->getAlterTableCmd()->getBehavior());
+ }
+
+ public function test_drop_constraint_if_exists() : void
+ {
+ $builder = AlterTableBuilder::create('users')
+ ->dropConstraintIfExists('users_email_key');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterTableStmt::class, $ast);
+ self::assertTrue($ast->getCmds()[0]->getAlterTableCmd()->getMissingOk());
+ }
+
+ public function test_immutability() : void
+ {
+ $original = AlterTableBuilder::create('users');
+ $modified = $original->addColumn(ColumnDefinition::create('email', DataType::varchar(255)));
+
+ self::assertCount(0, $original->toAst()->getCmds());
+ self::assertCount(1, $modified->toAst()->getCmds());
+ }
+
+ 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)))
+ ->addConstraint(UniqueConstraint::create('email'))
+ ->alterColumnSetNotNull('phone');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterTableStmt::class, $ast);
+ self::assertCount(4, $ast->getCmds());
+ }
+
+ public function test_simple_alter_table() : void
+ {
+ $builder = AlterTableBuilder::create('users')
+ ->addColumn(ColumnDefinition::create('email', DataType::varchar(255)));
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterTableStmt::class, $ast);
+ self::assertSame('users', $ast->getRelation()->getRelname());
+ self::assertSame(ObjectType::OBJECT_TABLE, $ast->getObjtype());
+ self::assertCount(1, $ast->getCmds());
+ }
+}
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
new file mode 100644
index 000000000..745870d45
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/ColumnDefinitionTest.php
@@ -0,0 +1,249 @@
+toAst();
+
+ self::assertInstanceOf(ColumnDef::class, $ast);
+ self::assertSame('id', $ast->getColname());
+ self::assertFalse($ast->getIsNotNull());
+ }
+
+ public function test_check_constraint() : void
+ {
+ $column = ColumnDefinition::create('age', DataType::integer())
+ ->check('age > 0');
+
+ $ast = $column->toAst();
+
+ self::assertInstanceOf(ColumnDef::class, $ast);
+ self::assertCount(1, $ast->getConstraints());
+ self::assertSame(ConstrType::CONSTR_CHECK, $ast->getConstraints()[0]->getConstraint()->getContype());
+ }
+
+ public function test_column_with_boolean_default_false() : void
+ {
+ $column = ColumnDefinition::create('is_active', DataType::boolean())
+ ->default(false);
+
+ $ast = $column->toAst();
+
+ self::assertInstanceOf(ColumnDef::class, $ast);
+ self::assertCount(1, $ast->getConstraints());
+ self::assertSame(ConstrType::CONSTR_DEFAULT, $ast->getConstraints()[0]->getConstraint()->getContype());
+ }
+
+ public function test_column_with_boolean_default_true() : void
+ {
+ $column = ColumnDefinition::create('is_active', DataType::boolean())
+ ->default(true);
+
+ $ast = $column->toAst();
+
+ self::assertInstanceOf(ColumnDef::class, $ast);
+ self::assertCount(1, $ast->getConstraints());
+ self::assertSame(ConstrType::CONSTR_DEFAULT, $ast->getConstraints()[0]->getConstraint()->getContype());
+ }
+
+ public function test_column_with_default_integer() : void
+ {
+ $column = ColumnDefinition::create('status', DataType::integer())
+ ->default(0);
+
+ $ast = $column->toAst();
+
+ self::assertInstanceOf(ColumnDef::class, $ast);
+ self::assertCount(1, $ast->getConstraints());
+ self::assertSame(ConstrType::CONSTR_DEFAULT, $ast->getConstraints()[0]->getConstraint()->getContype());
+ }
+
+ public function test_column_with_default_null() : void
+ {
+ $column = ColumnDefinition::create('optional', DataType::text())
+ ->default(null);
+
+ $ast = $column->toAst();
+
+ self::assertInstanceOf(ColumnDef::class, $ast);
+ self::assertCount(1, $ast->getConstraints());
+ self::assertSame(ConstrType::CONSTR_DEFAULT, $ast->getConstraints()[0]->getConstraint()->getContype());
+ }
+
+ public function test_column_with_default_raw_expression() : void
+ {
+ $column = ColumnDefinition::create('created_at', DataType::timestamp())
+ ->defaultRaw('CURRENT_TIMESTAMP');
+
+ $ast = $column->toAst();
+
+ self::assertInstanceOf(ColumnDef::class, $ast);
+ self::assertCount(1, $ast->getConstraints());
+ self::assertSame(ConstrType::CONSTR_DEFAULT, $ast->getConstraints()[0]->getConstraint()->getContype());
+ }
+
+ public function test_column_with_default_string() : void
+ {
+ $column = ColumnDefinition::create('name', DataType::varchar(100))
+ ->default('Unknown');
+
+ $ast = $column->toAst();
+
+ self::assertInstanceOf(ColumnDef::class, $ast);
+ self::assertCount(1, $ast->getConstraints());
+ self::assertSame(ConstrType::CONSTR_DEFAULT, $ast->getConstraints()[0]->getConstraint()->getContype());
+ }
+
+ public function test_generated_column() : void
+ {
+ $column = ColumnDefinition::create('full_name', DataType::text())
+ ->generatedAs("first_name || ' ' || last_name");
+
+ $ast = $column->toAst();
+
+ self::assertInstanceOf(ColumnDef::class, $ast);
+ self::assertSame('s', $ast->getGenerated());
+ self::assertCount(1, $ast->getConstraints());
+ self::assertSame(ConstrType::CONSTR_GENERATED, $ast->getConstraints()[0]->getConstraint()->getContype());
+ }
+
+ public function test_identity_always() : void
+ {
+ $column = ColumnDefinition::create('id', DataType::integer())
+ ->identity('ALWAYS');
+
+ $ast = $column->toAst();
+
+ self::assertInstanceOf(ColumnDef::class, $ast);
+ self::assertSame('a', $ast->getIdentity());
+ }
+
+ public function test_identity_by_default() : void
+ {
+ $column = ColumnDefinition::create('id', DataType::integer())
+ ->identity('BY DEFAULT');
+
+ $ast = $column->toAst();
+
+ self::assertInstanceOf(ColumnDef::class, $ast);
+ self::assertSame('d', $ast->getIdentity());
+ }
+
+ public function test_immutability() : void
+ {
+ $original = ColumnDefinition::create('id', DataType::integer());
+ $modified = $original->notNull();
+
+ self::assertNotSame($original, $modified);
+ self::assertCount(0, $original->toAst()->getConstraints());
+ self::assertCount(1, $modified->toAst()->getConstraints());
+ self::assertSame(ConstrType::CONSTR_NOTNULL, $modified->toAst()->getConstraints()[0]->getConstraint()->getContype());
+ }
+
+ public function test_multiple_constraints() : void
+ {
+ $column = ColumnDefinition::create('id', DataType::integer())
+ ->notNull()
+ ->primaryKey();
+
+ $ast = $column->toAst();
+
+ self::assertInstanceOf(ColumnDef::class, $ast);
+ self::assertCount(2, $ast->getConstraints());
+ self::assertSame(ConstrType::CONSTR_NOTNULL, $ast->getConstraints()[0]->getConstraint()->getContype());
+ self::assertSame(ConstrType::CONSTR_PRIMARY, $ast->getConstraints()[1]->getConstraint()->getContype());
+ }
+
+ public function test_not_null_column() : void
+ {
+ $column = ColumnDefinition::create('name', DataType::varchar(100))
+ ->notNull();
+
+ $ast = $column->toAst();
+
+ self::assertInstanceOf(ColumnDef::class, $ast);
+ self::assertCount(1, $ast->getConstraints());
+ self::assertSame(ConstrType::CONSTR_NOTNULL, $ast->getConstraints()[0]->getConstraint()->getContype());
+ }
+
+ public function test_nullable_column() : void
+ {
+ $column = ColumnDefinition::create('name', DataType::varchar(100))
+ ->notNull()
+ ->nullable();
+
+ $ast = $column->toAst();
+
+ self::assertInstanceOf(ColumnDef::class, $ast);
+ self::assertCount(0, $ast->getConstraints());
+ }
+
+ public function test_primary_key_constraint() : void
+ {
+ $column = ColumnDefinition::create('id', DataType::integer())
+ ->primaryKey();
+
+ $ast = $column->toAst();
+
+ self::assertInstanceOf(ColumnDef::class, $ast);
+ self::assertCount(1, $ast->getConstraints());
+ self::assertSame(ConstrType::CONSTR_PRIMARY, $ast->getConstraints()[0]->getConstraint()->getContype());
+ }
+
+ public function test_references_constraint() : void
+ {
+ $column = ColumnDefinition::create('user_id', DataType::integer())
+ ->references('users', 'id');
+
+ $ast = $column->toAst();
+
+ self::assertInstanceOf(ColumnDef::class, $ast);
+ self::assertCount(1, $ast->getConstraints());
+ $constraint = $ast->getConstraints()[0]->getConstraint();
+ self::assertSame(ConstrType::CONSTR_FOREIGN, $constraint->getContype());
+ self::assertSame('users', $constraint->getPktable()->getRelname());
+ }
+
+ public function test_references_with_schema() : void
+ {
+ $column = ColumnDefinition::create('user_id', DataType::integer())
+ ->references('users', 'id', 'public');
+
+ $ast = $column->toAst();
+
+ self::assertInstanceOf(ColumnDef::class, $ast);
+ $constraint = $ast->getConstraints()[0]->getConstraint();
+ self::assertSame('public', $constraint->getPktable()->getSchemaname());
+ self::assertSame('users', $constraint->getPktable()->getRelname());
+ }
+
+ public function test_unique_constraint() : void
+ {
+ $column = ColumnDefinition::create('email', DataType::varchar(255))
+ ->unique();
+
+ $ast = $column->toAst();
+
+ self::assertInstanceOf(ColumnDef::class, $ast);
+ self::assertCount(1, $ast->getConstraints());
+ self::assertSame(ConstrType::CONSTR_UNIQUE, $ast->getConstraints()[0]->getConstraint()->getContype());
+ }
+}
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
new file mode 100644
index 000000000..965c210cb
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Constraint/CheckConstraintTest.php
@@ -0,0 +1,88 @@
+ 0')
+ ->name('chk_positive_age');
+
+ $ast = $constraint->toAst();
+
+ self::assertInstanceOf(Constraint::class, $ast);
+ self::assertSame(ConstrType::CONSTR_CHECK, $ast->getContype());
+ self::assertSame('chk_positive_age', $ast->getConname());
+ }
+
+ public function test_complex_check_expression() : void
+ {
+ $constraint = CheckConstraint::create('start_date < end_date');
+
+ $ast = $constraint->toAst();
+
+ self::assertInstanceOf(Constraint::class, $ast);
+ self::assertSame(ConstrType::CONSTR_CHECK, $ast->getContype());
+ self::assertTrue($ast->hasRawExpr());
+ }
+
+ public function test_immutability() : void
+ {
+ $original = CheckConstraint::create('value > 0');
+ $withName = $original->name('chk_test');
+
+ self::assertNotSame($original, $withName);
+ self::assertSame('', $original->toAst()->getConname());
+ self::assertSame('chk_test', $withName->toAst()->getConname());
+ }
+
+ public function test_no_inherit() : void
+ {
+ $constraint = CheckConstraint::create('status IN (\'active\', \'inactive\')')
+ ->noInherit();
+
+ $ast = $constraint->toAst();
+
+ self::assertInstanceOf(Constraint::class, $ast);
+ self::assertSame(ConstrType::CONSTR_CHECK, $ast->getContype());
+ self::assertTrue($ast->getIsNoInherit());
+ }
+
+ public function test_simple_check_constraint() : void
+ {
+ $constraint = CheckConstraint::create('age > 0');
+
+ $ast = $constraint->toAst();
+
+ self::assertInstanceOf(Constraint::class, $ast);
+ self::assertSame(ConstrType::CONSTR_CHECK, $ast->getContype());
+ self::assertTrue($ast->hasRawExpr());
+ }
+
+ public function test_with_all_options() : void
+ {
+ $constraint = CheckConstraint::create('amount >= 0')
+ ->name('chk_positive_amount')
+ ->noInherit();
+
+ $ast = $constraint->toAst();
+
+ self::assertInstanceOf(Constraint::class, $ast);
+ self::assertSame('chk_positive_amount', $ast->getConname());
+ self::assertTrue($ast->getIsNoInherit());
+ }
+}
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
new file mode 100644
index 000000000..2afe979c0
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Constraint/ExcludeConstraintTest.php
@@ -0,0 +1,108 @@
+element('id', '=');
+
+ $ast = $constraint->toAst();
+
+ self::assertInstanceOf(Constraint::class, $ast);
+ self::assertSame(ConstrType::CONSTR_EXCLUSION, $ast->getContype());
+ self::assertSame('btree', $ast->getAccessMethod());
+ }
+
+ public function test_exclude_constraint_with_multiple_elements() : void
+ {
+ $constraint = ExcludeConstraint::create('gist')
+ ->element('room_id', '=')
+ ->element('during', '&&');
+
+ $ast = $constraint->toAst();
+
+ self::assertInstanceOf(Constraint::class, $ast);
+ self::assertSame(ConstrType::CONSTR_EXCLUSION, $ast->getContype());
+ self::assertCount(4, $ast->getExclusions());
+ }
+
+ public function test_exclude_constraint_with_name() : void
+ {
+ $constraint = ExcludeConstraint::create()
+ ->element('room_id', '=')
+ ->name('exc_room_booking');
+
+ $ast = $constraint->toAst();
+
+ self::assertInstanceOf(Constraint::class, $ast);
+ self::assertSame('exc_room_booking', $ast->getConname());
+ }
+
+ public function test_exclude_constraint_with_where_clause() : void
+ {
+ $constraint = ExcludeConstraint::create()
+ ->element('room_id', '=')
+ ->where('active = true');
+
+ $ast = $constraint->toAst();
+
+ self::assertInstanceOf(Constraint::class, $ast);
+ self::assertTrue($ast->hasWhereClause());
+ }
+
+ public function test_exclude_with_all_options() : void
+ {
+ $constraint = ExcludeConstraint::create('gist')
+ ->name('exc_booking')
+ ->element('room_id', '=')
+ ->element('period', '&&')
+ ->where('cancelled = false');
+
+ $ast = $constraint->toAst();
+
+ self::assertInstanceOf(Constraint::class, $ast);
+ self::assertSame('exc_booking', $ast->getConname());
+ self::assertSame('gist', $ast->getAccessMethod());
+ self::assertCount(4, $ast->getExclusions());
+ self::assertTrue($ast->hasWhereClause());
+ }
+
+ public function test_immutability() : void
+ {
+ $original = ExcludeConstraint::create();
+ $withName = $original->name('exc_test');
+
+ self::assertNotSame($original, $withName);
+ self::assertSame('', $original->toAst()->getConname());
+ self::assertSame('exc_test', $withName->toAst()->getConname());
+ }
+
+ public function test_simple_exclude_constraint() : void
+ {
+ $constraint = ExcludeConstraint::create()
+ ->element('room_id', '=');
+
+ $ast = $constraint->toAst();
+
+ self::assertInstanceOf(Constraint::class, $ast);
+ self::assertSame(ConstrType::CONSTR_EXCLUSION, $ast->getContype());
+ self::assertSame('gist', $ast->getAccessMethod());
+ self::assertCount(2, $ast->getExclusions());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Constraint/ForeignKeyConstraintTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Constraint/ForeignKeyConstraintTest.php
new file mode 100644
index 000000000..c4ccef91d
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Constraint/ForeignKeyConstraintTest.php
@@ -0,0 +1,206 @@
+toAst();
+
+ self::assertInstanceOf(Constraint::class, $ast);
+ self::assertSame(ConstrType::CONSTR_FOREIGN, $ast->getContype());
+ self::assertCount(2, $ast->getFkAttrs());
+ self::assertCount(2, $ast->getPkAttrs());
+ }
+
+ public function test_deferrable() : void
+ {
+ $constraint = ForeignKeyConstraint::create(['user_id'], 'users', ['id'])
+ ->deferrable();
+
+ $ast = $constraint->toAst();
+
+ self::assertInstanceOf(Constraint::class, $ast);
+ self::assertTrue($ast->getDeferrable());
+ self::assertFalse($ast->getInitdeferred());
+ }
+
+ public function test_deferrable_initially_deferred() : void
+ {
+ $constraint = ForeignKeyConstraint::create(['user_id'], 'users', ['id'])
+ ->deferrable(initiallyDeferred: true);
+
+ $ast = $constraint->toAst();
+
+ self::assertInstanceOf(Constraint::class, $ast);
+ self::assertTrue($ast->getDeferrable());
+ self::assertTrue($ast->getInitdeferred());
+ }
+
+ public function test_foreign_key_with_all_options() : void
+ {
+ $constraint = ForeignKeyConstraint::create(['user_id'], 'users', ['id'])
+ ->name('fk_orders_user')
+ ->schema('public')
+ ->onUpdate(ReferentialAction::CASCADE)
+ ->onDelete(ReferentialAction::SET_NULL)
+ ->deferrable(initiallyDeferred: true);
+
+ $ast = $constraint->toAst();
+
+ self::assertInstanceOf(Constraint::class, $ast);
+ self::assertSame('fk_orders_user', $ast->getConname());
+ self::assertSame('public', $ast->getPktable()->getSchemaname());
+ self::assertSame('c', $ast->getFkUpdAction());
+ self::assertSame('n', $ast->getFkDelAction());
+ self::assertTrue($ast->getDeferrable());
+ self::assertTrue($ast->getInitdeferred());
+ }
+
+ public function test_foreign_key_with_name() : void
+ {
+ $constraint = ForeignKeyConstraint::create(['user_id'], 'users', ['id'])
+ ->name('fk_orders_user');
+
+ $ast = $constraint->toAst();
+
+ self::assertInstanceOf(Constraint::class, $ast);
+ self::assertSame('fk_orders_user', $ast->getConname());
+ }
+
+ public function test_foreign_key_with_schema() : void
+ {
+ $constraint = ForeignKeyConstraint::create(['user_id'], 'users', ['id'])
+ ->schema('public');
+
+ $ast = $constraint->toAst();
+
+ self::assertInstanceOf(Constraint::class, $ast);
+ self::assertSame('public', $ast->getPktable()->getSchemaname());
+ self::assertSame('users', $ast->getPktable()->getRelname());
+ }
+
+ public function test_immutability() : void
+ {
+ $original = ForeignKeyConstraint::create(['user_id'], 'users', ['id']);
+ $withName = $original->name('fk_test');
+
+ self::assertNotSame($original, $withName);
+ self::assertSame('', $original->toAst()->getConname());
+ self::assertSame('fk_test', $withName->toAst()->getConname());
+ }
+
+ public function test_on_delete_cascade() : void
+ {
+ $constraint = ForeignKeyConstraint::create(['user_id'], 'users', ['id'])
+ ->onDelete(ReferentialAction::CASCADE);
+
+ $ast = $constraint->toAst();
+
+ self::assertInstanceOf(Constraint::class, $ast);
+ self::assertSame('c', $ast->getFkDelAction());
+ }
+
+ public function test_on_delete_restrict() : void
+ {
+ $constraint = ForeignKeyConstraint::create(['user_id'], 'users', ['id'])
+ ->onDelete(ReferentialAction::RESTRICT);
+
+ $ast = $constraint->toAst();
+
+ self::assertInstanceOf(Constraint::class, $ast);
+ self::assertSame('r', $ast->getFkDelAction());
+ }
+
+ public function test_on_delete_set_default() : void
+ {
+ $constraint = ForeignKeyConstraint::create(['user_id'], 'users', ['id'])
+ ->onDelete(ReferentialAction::SET_DEFAULT);
+
+ $ast = $constraint->toAst();
+
+ self::assertInstanceOf(Constraint::class, $ast);
+ self::assertSame('d', $ast->getFkDelAction());
+ }
+
+ public function test_on_delete_set_null() : void
+ {
+ $constraint = ForeignKeyConstraint::create(['user_id'], 'users', ['id'])
+ ->onDelete(ReferentialAction::SET_NULL);
+
+ $ast = $constraint->toAst();
+
+ self::assertInstanceOf(Constraint::class, $ast);
+ self::assertSame('n', $ast->getFkDelAction());
+ }
+
+ public function test_on_update_cascade() : void
+ {
+ $constraint = ForeignKeyConstraint::create(['user_id'], 'users', ['id'])
+ ->onUpdate(ReferentialAction::CASCADE);
+
+ $ast = $constraint->toAst();
+
+ self::assertInstanceOf(Constraint::class, $ast);
+ self::assertSame('c', $ast->getFkUpdAction());
+ }
+
+ public function test_on_update_no_action() : void
+ {
+ $constraint = ForeignKeyConstraint::create(['user_id'], 'users', ['id'])
+ ->onUpdate(ReferentialAction::NO_ACTION);
+
+ $ast = $constraint->toAst();
+
+ self::assertInstanceOf(Constraint::class, $ast);
+ self::assertSame('a', $ast->getFkUpdAction());
+ }
+
+ public function test_simple_foreign_key() : void
+ {
+ $constraint = ForeignKeyConstraint::create(['user_id'], 'users', ['id']);
+
+ $ast = $constraint->toAst();
+
+ self::assertInstanceOf(Constraint::class, $ast);
+ self::assertSame(ConstrType::CONSTR_FOREIGN, $ast->getContype());
+ self::assertCount(1, $ast->getFkAttrs());
+ self::assertSame('user_id', $ast->getFkAttrs()[0]->getString()->getSval());
+ self::assertSame('users', $ast->getPktable()->getRelname());
+ self::assertCount(1, $ast->getPkAttrs());
+ self::assertSame('id', $ast->getPkAttrs()[0]->getString()->getSval());
+ }
+
+ public function test_simple_foreign_key_without_reference_columns() : void
+ {
+ $constraint = ForeignKeyConstraint::create(['user_id'], 'users');
+
+ $ast = $constraint->toAst();
+
+ self::assertInstanceOf(Constraint::class, $ast);
+ self::assertSame(ConstrType::CONSTR_FOREIGN, $ast->getContype());
+ self::assertSame('users', $ast->getPktable()->getRelname());
+ self::assertCount(0, $ast->getPkAttrs());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Constraint/PrimaryKeyConstraintTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Constraint/PrimaryKeyConstraintTest.php
new file mode 100644
index 000000000..68f57e12a
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Constraint/PrimaryKeyConstraintTest.php
@@ -0,0 +1,68 @@
+toAst();
+
+ self::assertInstanceOf(Constraint::class, $ast);
+ self::assertSame(ConstrType::CONSTR_PRIMARY, $ast->getContype());
+ self::assertCount(2, $ast->getKeys());
+ self::assertSame('user_id', $ast->getKeys()[0]->getString()->getSval());
+ self::assertSame('order_id', $ast->getKeys()[1]->getString()->getSval());
+ }
+
+ public function test_immutability() : void
+ {
+ $original = PrimaryKeyConstraint::create('id');
+ $withName = $original->name('pk_test');
+
+ self::assertNotSame($original, $withName);
+ self::assertSame('', $original->toAst()->getConname());
+ self::assertSame('pk_test', $withName->toAst()->getConname());
+ }
+
+ public function test_primary_key_with_name() : void
+ {
+ $constraint = PrimaryKeyConstraint::create('id')
+ ->name('pk_users');
+
+ $ast = $constraint->toAst();
+
+ self::assertInstanceOf(Constraint::class, $ast);
+ self::assertSame(ConstrType::CONSTR_PRIMARY, $ast->getContype());
+ self::assertSame('pk_users', $ast->getConname());
+ self::assertCount(1, $ast->getKeys());
+ self::assertSame('id', $ast->getKeys()[0]->getString()->getSval());
+ }
+
+ public function test_simple_primary_key() : void
+ {
+ $constraint = PrimaryKeyConstraint::create('id');
+
+ $ast = $constraint->toAst();
+
+ self::assertInstanceOf(Constraint::class, $ast);
+ self::assertSame(ConstrType::CONSTR_PRIMARY, $ast->getContype());
+ self::assertCount(1, $ast->getKeys());
+ self::assertSame('id', $ast->getKeys()[0]->getString()->getSval());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Constraint/UniqueConstraintTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Constraint/UniqueConstraintTest.php
new file mode 100644
index 000000000..1cc1beb2b
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Constraint/UniqueConstraintTest.php
@@ -0,0 +1,91 @@
+toAst();
+
+ self::assertInstanceOf(Constraint::class, $ast);
+ self::assertSame(ConstrType::CONSTR_UNIQUE, $ast->getContype());
+ self::assertCount(2, $ast->getKeys());
+ self::assertSame('first_name', $ast->getKeys()[0]->getString()->getSval());
+ self::assertSame('last_name', $ast->getKeys()[1]->getString()->getSval());
+ }
+
+ public function test_immutability() : void
+ {
+ $original = UniqueConstraint::create('email');
+ $withName = $original->name('uq_test');
+
+ self::assertNotSame($original, $withName);
+ self::assertSame('', $original->toAst()->getConname());
+ self::assertSame('uq_test', $withName->toAst()->getConname());
+ }
+
+ public function test_nulls_not_distinct() : void
+ {
+ $constraint = UniqueConstraint::create('email')
+ ->nullsNotDistinct();
+
+ $ast = $constraint->toAst();
+
+ self::assertInstanceOf(Constraint::class, $ast);
+ self::assertSame(ConstrType::CONSTR_UNIQUE, $ast->getContype());
+ self::assertTrue($ast->getNullsNotDistinct());
+ }
+
+ public function test_simple_unique_constraint() : void
+ {
+ $constraint = UniqueConstraint::create('email');
+
+ $ast = $constraint->toAst();
+
+ self::assertInstanceOf(Constraint::class, $ast);
+ self::assertSame(ConstrType::CONSTR_UNIQUE, $ast->getContype());
+ self::assertCount(1, $ast->getKeys());
+ self::assertSame('email', $ast->getKeys()[0]->getString()->getSval());
+ }
+
+ public function test_unique_constraint_with_name() : void
+ {
+ $constraint = UniqueConstraint::create('email')
+ ->name('uq_users_email');
+
+ $ast = $constraint->toAst();
+
+ self::assertInstanceOf(Constraint::class, $ast);
+ self::assertSame(ConstrType::CONSTR_UNIQUE, $ast->getContype());
+ self::assertSame('uq_users_email', $ast->getConname());
+ }
+
+ public function test_unique_with_all_options() : void
+ {
+ $constraint = UniqueConstraint::create('email')
+ ->name('uq_users_email')
+ ->nullsNotDistinct();
+
+ $ast = $constraint->toAst();
+
+ self::assertInstanceOf(Constraint::class, $ast);
+ self::assertSame('uq_users_email', $ast->getConname());
+ self::assertTrue($ast->getNullsNotDistinct());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/CreateSequence/CreateSequenceBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/CreateSequence/CreateSequenceBuilderTest.php
new file mode 100644
index 000000000..cb603de3b
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/CreateSequence/CreateSequenceBuilderTest.php
@@ -0,0 +1,443 @@
+sequence('user_id_seq');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateSeqStmt::class, $ast);
+ self::assertTrue($ast->getIfNotExists());
+ }
+
+ public function test_create_sequence_no_max_value() : void
+ {
+ $builder = CreateSequenceBuilder::create()
+ ->sequence('user_id_seq')
+ ->noMaxValue();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateSeqStmt::class, $ast);
+ self::assertNotEmpty($ast->getOptions());
+
+ $optionFound = false;
+
+ foreach ($ast->getOptions() as $option) {
+ $defElem = $option->getDefElem();
+
+ if ($defElem?->getDefname() === 'maxvalue') {
+ $optionFound = true;
+ self::assertFalse($defElem->hasArg());
+ }
+ }
+ self::assertTrue($optionFound);
+ }
+
+ public function test_create_sequence_no_min_value() : void
+ {
+ $builder = CreateSequenceBuilder::create()
+ ->sequence('user_id_seq')
+ ->noMinValue();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateSeqStmt::class, $ast);
+ self::assertNotEmpty($ast->getOptions());
+
+ $optionFound = false;
+
+ foreach ($ast->getOptions() as $option) {
+ $defElem = $option->getDefElem();
+
+ if ($defElem?->getDefname() === 'minvalue') {
+ $optionFound = true;
+ self::assertFalse($defElem->hasArg());
+ }
+ }
+ self::assertTrue($optionFound);
+ }
+
+ public function test_create_sequence_owned_by() : void
+ {
+ $builder = CreateSequenceBuilder::create()
+ ->sequence('user_id_seq')
+ ->ownedBy('users', 'id');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateSeqStmt::class, $ast);
+ self::assertNotEmpty($ast->getOptions());
+
+ $optionFound = false;
+
+ foreach ($ast->getOptions() as $option) {
+ $defElem = $option->getDefElem();
+
+ if ($defElem?->getDefname() === 'owned_by') {
+ $optionFound = true;
+ self::assertTrue($defElem->hasArg());
+ $list = $defElem->getArg()?->getList();
+ self::assertNotNull($list);
+ self::assertCount(2, $list->getItems());
+ self::assertSame('users', $list->getItems()[0]->getString()?->getSval());
+ self::assertSame('id', $list->getItems()[1]->getString()?->getSval());
+ }
+ }
+ self::assertTrue($optionFound);
+ }
+
+ public function test_create_sequence_owned_by_none() : void
+ {
+ $builder = CreateSequenceBuilder::create()
+ ->sequence('user_id_seq')
+ ->ownedByNone();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateSeqStmt::class, $ast);
+ self::assertNotEmpty($ast->getOptions());
+
+ $optionFound = false;
+
+ foreach ($ast->getOptions() as $option) {
+ $defElem = $option->getDefElem();
+
+ if ($defElem?->getDefname() === 'owned_by') {
+ $optionFound = true;
+ self::assertTrue($defElem->hasArg());
+ $list = $defElem->getArg()?->getList();
+ self::assertNotNull($list);
+ self::assertCount(1, $list->getItems());
+ self::assertSame('none', $list->getItems()[0]->getString()?->getSval());
+ }
+ }
+ self::assertTrue($optionFound);
+ }
+
+ public function test_create_sequence_owned_by_with_schema() : void
+ {
+ $builder = CreateSequenceBuilder::create()
+ ->sequence('user_id_seq')
+ ->ownedBy('public.users', 'id');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateSeqStmt::class, $ast);
+ self::assertNotEmpty($ast->getOptions());
+
+ $optionFound = false;
+
+ foreach ($ast->getOptions() as $option) {
+ $defElem = $option->getDefElem();
+
+ if ($defElem?->getDefname() === 'owned_by') {
+ $optionFound = true;
+ self::assertTrue($defElem->hasArg());
+ $list = $defElem->getArg()?->getList();
+ self::assertNotNull($list);
+ self::assertCount(3, $list->getItems());
+ self::assertSame('public', $list->getItems()[0]->getString()?->getSval());
+ self::assertSame('users', $list->getItems()[1]->getString()?->getSval());
+ self::assertSame('id', $list->getItems()[2]->getString()?->getSval());
+ }
+ }
+ self::assertTrue($optionFound);
+ }
+
+ public function test_create_sequence_with_all_options() : void
+ {
+ $builder = CreateSequenceBuilder::create()
+ ->sequence('user_id_seq')
+ ->asType('bigint')
+ ->startWith(1)
+ ->incrementBy(1)
+ ->minValue(1)
+ ->maxValue(9223372036854775807)
+ ->cache(1)
+ ->noCycle();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateSeqStmt::class, $ast);
+ self::assertCount(7, $ast->getOptions());
+ }
+
+ public function test_create_sequence_with_as_type() : void
+ {
+ $builder = CreateSequenceBuilder::create()
+ ->sequence('user_id_seq')
+ ->asType('bigint');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateSeqStmt::class, $ast);
+ self::assertNotEmpty($ast->getOptions());
+
+ $optionFound = false;
+
+ foreach ($ast->getOptions() as $option) {
+ $defElem = $option->getDefElem();
+
+ if ($defElem?->getDefname() === 'as') {
+ $optionFound = true;
+ self::assertTrue($defElem->hasArg());
+ }
+ }
+ self::assertTrue($optionFound);
+ }
+
+ public function test_create_sequence_with_cache() : void
+ {
+ $builder = CreateSequenceBuilder::create()
+ ->sequence('user_id_seq')
+ ->cache(20);
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateSeqStmt::class, $ast);
+ self::assertNotEmpty($ast->getOptions());
+
+ $optionFound = false;
+
+ foreach ($ast->getOptions() as $option) {
+ $defElem = $option->getDefElem();
+
+ if ($defElem?->getDefname() === 'cache') {
+ $optionFound = true;
+ /** @phpstan-ignore method.nonObject (protobuf PHPDoc incorrectly returns int instead of Integer class) */
+ self::assertSame(20, $defElem->getArg()?->getInteger()?->getIval());
+ }
+ }
+ self::assertTrue($optionFound);
+ }
+
+ public function test_create_sequence_with_cycle() : void
+ {
+ $builder = CreateSequenceBuilder::create()
+ ->sequence('user_id_seq')
+ ->cycle();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateSeqStmt::class, $ast);
+ self::assertNotEmpty($ast->getOptions());
+
+ $optionFound = false;
+
+ foreach ($ast->getOptions() as $option) {
+ $defElem = $option->getDefElem();
+
+ if ($defElem?->getDefname() === 'cycle') {
+ $optionFound = true;
+ /** @phpstan-ignore method.nonObject (protobuf PHPDoc incorrectly returns bool instead of Boolean class) */
+ self::assertTrue($defElem->getArg()?->getBoolean()?->getBoolval());
+ }
+ }
+ self::assertTrue($optionFound);
+ }
+
+ public function test_create_sequence_with_increment() : void
+ {
+ $builder = CreateSequenceBuilder::create()
+ ->sequence('user_id_seq')
+ ->incrementBy(10);
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateSeqStmt::class, $ast);
+ self::assertNotEmpty($ast->getOptions());
+
+ $optionFound = false;
+
+ foreach ($ast->getOptions() as $option) {
+ $defElem = $option->getDefElem();
+
+ if ($defElem?->getDefname() === 'increment') {
+ $optionFound = true;
+ /** @phpstan-ignore method.nonObject (protobuf PHPDoc incorrectly returns int instead of Integer class) */
+ self::assertSame(10, $defElem->getArg()?->getInteger()?->getIval());
+ }
+ }
+ self::assertTrue($optionFound);
+ }
+
+ public function test_create_sequence_with_max_value() : void
+ {
+ $builder = CreateSequenceBuilder::create()
+ ->sequence('user_id_seq')
+ ->maxValue(9999999);
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateSeqStmt::class, $ast);
+ self::assertNotEmpty($ast->getOptions());
+
+ $optionFound = false;
+
+ foreach ($ast->getOptions() as $option) {
+ $defElem = $option->getDefElem();
+
+ if ($defElem?->getDefname() === 'maxvalue') {
+ $optionFound = true;
+ /** @phpstan-ignore method.nonObject (protobuf PHPDoc incorrectly returns int instead of Integer class) */
+ self::assertSame(9999999, $defElem->getArg()?->getInteger()?->getIval());
+ }
+ }
+ self::assertTrue($optionFound);
+ }
+
+ public function test_create_sequence_with_min_value() : void
+ {
+ $builder = CreateSequenceBuilder::create()
+ ->sequence('user_id_seq')
+ ->minValue(1);
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateSeqStmt::class, $ast);
+ self::assertNotEmpty($ast->getOptions());
+
+ $optionFound = false;
+
+ foreach ($ast->getOptions() as $option) {
+ $defElem = $option->getDefElem();
+
+ if ($defElem?->getDefname() === 'minvalue') {
+ $optionFound = true;
+ /** @phpstan-ignore method.nonObject (protobuf PHPDoc incorrectly returns int instead of Integer class) */
+ self::assertSame(1, $defElem->getArg()?->getInteger()?->getIval());
+ }
+ }
+ self::assertTrue($optionFound);
+ }
+
+ public function test_create_sequence_with_no_cycle() : void
+ {
+ $builder = CreateSequenceBuilder::create()
+ ->sequence('user_id_seq')
+ ->noCycle();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateSeqStmt::class, $ast);
+ self::assertNotEmpty($ast->getOptions());
+
+ $optionFound = false;
+
+ foreach ($ast->getOptions() as $option) {
+ $defElem = $option->getDefElem();
+
+ if ($defElem?->getDefname() === 'cycle') {
+ $optionFound = true;
+ /** @phpstan-ignore method.nonObject (protobuf PHPDoc incorrectly returns bool instead of Boolean class) */
+ self::assertFalse($defElem->getArg()?->getBoolean()?->getBoolval());
+ }
+ }
+ self::assertTrue($optionFound);
+ }
+
+ public function test_create_sequence_with_schema() : void
+ {
+ $builder = CreateSequenceBuilder::create()
+ ->sequence('user_id_seq', 'public');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateSeqStmt::class, $ast);
+ /** @phpstan-ignore method.nonObject (protobuf returns nullable but we know it's set) */
+ self::assertSame('user_id_seq', $ast->getSequence()->getRelname());
+ /** @phpstan-ignore method.nonObject (protobuf returns nullable but we know it's set) */
+ self::assertSame('public', $ast->getSequence()->getSchemaname());
+ }
+
+ public function test_create_sequence_with_start_value() : void
+ {
+ $builder = CreateSequenceBuilder::create()
+ ->sequence('user_id_seq')
+ ->startWith(100);
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateSeqStmt::class, $ast);
+ self::assertNotEmpty($ast->getOptions());
+
+ $optionFound = false;
+
+ foreach ($ast->getOptions() as $option) {
+ $defElem = $option->getDefElem();
+
+ if ($defElem?->getDefname() === 'start') {
+ $optionFound = true;
+ /** @phpstan-ignore method.nonObject (protobuf PHPDoc incorrectly returns int instead of Integer class) */
+ self::assertSame(100, $defElem->getArg()?->getInteger()?->getIval());
+ }
+ }
+ self::assertTrue($optionFound);
+ }
+
+ public function test_create_temporary_sequence() : void
+ {
+ $builder = CreateSequenceBuilder::createTemporary()
+ ->sequence('temp_seq');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateSeqStmt::class, $ast);
+ /** @phpstan-ignore method.nonObject (protobuf returns nullable but we know it's set) */
+ self::assertSame('t', $ast->getSequence()->getRelpersistence());
+ }
+
+ public function test_create_unlogged_sequence() : void
+ {
+ $builder = CreateSequenceBuilder::createUnlogged()
+ ->sequence('fast_seq');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateSeqStmt::class, $ast);
+ /** @phpstan-ignore method.nonObject (protobuf returns nullable but we know it's set) */
+ self::assertSame('u', $ast->getSequence()->getRelpersistence());
+ }
+
+ public function test_immutability() : void
+ {
+ $original = CreateSequenceBuilder::create()->sequence('test_seq');
+ $modified = $original->startWith(100);
+
+ self::assertEmpty($original->toAst()->getOptions());
+ self::assertNotEmpty($modified->toAst()->getOptions());
+ }
+
+ public function test_simple_create_sequence() : void
+ {
+ $builder = CreateSequenceBuilder::create()
+ ->sequence('user_id_seq');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateSeqStmt::class, $ast);
+ /** @phpstan-ignore method.nonObject (protobuf returns nullable but we know it's set) */
+ self::assertSame('user_id_seq', $ast->getSequence()->getRelname());
+ /** @phpstan-ignore method.nonObject (protobuf returns nullable but we know it's set) */
+ self::assertSame('p', $ast->getSequence()->getRelpersistence());
+ }
+}
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
new file mode 100644
index 000000000..d4c843168
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/CreateTable/CreateTableBuilderTest.php
@@ -0,0 +1,217 @@
+column(ColumnDefinition::create('id', DataType::integer()))
+ ->ifNotExists();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateStmt::class, $ast);
+ self::assertTrue($ast->getIfNotExists());
+ }
+
+ public function test_create_table_inherits() : void
+ {
+ $builder = CreateTableBuilder::create('employees')
+ ->column(ColumnDefinition::create('department', DataType::text()))
+ ->inherits('persons');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateStmt::class, $ast);
+ self::assertCount(1, $ast->getInhRelations());
+ self::assertSame('persons', $ast->getInhRelations()[0]->getRangeVar()->getRelname());
+ }
+
+ public function test_create_table_inherits_multiple() : void
+ {
+ $builder = CreateTableBuilder::create('employees')
+ ->column(ColumnDefinition::create('department', DataType::text()))
+ ->inherits('persons', 'contacts');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateStmt::class, $ast);
+ self::assertCount(2, $ast->getInhRelations());
+ }
+
+ public function test_create_table_partition_by_hash() : void
+ {
+ $builder = CreateTableBuilder::create('orders')
+ ->column(ColumnDefinition::create('id', DataType::integer()))
+ ->partitionByHash('id');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateStmt::class, $ast);
+ self::assertTrue($ast->hasPartspec());
+ self::assertSame(PartitionStrategy::PARTITION_STRATEGY_HASH, $ast->getPartspec()->getStrategy());
+ }
+
+ public function test_create_table_partition_by_list() : void
+ {
+ $builder = CreateTableBuilder::create('sales')
+ ->column(ColumnDefinition::create('region', DataType::text()))
+ ->partitionByList('region');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateStmt::class, $ast);
+ self::assertTrue($ast->hasPartspec());
+ self::assertSame(PartitionStrategy::PARTITION_STRATEGY_LIST, $ast->getPartspec()->getStrategy());
+ self::assertCount(1, $ast->getPartspec()->getPartParams());
+ }
+
+ public function test_create_table_partition_by_range() : void
+ {
+ $builder = CreateTableBuilder::create('logs')
+ ->column(ColumnDefinition::create('created_at', DataType::timestamp()))
+ ->partitionByRange('created_at');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateStmt::class, $ast);
+ self::assertTrue($ast->hasPartspec());
+ self::assertSame(PartitionStrategy::PARTITION_STRATEGY_RANGE, $ast->getPartspec()->getStrategy());
+ }
+
+ public function test_create_table_tablespace() : void
+ {
+ $builder = CreateTableBuilder::create('users')
+ ->column(ColumnDefinition::create('id', DataType::integer()))
+ ->tablespace('fast_storage');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateStmt::class, $ast);
+ self::assertSame('fast_storage', $ast->getTablespacename());
+ }
+
+ public function test_create_table_temporary() : void
+ {
+ $builder = CreateTableBuilder::create('temp_users')
+ ->column(ColumnDefinition::create('id', DataType::integer()))
+ ->temporary();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateStmt::class, $ast);
+ self::assertSame('t', $ast->getRelation()->getRelpersistence());
+ self::assertSame(OnCommitAction::ONCOMMIT_DROP, $ast->getOncommit());
+ }
+
+ public function test_create_table_unlogged() : void
+ {
+ $builder = CreateTableBuilder::create('unlogged_users')
+ ->column(ColumnDefinition::create('id', DataType::integer()))
+ ->unlogged();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateStmt::class, $ast);
+ self::assertSame('u', $ast->getRelation()->getRelpersistence());
+ }
+
+ 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)))
+ ->constraint(PrimaryKeyConstraint::create('id'))
+ ->constraint(UniqueConstraint::create('email'));
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateStmt::class, $ast);
+ // 2 columns + 2 constraints = 4 table elements
+ self::assertCount(4, $ast->getTableElts());
+ // Last 2 elements should be constraints
+ self::assertTrue($ast->getTableElts()[2]->hasConstraint());
+ self::assertTrue($ast->getTableElts()[3]->hasConstraint());
+ }
+
+ 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()))
+ ->constraint(ForeignKeyConstraint::create(['user_id'], 'users', ['id']));
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateStmt::class, $ast);
+ // 2 columns + 1 constraint = 3 table elements
+ self::assertCount(3, $ast->getTableElts());
+ // Last element should be the foreign key constraint
+ self::assertTrue($ast->getTableElts()[2]->hasConstraint());
+ }
+
+ 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());
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateStmt::class, $ast);
+ self::assertCount(3, $ast->getTableElts());
+ }
+
+ public function test_create_table_with_schema() : void
+ {
+ $builder = CreateTableBuilder::create('users', 'public')
+ ->column(ColumnDefinition::create('id', DataType::integer()));
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateStmt::class, $ast);
+ self::assertSame('public', $ast->getRelation()->getSchemaname());
+ self::assertSame('users', $ast->getRelation()->getRelname());
+ }
+
+ public function test_immutability() : void
+ {
+ $original = CreateTableBuilder::create('users')
+ ->column(ColumnDefinition::create('id', DataType::integer()));
+ $modified = $original->ifNotExists();
+
+ self::assertFalse($original->toAst()->getIfNotExists());
+ self::assertTrue($modified->toAst()->getIfNotExists());
+ }
+
+ public function test_simple_create_table() : void
+ {
+ $builder = CreateTableBuilder::create('users')
+ ->column(ColumnDefinition::create('id', DataType::integer()));
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateStmt::class, $ast);
+ self::assertSame('users', $ast->getRelation()->getRelname());
+ self::assertCount(1, $ast->getTableElts());
+ self::assertSame('p', $ast->getRelation()->getRelpersistence());
+ }
+}
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
new file mode 100644
index 000000000..26f827e93
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/CreateTableAs/CreateTableAsBuilderTest.php
@@ -0,0 +1,131 @@
+select(new RawExpression('1'));
+
+ $builder = CreateTableAsBuilder::create('new_table', $select)
+ ->ifNotExists();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateTableAsStmt::class, $ast);
+ self::assertTrue($ast->getIfNotExists());
+ }
+
+ public function test_create_table_as_with_column_names() : void
+ {
+ $select = SelectBuilder::create()
+ ->select(new RawExpression('id'), new RawExpression('name'));
+
+ $builder = CreateTableAsBuilder::create('new_table', $select)
+ ->columnNames('user_id', 'user_name');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateTableAsStmt::class, $ast);
+ self::assertCount(2, $ast->getInto()->getColNames());
+ self::assertSame('user_id', $ast->getInto()->getColNames()[0]->getString()->getSval());
+ self::assertSame('user_name', $ast->getInto()->getColNames()[1]->getString()->getSval());
+ }
+
+ public function test_create_table_as_with_no_data() : void
+ {
+ $select = SelectBuilder::create()
+ ->select(new RawExpression('id'), new RawExpression('name'))
+ ->from(new Table('users'));
+
+ $builder = CreateTableAsBuilder::create('users_copy', $select)
+ ->withNoData();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateTableAsStmt::class, $ast);
+ self::assertTrue($ast->getInto()->getSkipData());
+ }
+
+ public function test_create_table_as_with_schema() : void
+ {
+ $select = SelectBuilder::create()
+ ->select(new RawExpression('id'), new RawExpression('email'))
+ ->from(new Table('users'));
+
+ $builder = CreateTableAsBuilder::create('new_table', $select, 'archive');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateTableAsStmt::class, $ast);
+ self::assertSame('archive', $ast->getInto()->getRel()->getSchemaname());
+ self::assertSame('new_table', $ast->getInto()->getRel()->getRelname());
+ }
+
+ public function test_immutability() : void
+ {
+ $select = SelectBuilder::create()
+ ->select(new RawExpression('1'));
+
+ $original = CreateTableAsBuilder::create('new_table', $select);
+ $modified = $original->ifNotExists();
+
+ self::assertFalse($original->toAst()->getIfNotExists());
+ self::assertTrue($modified->toAst()->getIfNotExists());
+ }
+
+ public function test_simple_create_table_as() : void
+ {
+ $select = SelectBuilder::create()
+ ->select(new RawExpression('id'), new RawExpression('name'))
+ ->from(new Table('users'));
+
+ $builder = CreateTableAsBuilder::create('users_copy', $select);
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateTableAsStmt::class, $ast);
+ self::assertSame('users_copy', $ast->getInto()->getRel()->getRelname());
+ self::assertSame(ObjectType::OBJECT_TABLE, $ast->getObjtype());
+ self::assertTrue($ast->hasQuery());
+ }
+
+ public function test_with_all_options() : void
+ {
+ $select = SelectBuilder::create()
+ ->select(new RawExpression('id'), new RawExpression('name'))
+ ->from(new Table('users'));
+
+ $builder = CreateTableAsBuilder::create('users_backup', $select, 'archive')
+ ->columnNames('user_id', 'user_name')
+ ->ifNotExists()
+ ->withNoData();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateTableAsStmt::class, $ast);
+ self::assertSame('archive', $ast->getInto()->getRel()->getSchemaname());
+ self::assertSame('users_backup', $ast->getInto()->getRel()->getRelname());
+ self::assertCount(2, $ast->getInto()->getColNames());
+ self::assertTrue($ast->getIfNotExists());
+ self::assertTrue($ast->getInto()->getSkipData());
+ }
+}
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/DataTypeTest.php
new file mode 100644
index 000000000..ffbc99abd
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/DataTypeTest.php
@@ -0,0 +1,352 @@
+toAst();
+
+ self::assertInstanceOf(TypeName::class, $ast);
+ self::assertCount(2, $ast->getNames());
+ self::assertCount(1, $ast->getArrayBounds());
+ }
+
+ public function test_bigint() : void
+ {
+ $type = DataType::bigint();
+
+ $ast = $type->toAst();
+
+ self::assertInstanceOf(TypeName::class, $ast);
+ self::assertCount(2, $ast->getNames());
+ self::assertSame('pg_catalog', $ast->getNames()[0]->getString()->getSval());
+ self::assertSame('int8', $ast->getNames()[1]->getString()->getSval());
+ }
+
+ public function test_bigserial() : void
+ {
+ $type = DataType::bigserial();
+
+ $ast = $type->toAst();
+
+ self::assertInstanceOf(TypeName::class, $ast);
+ self::assertCount(1, $ast->getNames());
+ self::assertSame('bigserial', $ast->getNames()[0]->getString()->getSval());
+ }
+
+ public function test_boolean() : void
+ {
+ $type = DataType::boolean();
+
+ $ast = $type->toAst();
+
+ self::assertInstanceOf(TypeName::class, $ast);
+ self::assertCount(2, $ast->getNames());
+ self::assertSame('pg_catalog', $ast->getNames()[0]->getString()->getSval());
+ self::assertSame('bool', $ast->getNames()[1]->getString()->getSval());
+ }
+
+ public function test_bytea() : void
+ {
+ $type = DataType::bytea();
+
+ $ast = $type->toAst();
+
+ self::assertInstanceOf(TypeName::class, $ast);
+ self::assertSame('bytea', $ast->getNames()[1]->getString()->getSval());
+ }
+
+ public function test_char_with_length() : void
+ {
+ $type = DataType::char(10);
+
+ $ast = $type->toAst();
+
+ self::assertInstanceOf(TypeName::class, $ast);
+ self::assertSame('bpchar', $ast->getNames()[1]->getString()->getSval());
+ self::assertCount(1, $ast->getTypmods());
+ self::assertSame(10, $ast->getTypmods()[0]->getAConst()->getIval()->getIval());
+ }
+
+ public function test_cidr() : void
+ {
+ $type = DataType::cidr();
+
+ $ast = $type->toAst();
+
+ self::assertInstanceOf(TypeName::class, $ast);
+ self::assertSame('cidr', $ast->getNames()[1]->getString()->getSval());
+ }
+
+ public function test_custom_type_with_schema() : void
+ {
+ $type = DataType::custom('my_type', 'my_schema');
+
+ $ast = $type->toAst();
+
+ self::assertInstanceOf(TypeName::class, $ast);
+ self::assertCount(2, $ast->getNames());
+ self::assertSame('my_schema', $ast->getNames()[0]->getString()->getSval());
+ self::assertSame('my_type', $ast->getNames()[1]->getString()->getSval());
+ }
+
+ public function test_custom_type_without_schema() : void
+ {
+ $type = DataType::custom('my_type');
+
+ $ast = $type->toAst();
+
+ self::assertInstanceOf(TypeName::class, $ast);
+ self::assertCount(1, $ast->getNames());
+ self::assertSame('my_type', $ast->getNames()[0]->getString()->getSval());
+ }
+
+ public function test_date() : void
+ {
+ $type = DataType::date();
+
+ $ast = $type->toAst();
+
+ self::assertInstanceOf(TypeName::class, $ast);
+ self::assertSame('date', $ast->getNames()[1]->getString()->getSval());
+ }
+
+ public function test_double_precision() : void
+ {
+ $type = DataType::doublePrecision();
+
+ $ast = $type->toAst();
+
+ self::assertInstanceOf(TypeName::class, $ast);
+ self::assertSame('float8', $ast->getNames()[1]->getString()->getSval());
+ }
+
+ public function test_inet() : void
+ {
+ $type = DataType::inet();
+
+ $ast = $type->toAst();
+
+ self::assertInstanceOf(TypeName::class, $ast);
+ self::assertSame('inet', $ast->getNames()[1]->getString()->getSval());
+ }
+
+ public function test_integer() : void
+ {
+ $type = DataType::integer();
+
+ $ast = $type->toAst();
+
+ self::assertInstanceOf(TypeName::class, $ast);
+ self::assertCount(2, $ast->getNames());
+ self::assertSame('pg_catalog', $ast->getNames()[0]->getString()->getSval());
+ self::assertSame('int4', $ast->getNames()[1]->getString()->getSval());
+ }
+
+ public function test_interval() : void
+ {
+ $type = DataType::interval();
+
+ $ast = $type->toAst();
+
+ self::assertInstanceOf(TypeName::class, $ast);
+ self::assertSame('interval', $ast->getNames()[1]->getString()->getSval());
+ }
+
+ public function test_json() : void
+ {
+ $type = DataType::json();
+
+ $ast = $type->toAst();
+
+ self::assertInstanceOf(TypeName::class, $ast);
+ self::assertSame('json', $ast->getNames()[1]->getString()->getSval());
+ }
+
+ public function test_jsonb() : void
+ {
+ $type = DataType::jsonb();
+
+ $ast = $type->toAst();
+
+ self::assertInstanceOf(TypeName::class, $ast);
+ self::assertSame('jsonb', $ast->getNames()[1]->getString()->getSval());
+ }
+
+ public function test_macaddr() : void
+ {
+ $type = DataType::macaddr();
+
+ $ast = $type->toAst();
+
+ self::assertInstanceOf(TypeName::class, $ast);
+ self::assertSame('macaddr', $ast->getNames()[1]->getString()->getSval());
+ }
+
+ public function test_numeric_with_precision_and_scale() : void
+ {
+ $type = DataType::numeric(10, 2);
+
+ $ast = $type->toAst();
+
+ self::assertInstanceOf(TypeName::class, $ast);
+ self::assertSame('numeric', $ast->getNames()[1]->getString()->getSval());
+ self::assertCount(2, $ast->getTypmods());
+ self::assertSame(10, $ast->getTypmods()[0]->getAConst()->getIval()->getIval());
+ self::assertSame(2, $ast->getTypmods()[1]->getAConst()->getIval()->getIval());
+ }
+
+ public function test_numeric_with_precision_only() : void
+ {
+ $type = DataType::numeric(10);
+
+ $ast = $type->toAst();
+
+ self::assertInstanceOf(TypeName::class, $ast);
+ self::assertSame('numeric', $ast->getNames()[1]->getString()->getSval());
+ self::assertCount(1, $ast->getTypmods());
+ self::assertSame(10, $ast->getTypmods()[0]->getAConst()->getIval()->getIval());
+ }
+
+ public function test_numeric_without_precision() : void
+ {
+ $type = DataType::numeric();
+
+ $ast = $type->toAst();
+
+ self::assertInstanceOf(TypeName::class, $ast);
+ self::assertSame('numeric', $ast->getNames()[1]->getString()->getSval());
+ self::assertCount(0, $ast->getTypmods());
+ }
+
+ public function test_real() : void
+ {
+ $type = DataType::real();
+
+ $ast = $type->toAst();
+
+ self::assertInstanceOf(TypeName::class, $ast);
+ self::assertSame('float4', $ast->getNames()[1]->getString()->getSval());
+ }
+
+ public function test_serial() : void
+ {
+ $type = DataType::serial();
+
+ $ast = $type->toAst();
+
+ self::assertInstanceOf(TypeName::class, $ast);
+ self::assertCount(1, $ast->getNames());
+ self::assertSame('serial', $ast->getNames()[0]->getString()->getSval());
+ }
+
+ public function test_smallint() : void
+ {
+ $type = DataType::smallint();
+
+ $ast = $type->toAst();
+
+ self::assertInstanceOf(TypeName::class, $ast);
+ self::assertSame('int2', $ast->getNames()[1]->getString()->getSval());
+ }
+
+ public function test_text() : void
+ {
+ $type = DataType::text();
+
+ $ast = $type->toAst();
+
+ self::assertInstanceOf(TypeName::class, $ast);
+ self::assertSame('text', $ast->getNames()[1]->getString()->getSval());
+ }
+
+ public function test_time_with_precision() : void
+ {
+ $type = DataType::time(3);
+
+ $ast = $type->toAst();
+
+ self::assertInstanceOf(TypeName::class, $ast);
+ self::assertSame('time', $ast->getNames()[1]->getString()->getSval());
+ self::assertCount(1, $ast->getTypmods());
+ self::assertSame(3, $ast->getTypmods()[0]->getAConst()->getIval()->getIval());
+ }
+
+ public function test_time_without_precision() : void
+ {
+ $type = DataType::time();
+
+ $ast = $type->toAst();
+
+ self::assertInstanceOf(TypeName::class, $ast);
+ self::assertSame('time', $ast->getNames()[1]->getString()->getSval());
+ self::assertCount(0, $ast->getTypmods());
+ }
+
+ public function test_timestamp_with_precision() : void
+ {
+ $type = DataType::timestamp(6);
+
+ $ast = $type->toAst();
+
+ self::assertInstanceOf(TypeName::class, $ast);
+ self::assertSame('timestamp', $ast->getNames()[1]->getString()->getSval());
+ self::assertCount(1, $ast->getTypmods());
+ self::assertSame(6, $ast->getTypmods()[0]->getAConst()->getIval()->getIval());
+ }
+
+ public function test_timestamp_without_precision() : void
+ {
+ $type = DataType::timestamp();
+
+ $ast = $type->toAst();
+
+ self::assertInstanceOf(TypeName::class, $ast);
+ self::assertSame('timestamp', $ast->getNames()[1]->getString()->getSval());
+ self::assertCount(0, $ast->getTypmods());
+ }
+
+ public function test_timestamptz_with_precision() : void
+ {
+ $type = DataType::timestamptz(3);
+
+ $ast = $type->toAst();
+
+ self::assertInstanceOf(TypeName::class, $ast);
+ self::assertSame('timestamptz', $ast->getNames()[1]->getString()->getSval());
+ self::assertCount(1, $ast->getTypmods());
+ self::assertSame(3, $ast->getTypmods()[0]->getAConst()->getIval()->getIval());
+ }
+
+ public function test_uuid() : void
+ {
+ $type = DataType::uuid();
+
+ $ast = $type->toAst();
+
+ self::assertInstanceOf(TypeName::class, $ast);
+ self::assertSame('uuid', $ast->getNames()[1]->getString()->getSval());
+ }
+
+ public function test_varchar_with_length() : void
+ {
+ $type = DataType::varchar(255);
+
+ $ast = $type->toAst();
+
+ self::assertInstanceOf(TypeName::class, $ast);
+ self::assertSame('varchar', $ast->getNames()[1]->getString()->getSval());
+ self::assertCount(1, $ast->getTypmods());
+ self::assertSame(255, $ast->getTypmods()[0]->getAConst()->getIval()->getIval());
+ }
+}
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
new file mode 100644
index 000000000..392e4c3ca
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Domain/DomainBuilderTest.php
@@ -0,0 +1,334 @@
+addConstraint('valid_email', "VALUE ~ '^.+@.+$'");
+
+ $ast = $builder->toAst();
+
+ self::assertSame('C', $ast->getSubtype());
+ self::assertSame('valid_email', $ast->getName());
+ }
+
+ public function test_alter_domain_ast_type() : void
+ {
+ $builder = AlterDomainBuilder::create('email')
+ ->setNotNull();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterDomainStmt::class, $ast);
+ }
+
+ public function test_alter_domain_cascade() : void
+ {
+ $builder = AlterDomainBuilder::create('email')
+ ->dropConstraint('valid_email')
+ ->cascade();
+
+ $ast = $builder->toAst();
+
+ self::assertSame(DropBehavior::DROP_CASCADE, $ast->getBehavior());
+ }
+
+ public function test_alter_domain_drop_constraint() : void
+ {
+ $builder = AlterDomainBuilder::create('email')
+ ->dropConstraint('valid_email');
+
+ $ast = $builder->toAst();
+
+ self::assertSame('X', $ast->getSubtype());
+ self::assertSame('valid_email', $ast->getName());
+ }
+
+ public function test_alter_domain_drop_default() : void
+ {
+ $builder = AlterDomainBuilder::create('email')
+ ->dropDefault();
+
+ $ast = $builder->toAst();
+
+ self::assertSame('T', $ast->getSubtype());
+ }
+
+ public function test_alter_domain_drop_not_null() : void
+ {
+ $builder = AlterDomainBuilder::create('email')
+ ->dropNotNull();
+
+ $ast = $builder->toAst();
+
+ self::assertSame('N', $ast->getSubtype());
+ }
+
+ public function test_alter_domain_restrict() : void
+ {
+ $builder = AlterDomainBuilder::create('email')
+ ->dropConstraint('valid_email')
+ ->restrict();
+
+ $ast = $builder->toAst();
+
+ self::assertSame(DropBehavior::DROP_RESTRICT, $ast->getBehavior());
+ }
+
+ public function test_alter_domain_set_default() : void
+ {
+ $builder = AlterDomainBuilder::create('email')
+ ->setDefault("'default@example.com'");
+
+ $ast = $builder->toAst();
+
+ self::assertSame('T', $ast->getSubtype());
+ self::assertNotNull($ast->getDef());
+ }
+
+ public function test_alter_domain_set_not_null() : void
+ {
+ $builder = AlterDomainBuilder::create('email')
+ ->setNotNull();
+
+ $ast = $builder->toAst();
+
+ self::assertSame('O', $ast->getSubtype());
+ }
+
+ public function test_alter_domain_validate_constraint() : void
+ {
+ $builder = AlterDomainBuilder::create('email')
+ ->validateConstraint('valid_email');
+
+ $ast = $builder->toAst();
+
+ self::assertSame('V', $ast->getSubtype());
+ self::assertSame('valid_email', $ast->getName());
+ }
+
+ public function test_create_domain_ast_type() : void
+ {
+ $builder = CreateDomainBuilder::create('email')
+ ->as(sql_type_text());
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateDomainStmt::class, $ast);
+ }
+
+ public function test_create_domain_sets_name() : void
+ {
+ $builder = CreateDomainBuilder::create('email')
+ ->as(sql_type_text());
+
+ $ast = $builder->toAst();
+ $domainname = $ast->getDomainname();
+
+ self::assertCount(1, $domainname);
+ }
+
+ public function test_create_domain_sets_type() : void
+ {
+ $builder = CreateDomainBuilder::create('email')
+ ->as(sql_type_text());
+
+ $ast = $builder->toAst();
+ $typeName = $ast->getTypeName();
+
+ self::assertNotNull($typeName);
+ self::assertCount(2, $typeName->getNames()); // pg_catalog.text = 2 parts
+ }
+
+ public function test_create_domain_with_check() : void
+ {
+ $builder = CreateDomainBuilder::create('email')
+ ->as(sql_type_text())
+ ->check("VALUE ~ '^.+@.+$'");
+
+ $ast = $builder->toAst();
+ $constraints = $ast->getConstraints();
+
+ self::assertCount(1, $constraints);
+
+ $constraint = $constraints[0]->getConstraint();
+ self::assertNotNull($constraint);
+ self::assertSame(ConstrType::CONSTR_CHECK, $constraint->getContype());
+ }
+
+ public function test_create_domain_with_collation() : void
+ {
+ $builder = CreateDomainBuilder::create('email')
+ ->as(sql_type_text())
+ ->collate('en_US');
+
+ $ast = $builder->toAst();
+
+ self::assertNotNull($ast->getCollClause());
+ }
+
+ public function test_create_domain_with_default() : void
+ {
+ $builder = CreateDomainBuilder::create('email')
+ ->as(sql_type_text())
+ ->default("'default@example.com'");
+
+ $ast = $builder->toAst();
+ $constraints = $ast->getConstraints();
+
+ self::assertCount(1, $constraints);
+
+ $constraint = $constraints[0]->getConstraint();
+ self::assertNotNull($constraint);
+ self::assertSame(ConstrType::CONSTR_DEFAULT, $constraint->getContype());
+ }
+
+ public function test_create_domain_with_multiple_constraints() : void
+ {
+ $builder = CreateDomainBuilder::create('email')
+ ->as(sql_type_text())
+ ->notNull()
+ ->check("VALUE ~ '^.+@.+$'");
+
+ $ast = $builder->toAst();
+ $constraints = $ast->getConstraints();
+
+ self::assertCount(2, $constraints);
+ }
+
+ public function test_create_domain_with_named_constraint() : void
+ {
+ $builder = CreateDomainBuilder::create('email')
+ ->as(sql_type_text())
+ ->constraint('valid_email')
+ ->check("VALUE ~ '^.+@.+$'");
+
+ $ast = $builder->toAst();
+ $constraints = $ast->getConstraints();
+
+ self::assertCount(1, $constraints);
+
+ $constraint = $constraints[0]->getConstraint();
+ self::assertNotNull($constraint);
+ self::assertSame('valid_email', $constraint->getConname());
+ }
+
+ public function test_create_domain_with_not_null() : void
+ {
+ $builder = CreateDomainBuilder::create('email')
+ ->as(sql_type_text())
+ ->notNull();
+
+ $ast = $builder->toAst();
+ $constraints = $ast->getConstraints();
+
+ self::assertCount(1, $constraints);
+
+ $constraint = $constraints[0]->getConstraint();
+ self::assertNotNull($constraint);
+ self::assertSame(ConstrType::CONSTR_NOTNULL, $constraint->getContype());
+ }
+
+ public function test_create_domain_with_null() : void
+ {
+ $builder = CreateDomainBuilder::create('email')
+ ->as(sql_type_text())
+ ->null();
+
+ $ast = $builder->toAst();
+ $constraints = $ast->getConstraints();
+
+ self::assertCount(1, $constraints);
+
+ $constraint = $constraints[0]->getConstraint();
+ self::assertNotNull($constraint);
+ self::assertSame(ConstrType::CONSTR_NULL, $constraint->getContype());
+ }
+
+ public function test_create_domain_with_schema() : void
+ {
+ $builder = CreateDomainBuilder::create('public.email')
+ ->as(sql_type_text());
+
+ $ast = $builder->toAst();
+ $domainname = $ast->getDomainname();
+
+ self::assertCount(2, $domainname);
+ }
+
+ public function test_drop_domain_ast_type() : void
+ {
+ $builder = DropDomainBuilder::create('email');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(DropStmt::class, $ast);
+ self::assertSame(ObjectType::OBJECT_DOMAIN, $ast->getRemoveType());
+ }
+
+ public function test_drop_domain_cascade() : void
+ {
+ $builder = DropDomainBuilder::create('email')
+ ->cascade();
+
+ $ast = $builder->toAst();
+
+ self::assertSame(DropBehavior::DROP_CASCADE, $ast->getBehavior());
+ }
+
+ public function test_drop_domain_if_exists() : void
+ {
+ $builder = DropDomainBuilder::create('email')
+ ->ifExists();
+
+ $ast = $builder->toAst();
+
+ self::assertTrue($ast->getMissingOk());
+ }
+
+ public function test_drop_domain_immutability() : void
+ {
+ $original = DropDomainBuilder::create('email');
+ $modified = $original->ifExists();
+
+ self::assertFalse($original->toAst()->getMissingOk());
+ self::assertTrue($modified->toAst()->getMissingOk());
+ }
+
+ public function test_drop_domain_multiple_domains() : void
+ {
+ $builder = DropDomainBuilder::create('email', 'phone', 'url');
+
+ $ast = $builder->toAst();
+
+ self::assertCount(3, $ast->getObjects());
+ }
+
+ public function test_drop_domain_restrict() : void
+ {
+ $builder = DropDomainBuilder::create('email')
+ ->restrict();
+
+ $ast = $builder->toAst();
+
+ self::assertSame(DropBehavior::DROP_RESTRICT, $ast->getBehavior());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/DropSequence/DropSequenceBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/DropSequence/DropSequenceBuilderTest.php
new file mode 100644
index 000000000..c4156a4e8
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/DropSequence/DropSequenceBuilderTest.php
@@ -0,0 +1,119 @@
+sequence('user_id_seq', 'order_id_seq', 'product_id_seq');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(DropStmt::class, $ast);
+ self::assertCount(3, $ast->getObjects());
+ }
+
+ public function test_drop_sequence_cascade() : void
+ {
+ $builder = DropSequenceBuilder::create()
+ ->sequence('user_id_seq')
+ ->cascade();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(DropStmt::class, $ast);
+ self::assertSame(DropBehavior::DROP_CASCADE, $ast->getBehavior());
+ }
+
+ public function test_drop_sequence_if_exists() : void
+ {
+ $builder = DropSequenceBuilder::create()
+ ->sequence('user_id_seq')
+ ->ifExists();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(DropStmt::class, $ast);
+ self::assertTrue($ast->getMissingOk());
+ }
+
+ public function test_drop_sequence_if_exists_cascade() : void
+ {
+ $builder = DropSequenceBuilder::create()
+ ->sequence('user_id_seq')
+ ->ifExists()
+ ->cascade();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(DropStmt::class, $ast);
+ self::assertTrue($ast->getMissingOk());
+ self::assertSame(DropBehavior::DROP_CASCADE, $ast->getBehavior());
+ }
+
+ public function test_drop_sequence_restrict() : void
+ {
+ $builder = DropSequenceBuilder::create()
+ ->sequence('user_id_seq')
+ ->restrict();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(DropStmt::class, $ast);
+ self::assertSame(DropBehavior::DROP_RESTRICT, $ast->getBehavior());
+ }
+
+ public function test_drop_sequence_with_schema() : void
+ {
+ $builder = DropSequenceBuilder::create()
+ ->sequence('public.user_id_seq');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(DropStmt::class, $ast);
+ self::assertCount(1, $ast->getObjects());
+ /** @phpstan-ignore method.nonObject (protobuf returns nullable but we know it's set) */
+ self::assertCount(2, $ast->getObjects()[0]->getList()->getItems() ?? []);
+ /** @phpstan-ignore method.nonObject (protobuf returns nullable but we know it's set) */
+ self::assertSame('public', $ast->getObjects()[0]->getList()->getItems()[0]->getString()?->getSval());
+ /** @phpstan-ignore method.nonObject (protobuf returns nullable but we know it's set) */
+ self::assertSame('user_id_seq', $ast->getObjects()[0]->getList()->getItems()[1]->getString()?->getSval());
+ }
+
+ public function test_immutability() : void
+ {
+ $original = DropSequenceBuilder::create()->sequence('test_seq');
+ $modified = $original->cascade();
+
+ self::assertSame(DropBehavior::DROP_BEHAVIOR_UNDEFINED, $original->toAst()->getBehavior());
+ self::assertSame(DropBehavior::DROP_CASCADE, $modified->toAst()->getBehavior());
+ }
+
+ public function test_simple_drop_sequence() : void
+ {
+ $builder = DropSequenceBuilder::create()
+ ->sequence('user_id_seq');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(DropStmt::class, $ast);
+ self::assertSame(ObjectType::OBJECT_SEQUENCE, $ast->getRemoveType());
+ self::assertCount(1, $ast->getObjects());
+ self::assertSame('user_id_seq', $ast->getObjects()[0]->getList()?->getItems()[0]->getString()?->getSval());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/DropTable/DropTableBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/DropTable/DropTableBuilderTest.php
new file mode 100644
index 000000000..8f57f0f1c
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/DropTable/DropTableBuilderTest.php
@@ -0,0 +1,109 @@
+toAst();
+
+ self::assertInstanceOf(DropStmt::class, $ast);
+ self::assertCount(3, $ast->getObjects());
+ }
+
+ public function test_drop_table_cascade() : void
+ {
+ $builder = DropTableBuilder::create('users')
+ ->cascade();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(DropStmt::class, $ast);
+ self::assertSame(DropBehavior::DROP_CASCADE, $ast->getBehavior());
+ }
+
+ public function test_drop_table_if_exists() : void
+ {
+ $builder = DropTableBuilder::create('users')
+ ->ifExists();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(DropStmt::class, $ast);
+ self::assertTrue($ast->getMissingOk());
+ }
+
+ public function test_drop_table_if_exists_cascade() : void
+ {
+ $builder = DropTableBuilder::create('users')
+ ->ifExists()
+ ->cascade();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(DropStmt::class, $ast);
+ self::assertTrue($ast->getMissingOk());
+ self::assertSame(DropBehavior::DROP_CASCADE, $ast->getBehavior());
+ }
+
+ public function test_drop_table_restrict() : void
+ {
+ $builder = DropTableBuilder::create('users')
+ ->restrict();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(DropStmt::class, $ast);
+ self::assertSame(DropBehavior::DROP_RESTRICT, $ast->getBehavior());
+ }
+
+ public function test_drop_table_with_schema() : void
+ {
+ $builder = DropTableBuilder::create('public.users');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(DropStmt::class, $ast);
+ self::assertCount(1, $ast->getObjects());
+ self::assertCount(2, $ast->getObjects()[0]->getList()->getItems());
+ self::assertSame('public', $ast->getObjects()[0]->getList()->getItems()[0]->getString()->getSval());
+ self::assertSame('users', $ast->getObjects()[0]->getList()->getItems()[1]->getString()->getSval());
+ }
+
+ public function test_immutability() : void
+ {
+ $original = DropTableBuilder::create('users');
+ $modified = $original->ifExists();
+
+ self::assertFalse($original->toAst()->getMissingOk());
+ self::assertTrue($modified->toAst()->getMissingOk());
+ }
+
+ public function test_simple_drop_table() : void
+ {
+ $builder = DropTableBuilder::create('users');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(DropStmt::class, $ast);
+ self::assertSame(ObjectType::OBJECT_TABLE, $ast->getRemoveType());
+ self::assertCount(1, $ast->getObjects());
+ self::assertSame('users', $ast->getObjects()[0]->getList()->getItems()[0]->getString()->getSval());
+ }
+}
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
new file mode 100644
index 000000000..3f569a211
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Extension/ExtensionBuilderTest.php
@@ -0,0 +1,254 @@
+addFunction('ST_Distance');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterExtensionContentsStmt::class, $ast);
+ self::assertSame(ObjectType::OBJECT_FUNCTION, $ast->getObjtype());
+ self::assertSame(1, $ast->getAction());
+ }
+
+ public function test_alter_extension_add_table_ast_type() : void
+ {
+ $builder = AlterExtensionBuilder::create('postgis')
+ ->addTable('spatial_ref_sys');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterExtensionContentsStmt::class, $ast);
+ self::assertSame(ObjectType::OBJECT_TABLE, $ast->getObjtype());
+ self::assertSame(1, $ast->getAction());
+ }
+
+ public function test_alter_extension_drop_function_ast_type() : void
+ {
+ $builder = AlterExtensionBuilder::create('postgis')
+ ->dropFunction('ST_Distance');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterExtensionContentsStmt::class, $ast);
+ self::assertSame(ObjectType::OBJECT_FUNCTION, $ast->getObjtype());
+ self::assertSame(-1, $ast->getAction());
+ }
+
+ public function test_alter_extension_drop_table_ast_type() : void
+ {
+ $builder = AlterExtensionBuilder::create('postgis')
+ ->dropTable('spatial_ref_sys');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterExtensionContentsStmt::class, $ast);
+ self::assertSame(ObjectType::OBJECT_TABLE, $ast->getObjtype());
+ self::assertSame(-1, $ast->getAction());
+ }
+
+ public function test_alter_extension_update_ast_type() : void
+ {
+ $builder = AlterExtensionBuilder::create('postgis')
+ ->update();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterExtensionStmt::class, $ast);
+ }
+
+ public function test_alter_extension_update_sets_name() : void
+ {
+ $builder = AlterExtensionBuilder::create('postgis')
+ ->update();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterExtensionStmt::class, $ast);
+ self::assertSame('postgis', $ast->getExtname());
+ }
+
+ public function test_alter_extension_update_to_sets_version() : void
+ {
+ $builder = AlterExtensionBuilder::create('postgis')
+ ->updateTo('3.1');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterExtensionStmt::class, $ast);
+
+ $options = $ast->getOptions();
+ self::assertCount(1, $options);
+
+ $defElem = $options[0]->getDefElem();
+ self::assertNotNull($defElem);
+ self::assertSame('new_version', $defElem->getDefname());
+ }
+
+ public function test_create_extension_ast_type() : void
+ {
+ $builder = CreateExtensionBuilder::create('uuid-ossp');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateExtensionStmt::class, $ast);
+ }
+
+ public function test_create_extension_cascade_sets_option() : void
+ {
+ $builder = CreateExtensionBuilder::create('postgis')
+ ->cascade();
+
+ $ast = $builder->toAst();
+ $options = $ast->getOptions();
+
+ self::assertCount(1, $options);
+
+ $defElem = $options[0]->getDefElem();
+ self::assertNotNull($defElem);
+ self::assertSame('cascade', $defElem->getDefname());
+ }
+
+ public function test_create_extension_if_not_exists_sets_flag() : void
+ {
+ $builder = CreateExtensionBuilder::create('postgis')
+ ->ifNotExists();
+
+ $ast = $builder->toAst();
+
+ self::assertTrue($ast->getIfNotExists());
+ }
+
+ public function test_create_extension_immutability() : void
+ {
+ $original = CreateExtensionBuilder::create('postgis');
+ $modified = $original->ifNotExists();
+
+ self::assertFalse($original->toAst()->getIfNotExists());
+ self::assertTrue($modified->toAst()->getIfNotExists());
+ }
+
+ public function test_create_extension_schema_sets_option() : void
+ {
+ $builder = CreateExtensionBuilder::create('postgis')
+ ->schema('public');
+
+ $ast = $builder->toAst();
+ $options = $ast->getOptions();
+
+ self::assertCount(1, $options);
+
+ $defElem = $options[0]->getDefElem();
+ self::assertNotNull($defElem);
+ self::assertSame('schema', $defElem->getDefname());
+ }
+
+ public function test_create_extension_sets_name() : void
+ {
+ $builder = CreateExtensionBuilder::create('postgis');
+
+ $ast = $builder->toAst();
+
+ self::assertSame('postgis', $ast->getExtname());
+ }
+
+ public function test_create_extension_version_sets_option() : void
+ {
+ $builder = CreateExtensionBuilder::create('postgis')
+ ->version('3.0');
+
+ $ast = $builder->toAst();
+ $options = $ast->getOptions();
+
+ self::assertCount(1, $options);
+
+ $defElem = $options[0]->getDefElem();
+ self::assertNotNull($defElem);
+ self::assertSame('new_version', $defElem->getDefname());
+ }
+
+ public function test_drop_extension_ast_type() : void
+ {
+ $builder = DropExtensionBuilder::create('postgis');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(DropStmt::class, $ast);
+ self::assertSame(ObjectType::OBJECT_EXTENSION, $ast->getRemoveType());
+ }
+
+ public function test_drop_extension_cascade_sets_behavior() : void
+ {
+ $builder = DropExtensionBuilder::create('postgis')
+ ->cascade();
+
+ $ast = $builder->toAst();
+
+ self::assertSame(DropBehavior::DROP_CASCADE, $ast->getBehavior());
+ }
+
+ public function test_drop_extension_if_exists_sets_flag() : void
+ {
+ $builder = DropExtensionBuilder::create('postgis')
+ ->ifExists();
+
+ $ast = $builder->toAst();
+
+ self::assertTrue($ast->getMissingOk());
+ }
+
+ public function test_drop_extension_immutability() : void
+ {
+ $original = DropExtensionBuilder::create('postgis');
+ $modified = $original->ifExists();
+
+ self::assertFalse($original->toAst()->getMissingOk());
+ self::assertTrue($modified->toAst()->getMissingOk());
+ }
+
+ public function test_drop_extension_multiple_extensions() : void
+ {
+ $builder = DropExtensionBuilder::create('postgis', 'pg_trgm', 'uuid-ossp');
+
+ $ast = $builder->toAst();
+
+ self::assertCount(3, $ast->getObjects());
+ }
+
+ public function test_drop_extension_restrict_sets_behavior() : void
+ {
+ $builder = DropExtensionBuilder::create('postgis')
+ ->restrict();
+
+ $ast = $builder->toAst();
+
+ self::assertSame(DropBehavior::DROP_RESTRICT, $ast->getBehavior());
+ }
+
+ public function test_drop_extension_sets_name() : void
+ {
+ $builder = DropExtensionBuilder::create('postgis');
+
+ $ast = $builder->toAst();
+
+ self::assertCount(1, $ast->getObjects());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Function/EnumsTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Function/EnumsTest.php
new file mode 100644
index 000000000..6bc36b573
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Function/EnumsTest.php
@@ -0,0 +1,73 @@
+value);
+ }
+
+ #[Test]
+ public function test_argument_mode_inout() : void
+ {
+ self::assertSame(FunctionParameterMode::FUNC_PARAM_INOUT, ArgumentMode::INOUT->value);
+ }
+
+ #[Test]
+ public function test_argument_mode_out() : void
+ {
+ self::assertSame(FunctionParameterMode::FUNC_PARAM_OUT, ArgumentMode::OUT->value);
+ }
+
+ #[Test]
+ public function test_argument_mode_variadic() : void
+ {
+ self::assertSame(FunctionParameterMode::FUNC_PARAM_VARIADIC, ArgumentMode::VARIADIC->value);
+ }
+
+ #[Test]
+ public function test_function_volatility_immutable() : void
+ {
+ self::assertSame('immutable', FunctionVolatility::IMMUTABLE->value);
+ }
+
+ #[Test]
+ public function test_function_volatility_stable() : void
+ {
+ self::assertSame('stable', FunctionVolatility::STABLE->value);
+ }
+
+ #[Test]
+ public function test_function_volatility_volatile() : void
+ {
+ self::assertSame('volatile', FunctionVolatility::VOLATILE->value);
+ }
+
+ #[Test]
+ public function test_parallel_safety_restricted() : void
+ {
+ self::assertSame('restricted', ParallelSafety::RESTRICTED->value);
+ }
+
+ #[Test]
+ public function test_parallel_safety_safe() : void
+ {
+ self::assertSame('safe', ParallelSafety::SAFE->value);
+ }
+
+ #[Test]
+ public function test_parallel_safety_unsafe() : void
+ {
+ self::assertSame('unsafe', ParallelSafety::UNSAFE->value);
+ }
+}
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
new file mode 100644
index 000000000..c8f17d57e
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Function/FunctionArgumentTest.php
@@ -0,0 +1,87 @@
+type);
+ self::assertNull($arg->name);
+ self::assertSame(ArgumentMode::IN, $arg->mode);
+ self::assertNull($arg->default);
+ }
+
+ #[Test]
+ public function test_function_argument_in_mode() : void
+ {
+ $arg = FunctionArgument::of(DataType::text())->in();
+
+ self::assertSame(ArgumentMode::IN, $arg->mode);
+ }
+
+ #[Test]
+ public function test_function_argument_inout_mode() : void
+ {
+ $arg = FunctionArgument::of(DataType::text())->inout();
+
+ self::assertSame(ArgumentMode::INOUT, $arg->mode);
+ }
+
+ #[Test]
+ public function test_function_argument_named() : void
+ {
+ $arg = FunctionArgument::of(DataType::text())->named('username');
+
+ self::assertSame('username', $arg->name);
+ self::assertInstanceOf(DataType::class, $arg->type);
+ }
+
+ #[Test]
+ public function test_function_argument_out_mode() : void
+ {
+ $arg = FunctionArgument::of(DataType::integer())->out();
+
+ self::assertSame(ArgumentMode::OUT, $arg->mode);
+ }
+
+ #[Test]
+ public function test_function_argument_variadic_mode() : void
+ {
+ $arg = FunctionArgument::of(DataType::text())->variadic();
+
+ self::assertSame(ArgumentMode::VARIADIC, $arg->mode);
+ }
+
+ #[Test]
+ public function test_function_argument_with_default() : void
+ {
+ $arg = FunctionArgument::of(DataType::integer())->default('0');
+
+ self::assertSame('0', $arg->default);
+ }
+
+ #[Test]
+ public function test_function_argument_with_mode_and_name_and_default() : void
+ {
+ $arg = FunctionArgument::of(DataType::text())
+ ->named('value')
+ ->out()
+ ->default('null');
+
+ self::assertInstanceOf(DataType::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/Unit/QueryBuilder/Schema/Grant/GrantBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Grant/GrantBuilderTest.php
new file mode 100644
index 000000000..ba010dfe0
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Grant/GrantBuilderTest.php
@@ -0,0 +1,204 @@
+onTable('users')
+ ->to('app_user');
+
+ $ast = $builder->toAst();
+
+ self::assertCount(0, $ast->getPrivileges());
+ }
+
+ public function test_grant_ast_type() : void
+ {
+ $builder = GrantBuilder::create(TablePrivilege::SELECT)
+ ->onTable('users')
+ ->to('app_user');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(GrantStmt::class, $ast);
+ self::assertTrue($ast->getIsGrant());
+ }
+
+ public function test_grant_immutability() : void
+ {
+ $original = GrantBuilder::create(TablePrivilege::SELECT)
+ ->onTable('users')
+ ->to('app_user');
+ $modified = $original->withGrantOption();
+
+ self::assertFalse($original->toAst()->getGrantOption());
+ self::assertTrue($modified->toAst()->getGrantOption());
+ }
+
+ public function test_grant_on_all_tables_in_schema() : void
+ {
+ $builder = GrantBuilder::create(TablePrivilege::SELECT)
+ ->onAllTablesInSchema('public')
+ ->to('admin');
+
+ $ast = $builder->toAst();
+
+ self::assertSame(GrantTargetType::ACL_TARGET_ALL_IN_SCHEMA, $ast->getTargtype());
+ }
+
+ public function test_grant_privileges_on_table() : void
+ {
+ $builder = GrantBuilder::create(TablePrivilege::SELECT, TablePrivilege::INSERT)
+ ->onTable('users')
+ ->to('app_user');
+
+ $ast = $builder->toAst();
+
+ self::assertSame(GrantTargetType::ACL_TARGET_OBJECT, $ast->getTargtype());
+ self::assertSame(ObjectType::OBJECT_TABLE, $ast->getObjtype());
+ self::assertCount(2, $ast->getPrivileges());
+ }
+
+ public function test_grant_role_ast_type() : void
+ {
+ $builder = GrantRoleBuilder::create('admin')
+ ->to('user1');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(GrantRoleStmt::class, $ast);
+ self::assertTrue($ast->getIsGrant());
+ }
+
+ public function test_grant_role_sets_granted_roles() : void
+ {
+ $builder = GrantRoleBuilder::create('admin', 'developer')
+ ->to('user1');
+
+ $ast = $builder->toAst();
+
+ self::assertCount(2, $ast->getGrantedRoles());
+ }
+
+ public function test_grant_role_with_admin_option() : void
+ {
+ $builder = GrantRoleBuilder::create('admin')
+ ->to('user1')
+ ->withAdminOption();
+
+ $ast = $builder->toAst();
+ $opts = $ast->getOpt();
+
+ self::assertCount(1, $opts);
+
+ $defElem = $opts[0]->getDefElem();
+ self::assertNotNull($defElem);
+ self::assertSame('admin', $defElem->getDefname());
+
+ $arg = $defElem->getArg();
+ self::assertNotNull($arg);
+ self::assertTrue($arg->getBoolean()->getBoolval());
+ }
+
+ public function test_grant_to_public() : void
+ {
+ $builder = GrantBuilder::create(TablePrivilege::SELECT)
+ ->onTable('users')
+ ->toPublic();
+
+ $ast = $builder->toAst();
+ $grantees = $ast->getGrantees();
+
+ self::assertCount(1, $grantees);
+
+ $roleSpec = $grantees[0]->getRoleSpec();
+ self::assertNotNull($roleSpec);
+ self::assertSame(RoleSpecType::ROLESPEC_PUBLIC, $roleSpec->getRoletype());
+ }
+
+ public function test_grant_with_grant_option() : void
+ {
+ $builder = GrantBuilder::create(TablePrivilege::SELECT)
+ ->onTable('users')
+ ->to('app_user')
+ ->withGrantOption();
+
+ $ast = $builder->toAst();
+
+ self::assertTrue($ast->getGrantOption());
+ }
+
+ public function test_revoke_ast_type() : void
+ {
+ $builder = RevokeBuilder::create(TablePrivilege::SELECT)
+ ->onTable('users')
+ ->from('app_user');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(GrantStmt::class, $ast);
+ self::assertFalse($ast->getIsGrant());
+ }
+
+ public function test_revoke_cascade_sets_behavior() : void
+ {
+ $builder = RevokeBuilder::create(TablePrivilege::SELECT)
+ ->onTable('users')
+ ->from('app_user')
+ ->cascade();
+
+ $ast = $builder->toAst();
+
+ self::assertSame(DropBehavior::DROP_CASCADE, $ast->getBehavior());
+ }
+
+ public function test_revoke_restrict_sets_behavior() : void
+ {
+ $builder = RevokeBuilder::create(TablePrivilege::SELECT)
+ ->onTable('users')
+ ->from('app_user')
+ ->restrict();
+
+ $ast = $builder->toAst();
+
+ self::assertSame(DropBehavior::DROP_RESTRICT, $ast->getBehavior());
+ }
+
+ public function test_revoke_role_ast_type() : void
+ {
+ $builder = RevokeRoleBuilder::create('admin')
+ ->from('user1');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(GrantRoleStmt::class, $ast);
+ self::assertFalse($ast->getIsGrant());
+ }
+
+ public function test_revoke_role_cascade_sets_behavior() : void
+ {
+ $builder = RevokeRoleBuilder::create('admin')
+ ->from('user1')
+ ->cascade();
+
+ $ast = $builder->toAst();
+
+ self::assertSame(DropBehavior::DROP_CASCADE, $ast->getBehavior());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Index/AlterIndexBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Index/AlterIndexBuilderTest.php
new file mode 100644
index 000000000..b8cbc1ff3
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Index/AlterIndexBuilderTest.php
@@ -0,0 +1,107 @@
+ifExists()
+ ->renameTo('idx_new');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(RenameStmt::class, $ast);
+ self::assertTrue($ast->getMissingOk());
+ }
+
+ public function test_if_exists_sets_flag_for_tablespace() : void
+ {
+ $builder = AlterIndexBuilder::create('idx_users_email')
+ ->ifExists()
+ ->setTablespace('fast_storage');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterTableStmt::class, $ast);
+ self::assertTrue($ast->getMissingOk());
+ }
+
+ public function test_immutability() : void
+ {
+ $original = AlterIndexBuilder::create('idx_old');
+ $modified = $original->ifExists();
+
+ $renamedOriginal = $original->renameTo('idx_new');
+ $renamedModified = $modified->renameTo('idx_new');
+
+ self::assertFalse($renamedOriginal->toAst()->getMissingOk());
+ self::assertTrue($renamedModified->toAst()->getMissingOk());
+ }
+
+ public function test_rename_creates_rename_stmt() : void
+ {
+ $builder = AlterIndexBuilder::create('idx_old')
+ ->renameTo('idx_new');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(RenameStmt::class, $ast);
+ self::assertSame(ObjectType::OBJECT_INDEX, $ast->getRenameType());
+ self::assertSame('idx_old', $ast->getRelation()->getRelname());
+ self::assertSame('idx_new', $ast->getNewname());
+ }
+
+ public function test_rename_with_schema() : void
+ {
+ $builder = AlterIndexBuilder::create('idx_old', 'public')
+ ->renameTo('idx_new');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(RenameStmt::class, $ast);
+ self::assertSame('public', $ast->getRelation()->getSchemaname());
+ self::assertSame('idx_old', $ast->getRelation()->getRelname());
+ }
+
+ public function test_set_tablespace_creates_alter_table_stmt() : void
+ {
+ $builder = AlterIndexBuilder::create('idx_users_email')
+ ->setTablespace('fast_storage');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterTableStmt::class, $ast);
+ self::assertSame(ObjectType::OBJECT_INDEX, $ast->getObjtype());
+ self::assertSame('idx_users_email', $ast->getRelation()->getRelname());
+ 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_with_schema() : void
+ {
+ $builder = AlterIndexBuilder::create('idx_users_email', 'public')
+ ->setTablespace('fast_storage');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterTableStmt::class, $ast);
+ self::assertSame('public', $ast->getRelation()->getSchemaname());
+ self::assertSame('idx_users_email', $ast->getRelation()->getRelname());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Index/CreateIndexBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Index/CreateIndexBuilderTest.php
new file mode 100644
index 000000000..414e53710
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Index/CreateIndexBuilderTest.php
@@ -0,0 +1,201 @@
+on('users')
+ ->columns(IndexColumn::column('email')->desc(), IndexColumn::column('name')->asc());
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(IndexStmt::class, $ast);
+ self::assertCount(2, $ast->getIndexParams());
+ }
+
+ public function test_columns_accepts_strings() : void
+ {
+ $builder = CreateIndexBuilder::create('idx_users_email')
+ ->on('users')
+ ->columns('email', 'name');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(IndexStmt::class, $ast);
+ self::assertCount(2, $ast->getIndexParams());
+ }
+
+ public function test_concurrently_sets_flag() : void
+ {
+ $builder = CreateIndexBuilder::create('idx_users_email')
+ ->concurrently()
+ ->on('users')
+ ->columns('email');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(IndexStmt::class, $ast);
+ self::assertTrue($ast->getConcurrent());
+ }
+
+ public function test_if_not_exists_sets_flag() : void
+ {
+ $builder = CreateIndexBuilder::create('idx_users_email')
+ ->ifNotExists()
+ ->on('users')
+ ->columns('email');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(IndexStmt::class, $ast);
+ self::assertTrue($ast->getIfNotExists());
+ }
+
+ public function test_immutability() : void
+ {
+ $original = CreateIndexBuilder::create('idx_users_email')
+ ->on('users')
+ ->columns('email');
+ $modified = $original->tablespace('fast_storage');
+
+ $originalAst = $original->toAst();
+ $modifiedAst = $modified->toAst();
+
+ self::assertEmpty($originalAst->getTableSpace());
+ self::assertSame('fast_storage', $modifiedAst->getTableSpace());
+ }
+
+ public function test_include_columns() : void
+ {
+ $builder = CreateIndexBuilder::create('idx_users_email')
+ ->on('users')
+ ->columns('email')
+ ->include('name', 'created_at');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(IndexStmt::class, $ast);
+ self::assertCount(2, $ast->getIndexIncludingParams());
+ }
+
+ public function test_nulls_not_distinct_sets_flag() : void
+ {
+ $builder = CreateIndexBuilder::create('idx_users_email')
+ ->unique()
+ ->on('users')
+ ->columns('email')
+ ->nullsNotDistinct();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(IndexStmt::class, $ast);
+ self::assertTrue($ast->getNullsNotDistinct());
+ }
+
+ public function test_on_only_sets_inh_to_false() : void
+ {
+ $builder = CreateIndexBuilder::create('idx_users_email')
+ ->onOnly('users')
+ ->columns('email');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(IndexStmt::class, $ast);
+ self::assertFalse($ast->getRelation()->getInh());
+ }
+
+ public function test_on_sets_inh_to_true() : void
+ {
+ $builder = CreateIndexBuilder::create('idx_users_email')
+ ->on('users')
+ ->columns('email');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(IndexStmt::class, $ast);
+ self::assertTrue($ast->getRelation()->getInh());
+ }
+
+ public function test_simple_create_index() : void
+ {
+ $builder = CreateIndexBuilder::create('idx_users_email')
+ ->on('users')
+ ->columns('email');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(IndexStmt::class, $ast);
+ self::assertSame('idx_users_email', $ast->getIdxname());
+ self::assertSame('users', $ast->getRelation()->getRelname());
+ self::assertCount(1, $ast->getIndexParams());
+ }
+
+ public function test_tablespace() : void
+ {
+ $builder = CreateIndexBuilder::create('idx_users_email')
+ ->on('users')
+ ->columns('email')
+ ->tablespace('fast_storage');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(IndexStmt::class, $ast);
+ self::assertSame('fast_storage', $ast->getTableSpace());
+ }
+
+ public function test_unique_sets_flag() : void
+ {
+ $builder = CreateIndexBuilder::create('idx_users_email')
+ ->unique()
+ ->on('users')
+ ->columns('email');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(IndexStmt::class, $ast);
+ self::assertTrue($ast->getUnique());
+ }
+
+ public function test_using_sets_access_method() : void
+ {
+ $builder = CreateIndexBuilder::create('idx_users_email')
+ ->on('users')
+ ->using(IndexMethod::HASH)
+ ->columns('email');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(IndexStmt::class, $ast);
+ self::assertSame('hash', $ast->getAccessMethod());
+ }
+
+ public function test_with_schema() : void
+ {
+ $builder = CreateIndexBuilder::create('idx_users_email')
+ ->on('users', 'public')
+ ->columns('email');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(IndexStmt::class, $ast);
+ self::assertSame('public', $ast->getRelation()->getSchemaname());
+ self::assertSame('users', $ast->getRelation()->getRelname());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Index/DropIndexBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Index/DropIndexBuilderTest.php
new file mode 100644
index 000000000..c698af812
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Index/DropIndexBuilderTest.php
@@ -0,0 +1,109 @@
+cascade();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(DropStmt::class, $ast);
+ self::assertSame(DropBehavior::DROP_CASCADE, $ast->getBehavior());
+ }
+
+ public function test_concurrently_sets_flag() : void
+ {
+ $builder = DropIndexBuilder::create('idx_users_email')
+ ->concurrently();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(DropStmt::class, $ast);
+ self::assertTrue($ast->getConcurrent());
+ }
+
+ public function test_drop_multiple_indexes() : void
+ {
+ $builder = DropIndexBuilder::create('idx_a', 'idx_b', 'idx_c');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(DropStmt::class, $ast);
+ self::assertCount(3, $ast->getObjects());
+ }
+
+ public function test_if_exists_sets_flag() : void
+ {
+ $builder = DropIndexBuilder::create('idx_users_email')
+ ->ifExists();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(DropStmt::class, $ast);
+ self::assertTrue($ast->getMissingOk());
+ }
+
+ public function test_immutability() : void
+ {
+ $original = DropIndexBuilder::create('idx_users_email');
+ $modified = $original->ifExists();
+
+ $originalAst = $original->toAst();
+ $modifiedAst = $modified->toAst();
+
+ self::assertFalse($originalAst->getMissingOk());
+ self::assertTrue($modifiedAst->getMissingOk());
+ }
+
+ public function test_restrict_sets_behavior() : void
+ {
+ $builder = DropIndexBuilder::create('idx_users_email')
+ ->restrict();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(DropStmt::class, $ast);
+ self::assertSame(DropBehavior::DROP_RESTRICT, $ast->getBehavior());
+ }
+
+ public function test_simple_drop_index() : void
+ {
+ $builder = DropIndexBuilder::create('idx_users_email');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(DropStmt::class, $ast);
+ self::assertSame(ObjectType::OBJECT_INDEX, $ast->getRemoveType());
+ self::assertCount(1, $ast->getObjects());
+ }
+
+ public function test_with_schema() : void
+ {
+ $builder = DropIndexBuilder::create('public.idx_users_email');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(DropStmt::class, $ast);
+ self::assertCount(1, $ast->getObjects());
+ self::assertCount(2, $ast->getObjects()[0]->getList()->getItems());
+ self::assertSame('public', $ast->getObjects()[0]->getList()->getItems()[0]->getString()->getSval());
+ self::assertSame('idx_users_email', $ast->getObjects()[0]->getList()->getItems()[1]->getString()->getSval());
+ }
+}
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
new file mode 100644
index 000000000..ab98976f9
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Index/IndexColumnTest.php
@@ -0,0 +1,133 @@
+asc();
+
+ $ast = $column->toAst();
+
+ self::assertInstanceOf(IndexElem::class, $ast);
+ self::assertSame(SortByDir::SORTBY_ASC, $ast->getOrdering());
+ }
+
+ public function test_collation() : void
+ {
+ $column = IndexColumn::column('name')->collate('en_US');
+
+ $ast = $column->toAst();
+
+ self::assertInstanceOf(IndexElem::class, $ast);
+ self::assertCount(1, $ast->getCollation());
+ self::assertSame('en_US', $ast->getCollation()[0]->getString()->getSval());
+ }
+
+ public function test_column_creates_index_elem() : void
+ {
+ $column = IndexColumn::column('name');
+
+ $ast = $column->toAst();
+
+ self::assertInstanceOf(IndexElem::class, $ast);
+ self::assertSame('name', $ast->getName());
+ }
+
+ public function test_combined_options() : void
+ {
+ $column = IndexColumn::column('name')
+ ->desc()
+ ->nullsFirst()
+ ->opclass('text_pattern_ops')
+ ->collate('en_US');
+
+ $ast = $column->toAst();
+
+ self::assertInstanceOf(IndexElem::class, $ast);
+ self::assertSame('name', $ast->getName());
+ self::assertSame(SortByDir::SORTBY_DESC, $ast->getOrdering());
+ self::assertSame(SortByNulls::SORTBY_NULLS_FIRST, $ast->getNullsOrdering());
+ self::assertCount(1, $ast->getOpclass());
+ self::assertCount(1, $ast->getCollation());
+ }
+
+ public function test_desc_sets_ordering() : void
+ {
+ $column = IndexColumn::column('name')->desc();
+
+ $ast = $column->toAst();
+
+ self::assertInstanceOf(IndexElem::class, $ast);
+ self::assertSame(SortByDir::SORTBY_DESC, $ast->getOrdering());
+ }
+
+ public function test_expression_creates_index_elem() : void
+ {
+ $column = IndexColumn::expression(new RawExpression('lower(name)'));
+
+ $ast = $column->toAst();
+
+ self::assertInstanceOf(IndexElem::class, $ast);
+ self::assertEmpty($ast->getName());
+ self::assertNotNull($ast->getExpr());
+ }
+
+ public function test_immutability() : void
+ {
+ $original = IndexColumn::column('name');
+ $modified = $original->desc();
+
+ $originalAst = $original->toAst();
+ $modifiedAst = $modified->toAst();
+
+ self::assertSame(SortByDir::SORT_BY_DIR_UNDEFINED, $originalAst->getOrdering());
+ self::assertSame(SortByDir::SORTBY_DESC, $modifiedAst->getOrdering());
+ }
+
+ public function test_nulls_first_sets_nulls_ordering() : void
+ {
+ $column = IndexColumn::column('name')->nullsFirst();
+
+ $ast = $column->toAst();
+
+ self::assertInstanceOf(IndexElem::class, $ast);
+ self::assertSame(SortByNulls::SORTBY_NULLS_FIRST, $ast->getNullsOrdering());
+ }
+
+ public function test_nulls_last_sets_nulls_ordering() : void
+ {
+ $column = IndexColumn::column('name')->nullsLast();
+
+ $ast = $column->toAst();
+
+ self::assertInstanceOf(IndexElem::class, $ast);
+ self::assertSame(SortByNulls::SORTBY_NULLS_LAST, $ast->getNullsOrdering());
+ }
+
+ public function test_opclass() : void
+ {
+ $column = IndexColumn::column('name')->opclass('text_pattern_ops');
+
+ $ast = $column->toAst();
+
+ self::assertInstanceOf(IndexElem::class, $ast);
+ self::assertCount(1, $ast->getOpclass());
+ self::assertSame('text_pattern_ops', $ast->getOpclass()[0]->getString()->getSval());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Index/IndexMethodTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Index/IndexMethodTest.php
new file mode 100644
index 000000000..f398b1b09
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Index/IndexMethodTest.php
@@ -0,0 +1,54 @@
+value);
+ }
+
+ public function test_btree_value() : void
+ {
+ self::assertSame('btree', IndexMethod::BTREE->value);
+ }
+
+ public function test_gin_value() : void
+ {
+ self::assertSame('gin', IndexMethod::GIN->value);
+ }
+
+ public function test_gist_value() : void
+ {
+ self::assertSame('gist', IndexMethod::GIST->value);
+ }
+
+ public function test_hash_value() : void
+ {
+ self::assertSame('hash', IndexMethod::HASH->value);
+ }
+
+ public function test_spgist_value() : void
+ {
+ self::assertSame('spgist', IndexMethod::SPGIST->value);
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Index/ReindexBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Index/ReindexBuilderTest.php
new file mode 100644
index 000000000..be75da59e
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Index/ReindexBuilderTest.php
@@ -0,0 +1,147 @@
+concurrently();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(ReindexStmt::class, $ast);
+ self::assertCount(1, $ast->getParams());
+ self::assertSame('concurrently', $ast->getParams()[0]->getDefElem()->getDefname());
+ }
+
+ public function test_database_reindex() : void
+ {
+ $builder = ReindexBuilder::database('mydb');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(ReindexStmt::class, $ast);
+ self::assertSame(ReindexObjectType::REINDEX_OBJECT_DATABASE, $ast->getKind());
+ self::assertSame('mydb', $ast->getName());
+ }
+
+ public function test_immutability() : void
+ {
+ $original = ReindexBuilder::index('idx_users_email');
+ $modified = $original->concurrently();
+
+ $originalAst = $original->toAst();
+ $modifiedAst = $modified->toAst();
+
+ self::assertCount(0, $originalAst->getParams());
+ self::assertCount(1, $modifiedAst->getParams());
+ }
+
+ public function test_index_reindex() : void
+ {
+ $builder = ReindexBuilder::index('idx_users_email');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(ReindexStmt::class, $ast);
+ self::assertSame(ReindexObjectType::REINDEX_OBJECT_INDEX, $ast->getKind());
+ self::assertSame('idx_users_email', $ast->getRelation()->getRelname());
+ }
+
+ public function test_index_with_schema() : void
+ {
+ $builder = ReindexBuilder::index('public.idx_users_email');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(ReindexStmt::class, $ast);
+ self::assertSame('public', $ast->getRelation()->getSchemaname());
+ self::assertSame('idx_users_email', $ast->getRelation()->getRelname());
+ }
+
+ public function test_multiple_params() : void
+ {
+ $builder = ReindexBuilder::table('users')
+ ->concurrently()
+ ->verbose()
+ ->tablespace('fast_storage');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(ReindexStmt::class, $ast);
+ self::assertCount(3, $ast->getParams());
+ }
+
+ public function test_schema_reindex() : void
+ {
+ $builder = ReindexBuilder::schema('public');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(ReindexStmt::class, $ast);
+ self::assertSame(ReindexObjectType::REINDEX_OBJECT_SCHEMA, $ast->getKind());
+ self::assertSame('public', $ast->getName());
+ }
+
+ public function test_system_reindex() : void
+ {
+ $builder = ReindexBuilder::system('mydb');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(ReindexStmt::class, $ast);
+ self::assertSame(ReindexObjectType::REINDEX_OBJECT_SYSTEM, $ast->getKind());
+ self::assertSame('mydb', $ast->getName());
+ }
+
+ public function test_table_reindex() : void
+ {
+ $builder = ReindexBuilder::table('users');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(ReindexStmt::class, $ast);
+ self::assertSame(ReindexObjectType::REINDEX_OBJECT_TABLE, $ast->getKind());
+ self::assertSame('users', $ast->getRelation()->getRelname());
+ }
+
+ public function test_tablespace_adds_param() : void
+ {
+ $builder = ReindexBuilder::index('idx_users_email')
+ ->tablespace('fast_storage');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(ReindexStmt::class, $ast);
+ self::assertCount(1, $ast->getParams());
+ self::assertSame('tablespace', $ast->getParams()[0]->getDefElem()->getDefname());
+ self::assertSame('fast_storage', $ast->getParams()[0]->getDefElem()->getArg()->getString()->getSval());
+ }
+
+ public function test_verbose_adds_param() : void
+ {
+ $builder = ReindexBuilder::table('users')
+ ->verbose();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(ReindexStmt::class, $ast);
+ self::assertCount(1, $ast->getParams());
+ self::assertSame('verbose', $ast->getParams()[0]->getDefElem()->getDefname());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Ownership/OwnershipBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Ownership/OwnershipBuilderTest.php
new file mode 100644
index 000000000..88f961b8e
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Ownership/OwnershipBuilderTest.php
@@ -0,0 +1,106 @@
+toAst();
+
+ self::assertInstanceOf(DropOwnedStmt::class, $ast);
+ }
+
+ public function test_drop_owned_cascade_sets_behavior() : void
+ {
+ $builder = DropOwnedBuilder::create('role1')
+ ->cascade();
+
+ $ast = $builder->toAst();
+
+ self::assertSame(DropBehavior::DROP_CASCADE, $ast->getBehavior());
+ }
+
+ public function test_drop_owned_immutability() : void
+ {
+ $original = DropOwnedBuilder::create('role1');
+ $modified = $original->cascade();
+
+ self::assertSame(DropBehavior::DROP_RESTRICT, $original->toAst()->getBehavior());
+ self::assertSame(DropBehavior::DROP_CASCADE, $modified->toAst()->getBehavior());
+ }
+
+ public function test_drop_owned_restrict_sets_behavior() : void
+ {
+ $builder = DropOwnedBuilder::create('role1')
+ ->restrict();
+
+ $ast = $builder->toAst();
+
+ self::assertSame(DropBehavior::DROP_RESTRICT, $ast->getBehavior());
+ }
+
+ public function test_drop_owned_sets_roles() : void
+ {
+ $builder = DropOwnedBuilder::create('role1', 'role2');
+
+ $ast = $builder->toAst();
+ $roles = $ast->getRoles();
+
+ self::assertCount(2, $roles);
+ }
+
+ public function test_reassign_owned_ast_type() : void
+ {
+ $builder = ReassignOwnedBuilder::create('old_role')
+ ->to('new_role');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(ReassignOwnedStmt::class, $ast);
+ }
+
+ public function test_reassign_owned_sets_new_role() : void
+ {
+ $builder = ReassignOwnedBuilder::create('old_role')
+ ->to('new_owner');
+
+ $ast = $builder->toAst();
+ $newRole = $ast->getNewrole();
+
+ self::assertNotNull($newRole);
+ self::assertSame(RoleSpecType::ROLESPEC_CSTRING, $newRole->getRoletype());
+ self::assertSame('new_owner', $newRole->getRolename());
+ }
+
+ public function test_reassign_owned_sets_roles() : void
+ {
+ $builder = ReassignOwnedBuilder::create('role1', 'role2')
+ ->to('new_role');
+
+ $ast = $builder->toAst();
+ $roles = $ast->getRoles();
+
+ self::assertCount(2, $roles);
+
+ $roleSpec = $roles[0]->getRoleSpec();
+ self::assertNotNull($roleSpec);
+ self::assertSame(RoleSpecType::ROLESPEC_CSTRING, $roleSpec->getRoletype());
+ self::assertSame('role1', $roleSpec->getRolename());
+ }
+}
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
new file mode 100644
index 000000000..d6868c870
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Role/RoleBuilderTest.php
@@ -0,0 +1,202 @@
+superuser();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterRoleStmt::class, $ast);
+ }
+
+ public function test_alter_role_rename_ast_type() : void
+ {
+ $builder = AlterRoleBuilder::create('old_name')
+ ->renameTo('new_name');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(RenameStmt::class, $ast);
+ self::assertSame(ObjectType::OBJECT_ROLE, $ast->getRenameType());
+ }
+
+ public function test_alter_role_rename_sets_names() : void
+ {
+ $builder = AlterRoleBuilder::create('old_name')
+ ->renameTo('new_name');
+
+ $ast = $builder->toAst();
+
+ self::assertSame('old_name', $ast->getSubname());
+ self::assertSame('new_name', $ast->getNewname());
+ }
+
+ public function test_alter_role_sets_role_spec() : void
+ {
+ $builder = AlterRoleBuilder::create('admin')
+ ->noLogin();
+
+ $ast = $builder->toAst();
+ $roleSpec = $ast->getRole();
+
+ self::assertNotNull($roleSpec);
+ self::assertSame(RoleSpecType::ROLESPEC_CSTRING, $roleSpec->getRoletype());
+ self::assertSame('admin', $roleSpec->getRolename());
+ }
+
+ public function test_create_role_ast_type() : void
+ {
+ $builder = CreateRoleBuilder::create('admin');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateRoleStmt::class, $ast);
+ self::assertSame(RoleStmtType::ROLESTMT_ROLE, $ast->getStmtType());
+ }
+
+ public function test_create_role_immutability() : void
+ {
+ $original = CreateRoleBuilder::create('admin');
+ $modified = $original->superuser();
+
+ self::assertCount(0, $original->toAst()->getOptions());
+ self::assertCount(1, $modified->toAst()->getOptions());
+ }
+
+ public function test_create_role_sets_name() : void
+ {
+ $builder = CreateRoleBuilder::create('admin');
+
+ $ast = $builder->toAst();
+
+ self::assertSame('admin', $ast->getRole());
+ }
+
+ public function test_create_role_with_login_option() : void
+ {
+ $builder = CreateRoleBuilder::create('app_user')
+ ->login();
+
+ $ast = $builder->toAst();
+ $options = $ast->getOptions();
+
+ self::assertCount(1, $options);
+
+ $defElem = $options[0]->getDefElem();
+ self::assertNotNull($defElem);
+ self::assertSame('canlogin', $defElem->getDefname());
+ }
+
+ public function test_create_role_with_multiple_options() : void
+ {
+ $builder = CreateRoleBuilder::create('admin')
+ ->superuser()
+ ->login()
+ ->createDb();
+
+ $ast = $builder->toAst();
+ $options = $ast->getOptions();
+
+ self::assertCount(3, $options);
+ }
+
+ public function test_create_role_with_password_option() : void
+ {
+ $builder = CreateRoleBuilder::create('admin')
+ ->withPassword('secret');
+
+ $ast = $builder->toAst();
+ $options = $ast->getOptions();
+
+ self::assertCount(1, $options);
+
+ $defElem = $options[0]->getDefElem();
+ self::assertNotNull($defElem);
+ self::assertSame('password', $defElem->getDefname());
+ }
+
+ public function test_create_role_with_superuser_option() : void
+ {
+ $builder = CreateRoleBuilder::create('admin')
+ ->superuser();
+
+ $ast = $builder->toAst();
+ $options = $ast->getOptions();
+
+ self::assertCount(1, $options);
+
+ $defElem = $options[0]->getDefElem();
+ self::assertNotNull($defElem);
+ self::assertSame('superuser', $defElem->getDefname());
+ }
+
+ public function test_drop_role_ast_type() : void
+ {
+ $builder = DropRoleBuilder::create('admin');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(DropRoleStmt::class, $ast);
+ }
+
+ public function test_drop_role_if_exists_sets_flag() : void
+ {
+ $builder = DropRoleBuilder::create('admin')
+ ->ifExists();
+
+ $ast = $builder->toAst();
+
+ self::assertTrue($ast->getMissingOk());
+ }
+
+ public function test_drop_role_immutability() : void
+ {
+ $original = DropRoleBuilder::create('admin');
+ $modified = $original->ifExists();
+
+ self::assertFalse($original->toAst()->getMissingOk());
+ self::assertTrue($modified->toAst()->getMissingOk());
+ }
+
+ public function test_drop_role_multiple_roles() : void
+ {
+ $builder = DropRoleBuilder::create('role1', 'role2', 'role3');
+
+ $ast = $builder->toAst();
+
+ self::assertCount(3, $ast->getRoles());
+ }
+
+ public function test_drop_role_sets_role_names() : void
+ {
+ $builder = DropRoleBuilder::create('admin');
+
+ $ast = $builder->toAst();
+ $roles = $ast->getRoles();
+
+ self::assertCount(1, $roles);
+
+ $roleSpec = $roles[0]->getRoleSpec();
+ self::assertNotNull($roleSpec);
+ self::assertSame(RoleSpecType::ROLESPEC_CSTRING, $roleSpec->getRoletype());
+ self::assertSame('admin', $roleSpec->getRolename());
+ }
+}
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
new file mode 100644
index 000000000..43fb8c2e9
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Schema/SchemaBuilderTest.php
@@ -0,0 +1,173 @@
+ownerTo('new_owner');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterOwnerStmt::class, $ast);
+ self::assertSame(ObjectType::OBJECT_SCHEMA, $ast->getObjectType());
+ }
+
+ public function test_alter_schema_owner_sets_new_owner() : void
+ {
+ $builder = AlterSchemaBuilder::create('my_schema')
+ ->ownerTo('admin_user');
+
+ $ast = $builder->toAst();
+ $newOwner = $ast->getNewowner();
+
+ self::assertNotNull($newOwner);
+ self::assertSame(RoleSpecType::ROLESPEC_CSTRING, $newOwner->getRoletype());
+ self::assertSame('admin_user', $newOwner->getRolename());
+ }
+
+ public function test_alter_schema_rename_ast_type() : void
+ {
+ $builder = AlterSchemaBuilder::create('old_schema')
+ ->renameTo('new_schema');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(RenameStmt::class, $ast);
+ self::assertSame(ObjectType::OBJECT_SCHEMA, $ast->getRenameType());
+ }
+
+ public function test_alter_schema_rename_sets_names() : void
+ {
+ $builder = AlterSchemaBuilder::create('old_schema')
+ ->renameTo('new_schema');
+
+ $ast = $builder->toAst();
+
+ self::assertSame('old_schema', $ast->getSubname());
+ self::assertSame('new_schema', $ast->getNewname());
+ }
+
+ public function test_create_schema_ast_type() : void
+ {
+ $builder = CreateSchemaBuilder::create('my_schema');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateSchemaStmt::class, $ast);
+ }
+
+ public function test_create_schema_authorization_sets_role() : void
+ {
+ $builder = CreateSchemaBuilder::create('my_schema')
+ ->authorization('admin_user');
+
+ $ast = $builder->toAst();
+ $authRole = $ast->getAuthrole();
+
+ self::assertNotNull($authRole);
+ self::assertSame(RoleSpecType::ROLESPEC_CSTRING, $authRole->getRoletype());
+ self::assertSame('admin_user', $authRole->getRolename());
+ }
+
+ public function test_create_schema_if_not_exists_sets_flag() : void
+ {
+ $builder = CreateSchemaBuilder::create('my_schema')
+ ->ifNotExists();
+
+ $ast = $builder->toAst();
+
+ self::assertTrue($ast->getIfNotExists());
+ }
+
+ public function test_create_schema_immutability() : void
+ {
+ $original = CreateSchemaBuilder::create('my_schema');
+ $modified = $original->ifNotExists();
+
+ self::assertFalse($original->toAst()->getIfNotExists());
+ self::assertTrue($modified->toAst()->getIfNotExists());
+ }
+
+ public function test_create_schema_sets_name() : void
+ {
+ $builder = CreateSchemaBuilder::create('my_schema');
+
+ $ast = $builder->toAst();
+
+ self::assertSame('my_schema', $ast->getSchemaname());
+ }
+
+ public function test_drop_schema_ast_type() : void
+ {
+ $builder = DropSchemaBuilder::create('my_schema');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(DropStmt::class, $ast);
+ self::assertSame(ObjectType::OBJECT_SCHEMA, $ast->getRemoveType());
+ }
+
+ public function test_drop_schema_cascade_sets_behavior() : void
+ {
+ $builder = DropSchemaBuilder::create('my_schema')
+ ->cascade();
+
+ $ast = $builder->toAst();
+
+ self::assertSame(DropBehavior::DROP_CASCADE, $ast->getBehavior());
+ }
+
+ public function test_drop_schema_if_exists_sets_flag() : void
+ {
+ $builder = DropSchemaBuilder::create('my_schema')
+ ->ifExists();
+
+ $ast = $builder->toAst();
+
+ self::assertTrue($ast->getMissingOk());
+ }
+
+ public function test_drop_schema_immutability() : void
+ {
+ $original = DropSchemaBuilder::create('my_schema');
+ $modified = $original->ifExists();
+
+ self::assertFalse($original->toAst()->getMissingOk());
+ self::assertTrue($modified->toAst()->getMissingOk());
+ }
+
+ public function test_drop_schema_multiple_schemas() : void
+ {
+ $builder = DropSchemaBuilder::create('schema1', 'schema2', 'schema3');
+
+ $ast = $builder->toAst();
+
+ self::assertCount(3, $ast->getObjects());
+ }
+
+ public function test_drop_schema_restrict_sets_behavior() : void
+ {
+ $builder = DropSchemaBuilder::create('my_schema')
+ ->restrict();
+
+ $ast = $builder->toAst();
+
+ self::assertSame(DropBehavior::DROP_RESTRICT, $ast->getBehavior());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Session/SessionBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Session/SessionBuilderTest.php
new file mode 100644
index 000000000..6aee2e7b9
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Session/SessionBuilderTest.php
@@ -0,0 +1,80 @@
+toAst();
+
+ self::assertInstanceOf(VariableSetStmt::class, $ast);
+ self::assertSame(VariableSetKind::VAR_RESET, $ast->getKind());
+ }
+
+ public function test_reset_role_has_no_args() : void
+ {
+ $builder = ResetRoleBuilder::create();
+
+ $ast = $builder->toAst();
+
+ self::assertCount(0, $ast->getArgs());
+ }
+
+ public function test_reset_role_sets_name_to_role() : void
+ {
+ $builder = ResetRoleBuilder::create();
+
+ $ast = $builder->toAst();
+
+ self::assertSame('role', $ast->getName());
+ }
+
+ public function test_set_role_ast_type() : void
+ {
+ $builder = SetRoleBuilder::create('admin');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(VariableSetStmt::class, $ast);
+ self::assertSame(VariableSetKind::VAR_SET_VALUE, $ast->getKind());
+ }
+
+ public function test_set_role_sets_name_to_role() : void
+ {
+ $builder = SetRoleBuilder::create('admin');
+
+ $ast = $builder->toAst();
+
+ self::assertSame('role', $ast->getName());
+ }
+
+ public function test_set_role_sets_role_in_args() : void
+ {
+ $builder = SetRoleBuilder::create('admin');
+
+ $ast = $builder->toAst();
+ $args = $ast->getArgs();
+
+ self::assertCount(1, $args);
+
+ $aConst = $args[0]->getAConst();
+ self::assertNotNull($aConst);
+ self::assertSame('admin', $aConst->getSval()->getSval());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Trigger/TriggerEnumsTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Trigger/TriggerEnumsTest.php
new file mode 100644
index 000000000..fa920b8c2
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Trigger/TriggerEnumsTest.php
@@ -0,0 +1,104 @@
+value);
+ }
+
+ #[Test]
+ public function test_rule_event_insert_maps_to_cmd_type() : void
+ {
+ self::assertSame(CmdType::CMD_INSERT, RuleEvent::INSERT->value);
+ }
+
+ #[Test]
+ public function test_rule_event_select_maps_to_cmd_type() : void
+ {
+ self::assertSame(CmdType::CMD_SELECT, RuleEvent::SELECT->value);
+ }
+
+ #[Test]
+ public function test_rule_event_update_maps_to_cmd_type() : void
+ {
+ self::assertSame(CmdType::CMD_UPDATE, RuleEvent::UPDATE->value);
+ }
+
+ #[Test]
+ public function test_trigger_event_delete_has_value_8() : void
+ {
+ self::assertSame(8, TriggerEvent::DELETE->value);
+ }
+
+ #[Test]
+ public function test_trigger_event_insert_has_value_4() : void
+ {
+ self::assertSame(4, TriggerEvent::INSERT->value);
+ }
+
+ #[Test]
+ public function test_trigger_event_truncate_has_value_32() : void
+ {
+ self::assertSame(32, TriggerEvent::TRUNCATE->value);
+ }
+
+ #[Test]
+ public function test_trigger_event_update_has_value_16() : void
+ {
+ self::assertSame(16, TriggerEvent::UPDATE->value);
+ }
+
+ #[Test]
+ public function test_trigger_events_can_be_combined_as_bitmask() : void
+ {
+ $combined = TriggerEvent::INSERT->value | TriggerEvent::UPDATE->value | TriggerEvent::DELETE->value;
+
+ self::assertSame(28, $combined);
+ self::assertTrue(($combined & TriggerEvent::INSERT->value) !== 0);
+ self::assertTrue(($combined & TriggerEvent::UPDATE->value) !== 0);
+ self::assertTrue(($combined & TriggerEvent::DELETE->value) !== 0);
+ self::assertFalse(($combined & TriggerEvent::TRUNCATE->value) !== 0);
+ }
+
+ #[Test]
+ public function test_trigger_level_row_returns_true() : void
+ {
+ self::assertTrue(TriggerLevel::ROW->toBool());
+ }
+
+ #[Test]
+ public function test_trigger_level_statement_returns_false() : void
+ {
+ self::assertFalse(TriggerLevel::STATEMENT->toBool());
+ }
+
+ #[Test]
+ public function test_trigger_timing_after_has_value_0() : void
+ {
+ self::assertSame(0, TriggerTiming::AFTER->value);
+ }
+
+ #[Test]
+ public function test_trigger_timing_before_has_value_2() : void
+ {
+ self::assertSame(2, TriggerTiming::BEFORE->value);
+ }
+
+ #[Test]
+ public function test_trigger_timing_instead_of_has_value_64() : void
+ {
+ self::assertSame(64, TriggerTiming::INSTEAD_OF->value);
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Truncate/TruncateBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Truncate/TruncateBuilderTest.php
new file mode 100644
index 000000000..ebe473b9d
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Truncate/TruncateBuilderTest.php
@@ -0,0 +1,121 @@
+cascade();
+
+ self::assertSame(DropBehavior::DROP_BEHAVIOR_UNDEFINED, $original->toAst()->getBehavior());
+ self::assertSame(DropBehavior::DROP_CASCADE, $modified->toAst()->getBehavior());
+ }
+
+ public function test_simple_truncate() : void
+ {
+ $builder = TruncateBuilder::create('users');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(TruncateStmt::class, $ast);
+ self::assertCount(1, $ast->getRelations());
+ self::assertSame('users', $ast->getRelations()[0]->getRangeVar()->getRelname());
+ }
+
+ public function test_truncate_cascade() : void
+ {
+ $builder = TruncateBuilder::create('users')
+ ->cascade();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(TruncateStmt::class, $ast);
+ self::assertSame(DropBehavior::DROP_CASCADE, $ast->getBehavior());
+ }
+
+ public function test_truncate_continue_identity() : void
+ {
+ $builder = TruncateBuilder::create('users')
+ ->restartIdentity()
+ ->continueIdentity();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(TruncateStmt::class, $ast);
+ self::assertFalse($ast->getRestartSeqs());
+ }
+
+ public function test_truncate_multiple_tables() : void
+ {
+ $builder = TruncateBuilder::create('users', 'orders', 'products');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(TruncateStmt::class, $ast);
+ self::assertCount(3, $ast->getRelations());
+ self::assertSame('users', $ast->getRelations()[0]->getRangeVar()->getRelname());
+ self::assertSame('orders', $ast->getRelations()[1]->getRangeVar()->getRelname());
+ self::assertSame('products', $ast->getRelations()[2]->getRangeVar()->getRelname());
+ }
+
+ public function test_truncate_restart_identity() : void
+ {
+ $builder = TruncateBuilder::create('users')
+ ->restartIdentity();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(TruncateStmt::class, $ast);
+ self::assertTrue($ast->getRestartSeqs());
+ }
+
+ public function test_truncate_restart_identity_cascade() : void
+ {
+ $builder = TruncateBuilder::create('users')
+ ->restartIdentity()
+ ->cascade();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(TruncateStmt::class, $ast);
+ self::assertTrue($ast->getRestartSeqs());
+ self::assertSame(DropBehavior::DROP_CASCADE, $ast->getBehavior());
+ }
+
+ public function test_truncate_restrict() : void
+ {
+ $builder = TruncateBuilder::create('users')
+ ->restrict();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(TruncateStmt::class, $ast);
+ self::assertSame(DropBehavior::DROP_RESTRICT, $ast->getBehavior());
+ }
+
+ public function test_truncate_with_schema() : void
+ {
+ $builder = TruncateBuilder::create('public.users');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(TruncateStmt::class, $ast);
+ self::assertSame('public', $ast->getRelations()[0]->getRangeVar()->getSchemaname());
+ self::assertSame('users', $ast->getRelations()[0]->getRangeVar()->getRelname());
+ }
+}
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
new file mode 100644
index 000000000..ab3e9994b
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Type/TypeAttributeTest.php
@@ -0,0 +1,51 @@
+name);
+ self::assertInstanceOf(DataType::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));
+
+ self::assertInstanceOf(DataType::class, $intAttr->type);
+ self::assertInstanceOf(DataType::class, $boolAttr->type);
+ self::assertInstanceOf(DataType::class, $numericAttr->type);
+ }
+
+ public function test_type_attribute_immutability() : void
+ {
+ $original = TypeAttribute::of('name', DataType::text());
+ $modified = $original->collate('en_US');
+
+ self::assertNull($original->collation);
+ self::assertSame('en_US', $modified->collation);
+ }
+
+ public function test_type_attribute_with_collation() : void
+ {
+ $attr = TypeAttribute::of('name', DataType::text())
+ ->collate('en_US');
+
+ self::assertSame('name', $attr->name);
+ self::assertInstanceOf(DataType::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
new file mode 100644
index 000000000..fde1e280a
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/Type/TypeBuilderTest.php
@@ -0,0 +1,314 @@
+addValue('archived');
+
+ $ast = $builder->toAst();
+
+ self::assertSame('archived', $ast->getNewVal());
+ self::assertSame('', $ast->getOldVal());
+ }
+
+ public function test_alter_enum_type_add_value_after() : void
+ {
+ $builder = AlterEnumTypeBuilder::create('status')
+ ->addValueAfter('archived', 'closed');
+
+ $ast = $builder->toAst();
+
+ self::assertSame('archived', $ast->getNewVal());
+ self::assertSame('closed', $ast->getNewValNeighbor());
+ self::assertTrue($ast->getNewValIsAfter());
+ }
+
+ public function test_alter_enum_type_add_value_before() : void
+ {
+ $builder = AlterEnumTypeBuilder::create('status')
+ ->addValueBefore('pending', 'active');
+
+ $ast = $builder->toAst();
+
+ self::assertSame('pending', $ast->getNewVal());
+ self::assertSame('active', $ast->getNewValNeighbor());
+ self::assertFalse($ast->getNewValIsAfter());
+ }
+
+ public function test_alter_enum_type_ast_type() : void
+ {
+ $builder = AlterEnumTypeBuilder::create('status')
+ ->addValue('archived');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterEnumStmt::class, $ast);
+ }
+
+ public function test_alter_enum_type_if_not_exists() : void
+ {
+ $builder = AlterEnumTypeBuilder::create('status')
+ ->addValue('archived')
+ ->ifNotExists();
+
+ $ast = $builder->toAst();
+
+ self::assertTrue($ast->getSkipIfNewValExists());
+ }
+
+ public function test_alter_enum_type_rename_value() : void
+ {
+ $builder = AlterEnumTypeBuilder::create('status')
+ ->renameValue('old_name', 'new_name');
+
+ $ast = $builder->toAst();
+
+ self::assertSame('old_name', $ast->getOldVal());
+ self::assertSame('new_name', $ast->getNewVal());
+ }
+
+ public function test_create_composite_type_ast_type() : void
+ {
+ $builder = CreateCompositeTypeBuilder::create('address')
+ ->attributes(TypeAttribute::of('street', sql_type_text()));
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CompositeTypeStmt::class, $ast);
+ }
+
+ public function test_create_composite_type_sets_attributes() : void
+ {
+ $builder = CreateCompositeTypeBuilder::create('address')
+ ->attributes(
+ TypeAttribute::of('street', sql_type_text()),
+ TypeAttribute::of('city', sql_type_text()),
+ TypeAttribute::of('zip', sql_type_varchar(50))
+ );
+
+ $ast = $builder->toAst();
+ $coldeflist = $ast->getColdeflist();
+
+ self::assertCount(3, $coldeflist);
+ }
+
+ public function test_create_composite_type_sets_name() : void
+ {
+ $builder = CreateCompositeTypeBuilder::create('address')
+ ->attributes(TypeAttribute::of('street', sql_type_text()));
+
+ $ast = $builder->toAst();
+ $typevar = $ast->getTypevar();
+
+ self::assertNotNull($typevar);
+ self::assertSame('address', $typevar->getRelname());
+ }
+
+ public function test_create_composite_type_with_collation() : void
+ {
+ $builder = CreateCompositeTypeBuilder::create('address')
+ ->attributes(TypeAttribute::of('name', sql_type_text())->collate('en_US'));
+
+ $ast = $builder->toAst();
+ $coldeflist = $ast->getColdeflist();
+
+ self::assertCount(1, $coldeflist);
+
+ $coldef = $coldeflist[0]->getColumnDef();
+ self::assertNotNull($coldef);
+ self::assertNotNull($coldef->getCollClause());
+ }
+
+ public function test_create_composite_type_with_schema() : void
+ {
+ $builder = CreateCompositeTypeBuilder::create('public.address')
+ ->attributes(TypeAttribute::of('street', sql_type_text()));
+
+ $ast = $builder->toAst();
+ $typevar = $ast->getTypevar();
+
+ self::assertNotNull($typevar);
+ self::assertSame('address', $typevar->getRelname());
+ self::assertSame('public', $typevar->getSchemaname());
+ }
+
+ public function test_create_enum_type_ast_type() : void
+ {
+ $builder = CreateEnumTypeBuilder::create('status')
+ ->labels('pending', 'active', 'closed');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateEnumStmt::class, $ast);
+ }
+
+ public function test_create_enum_type_sets_labels() : void
+ {
+ $builder = CreateEnumTypeBuilder::create('status')
+ ->labels('pending', 'active', 'closed');
+
+ $ast = $builder->toAst();
+ $vals = $ast->getVals();
+
+ self::assertCount(3, $vals);
+ }
+
+ public function test_create_enum_type_sets_name() : void
+ {
+ $builder = CreateEnumTypeBuilder::create('status')
+ ->labels('pending', 'active');
+
+ $ast = $builder->toAst();
+ $typeName = $ast->getTypeName();
+
+ self::assertCount(1, $typeName);
+ }
+
+ public function test_create_enum_type_with_schema() : void
+ {
+ $builder = CreateEnumTypeBuilder::create('public.status')
+ ->labels('pending', 'active');
+
+ $ast = $builder->toAst();
+ $typeName = $ast->getTypeName();
+
+ self::assertCount(2, $typeName);
+ }
+
+ public function test_create_range_type_ast_type() : void
+ {
+ $builder = CreateRangeTypeBuilder::create('floatrange')
+ ->subtype('float8');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateRangeStmt::class, $ast);
+ }
+
+ public function test_create_range_type_sets_name() : void
+ {
+ $builder = CreateRangeTypeBuilder::create('floatrange')
+ ->subtype('float8');
+
+ $ast = $builder->toAst();
+ $typeName = $ast->getTypeName();
+
+ self::assertCount(1, $typeName);
+ }
+
+ public function test_create_range_type_sets_subtype() : void
+ {
+ $builder = CreateRangeTypeBuilder::create('floatrange')
+ ->subtype('float8');
+
+ $ast = $builder->toAst();
+ $params = $ast->getParams();
+
+ self::assertCount(1, $params);
+
+ $defElem = $params[0]->getDefElem();
+ self::assertNotNull($defElem);
+ self::assertSame('subtype', $defElem->getDefname());
+ }
+
+ public function test_create_range_type_with_options() : void
+ {
+ $builder = CreateRangeTypeBuilder::create('floatrange')
+ ->subtype('float8')
+ ->subtypeOpclass('float8_ops')
+ ->collation('en_US');
+
+ $ast = $builder->toAst();
+ $params = $ast->getParams();
+
+ self::assertCount(3, $params);
+ }
+
+ public function test_create_range_type_with_schema() : void
+ {
+ $builder = CreateRangeTypeBuilder::create('public.floatrange')
+ ->subtype('float8');
+
+ $ast = $builder->toAst();
+ $typeName = $ast->getTypeName();
+
+ self::assertCount(2, $typeName);
+ }
+
+ public function test_drop_type_ast_type() : void
+ {
+ $builder = DropTypeBuilder::create('address');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(DropStmt::class, $ast);
+ self::assertSame(ObjectType::OBJECT_TYPE, $ast->getRemoveType());
+ }
+
+ public function test_drop_type_cascade() : void
+ {
+ $builder = DropTypeBuilder::create('address')
+ ->cascade();
+
+ $ast = $builder->toAst();
+
+ self::assertSame(DropBehavior::DROP_CASCADE, $ast->getBehavior());
+ }
+
+ public function test_drop_type_if_exists() : void
+ {
+ $builder = DropTypeBuilder::create('address')
+ ->ifExists();
+
+ $ast = $builder->toAst();
+
+ self::assertTrue($ast->getMissingOk());
+ }
+
+ public function test_drop_type_immutability() : void
+ {
+ $original = DropTypeBuilder::create('address');
+ $modified = $original->ifExists();
+
+ self::assertFalse($original->toAst()->getMissingOk());
+ self::assertTrue($modified->toAst()->getMissingOk());
+ }
+
+ public function test_drop_type_multiple_types() : void
+ {
+ $builder = DropTypeBuilder::create('address', 'status', 'priority');
+
+ $ast = $builder->toAst();
+
+ self::assertCount(3, $ast->getObjects());
+ }
+
+ public function test_drop_type_restrict() : void
+ {
+ $builder = DropTypeBuilder::create('address')
+ ->restrict();
+
+ $ast = $builder->toAst();
+
+ self::assertSame(DropBehavior::DROP_RESTRICT, $ast->getBehavior());
+ }
+}
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
new file mode 100644
index 000000000..d64085c25
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Schema/View/ViewBuilderTest.php
@@ -0,0 +1,304 @@
+setTablespace('fast_storage');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterTableStmt::class, $ast);
+ }
+
+ public function test_alter_materialized_view_set_tablespace_if_exists_sets_flag() : void
+ {
+ $builder = AlterMaterializedViewBuilder::create('my_matview')
+ ->ifExists()
+ ->setTablespace('fast_storage');
+
+ $ast = $builder->toAst();
+
+ self::assertTrue($ast->getMissingOk());
+ }
+
+ public function test_alter_view_owner_to_ast_type() : void
+ {
+ $builder = AlterViewBuilder::create('my_view')
+ ->ownerTo('new_owner');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterTableStmt::class, $ast);
+ self::assertSame(ObjectType::OBJECT_VIEW, $ast->getObjtype());
+ }
+
+ public function test_alter_view_rename_ast_type() : void
+ {
+ $builder = AlterViewBuilder::create('old_view')
+ ->renameTo('new_view');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(RenameStmt::class, $ast);
+ }
+
+ public function test_alter_view_rename_if_exists_sets_flag() : void
+ {
+ $builder = AlterViewBuilder::create('old_view')
+ ->ifExists()
+ ->renameTo('new_view');
+
+ $ast = $builder->toAst();
+
+ self::assertTrue($ast->getMissingOk());
+ }
+
+ public function test_alter_view_set_schema_ast_type() : void
+ {
+ $builder = AlterViewBuilder::create('my_view')
+ ->setSchema('archive');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(AlterObjectSchemaStmt::class, $ast);
+ self::assertSame('archive', $ast->getNewschema());
+ }
+
+ public function test_create_materialized_view_ast_type() : void
+ {
+ $builder = CreateMaterializedViewBuilder::create('my_matview')
+ ->as(SelectBuilder::create()->select(star())->from(table('users')));
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CreateTableAsStmt::class, $ast);
+ self::assertSame(ObjectType::OBJECT_MATVIEW, $ast->getObjtype());
+ }
+
+ public function test_create_materialized_view_if_not_exists_sets_flag() : void
+ {
+ $builder = CreateMaterializedViewBuilder::create('my_matview')
+ ->ifNotExists()
+ ->as(SelectBuilder::create()->select(star())->from(table('users')));
+
+ $ast = $builder->toAst();
+
+ self::assertTrue($ast->getIfNotExists());
+ }
+
+ public function test_create_materialized_view_parses_schema_from_name() : void
+ {
+ $builder = CreateMaterializedViewBuilder::create('analytics.my_matview')
+ ->as(SelectBuilder::create()->select(star())->from(table('users')));
+
+ $ast = $builder->toAst();
+ $into = $ast->getInto();
+
+ self::assertNotNull($into);
+ $rel = $into->getRel();
+ self::assertNotNull($rel);
+ self::assertSame('analytics', $rel->getSchemaname());
+ self::assertSame('my_matview', $rel->getRelname());
+ }
+
+ public function test_create_materialized_view_with_columns() : void
+ {
+ $builder = CreateMaterializedViewBuilder::create('my_matview')
+ ->columns('user_id', 'total_orders')
+ ->as(SelectBuilder::create()->select(star())->from(table('users')));
+
+ $ast = $builder->toAst();
+ $into = $ast->getInto();
+
+ self::assertNotNull($into);
+ self::assertCount(2, $into->getColNames());
+ }
+
+ public function test_create_materialized_view_with_no_data_sets_flag() : void
+ {
+ $builder = CreateMaterializedViewBuilder::create('my_matview')
+ ->as(SelectBuilder::create()->select(star())->from(table('users')))
+ ->withNoData();
+
+ $ast = $builder->toAst();
+ $into = $ast->getInto();
+
+ self::assertNotNull($into);
+ self::assertTrue($into->getSkipData());
+ }
+
+ public function test_create_materialized_view_with_tablespace() : void
+ {
+ $builder = CreateMaterializedViewBuilder::create('my_matview')
+ ->as(SelectBuilder::create()->select(star())->from(table('users')))
+ ->tablespace('fast_storage');
+
+ $ast = $builder->toAst();
+ $into = $ast->getInto();
+
+ self::assertNotNull($into);
+ self::assertSame('fast_storage', $into->getTableSpaceName());
+ }
+
+ public function test_create_view_ast_type() : void
+ {
+ $builder = CreateViewBuilder::create('my_view')
+ ->as(SelectBuilder::create()->select(star())->from(table('users')));
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(ViewStmt::class, $ast);
+ }
+
+ public function test_create_view_immutability() : void
+ {
+ $original = CreateViewBuilder::create('my_view');
+ $modified = $original->orReplace();
+
+ $originalAst = $original->as(SelectBuilder::create()->select(star())->from(table('users')))->toAst();
+ $modifiedAst = $modified->as(SelectBuilder::create()->select(star())->from(table('users')))->toAst();
+
+ self::assertFalse($originalAst->getReplace());
+ self::assertTrue($modifiedAst->getReplace());
+ }
+
+ public function test_create_view_or_replace_sets_flag() : void
+ {
+ $builder = CreateViewBuilder::create('my_view')
+ ->orReplace()
+ ->as(SelectBuilder::create()->select(star())->from(table('users')));
+
+ $ast = $builder->toAst();
+
+ self::assertTrue($ast->getReplace());
+ }
+
+ public function test_create_view_parses_schema_from_name() : void
+ {
+ $builder = CreateViewBuilder::create('public.my_view')
+ ->as(SelectBuilder::create()->select(star())->from(table('users')));
+
+ $ast = $builder->toAst();
+ $view = $ast->getView();
+
+ self::assertNotNull($view);
+ self::assertSame('public', $view->getSchemaname());
+ self::assertSame('my_view', $view->getRelname());
+ }
+
+ public function test_create_view_with_columns() : void
+ {
+ $builder = CreateViewBuilder::create('my_view')
+ ->columns('id', 'name', 'email')
+ ->as(SelectBuilder::create()->select(star())->from(table('users')));
+
+ $ast = $builder->toAst();
+
+ self::assertCount(3, $ast->getAliases());
+ }
+
+ public function test_drop_materialized_view_ast_type() : void
+ {
+ $builder = DropMaterializedViewBuilder::create('my_matview');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(DropStmt::class, $ast);
+ self::assertSame(ObjectType::OBJECT_MATVIEW, $ast->getRemoveType());
+ }
+
+ public function test_drop_view_ast_type() : void
+ {
+ $builder = DropViewBuilder::create('my_view');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(DropStmt::class, $ast);
+ self::assertSame(ObjectType::OBJECT_VIEW, $ast->getRemoveType());
+ }
+
+ public function test_drop_view_if_exists_sets_flag() : void
+ {
+ $builder = DropViewBuilder::create('my_view')
+ ->ifExists();
+
+ $ast = $builder->toAst();
+
+ self::assertTrue($ast->getMissingOk());
+ }
+
+ public function test_drop_view_multiple_views() : void
+ {
+ $builder = DropViewBuilder::create('view1', 'view2', 'view3');
+
+ $ast = $builder->toAst();
+
+ self::assertCount(3, $ast->getObjects());
+ }
+
+ public function test_refresh_materialized_view_ast_type() : void
+ {
+ $builder = RefreshMaterializedViewBuilder::create('my_matview');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(RefreshMatViewStmt::class, $ast);
+ }
+
+ public function test_refresh_materialized_view_concurrently_sets_flag() : void
+ {
+ $builder = RefreshMaterializedViewBuilder::create('my_matview')
+ ->concurrently();
+
+ $ast = $builder->toAst();
+
+ self::assertTrue($ast->getConcurrent());
+ }
+
+ public function test_refresh_materialized_view_parses_schema_from_name() : void
+ {
+ $builder = RefreshMaterializedViewBuilder::create('analytics.my_matview');
+
+ $ast = $builder->toAst();
+ $relation = $ast->getRelation();
+
+ self::assertNotNull($relation);
+ self::assertSame('analytics', $relation->getSchemaname());
+ self::assertSame('my_matview', $relation->getRelname());
+ }
+
+ public function test_refresh_materialized_view_with_no_data_sets_flag() : void
+ {
+ $builder = RefreshMaterializedViewBuilder::create('my_matview')
+ ->withNoData();
+
+ $ast = $builder->toAst();
+
+ self::assertTrue($ast->getSkipData());
+ }
+}
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
new file mode 100644
index 000000000..f46191e05
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Select/SelectBuilderTest.php
@@ -0,0 +1,582 @@
+select(Column::name('id'));
+ $builder2 = $builder1->from(new Table('users'));
+
+ self::assertNotSame($builder1, $builder2);
+ }
+
+ public function test_immutability_join() : void
+ {
+ $builder1 = SelectBuilder::create()
+ ->select(Column::name('id'))
+ ->from(new Table('users'));
+ $builder2 = $builder1->leftJoin(
+ new Table('orders'),
+ new Comparison(Column::name('user_id'), ComparisonOperator::EQ, Column::name('id'))
+ );
+
+ self::assertNotSame($builder1, $builder2);
+ }
+
+ public function test_immutability_limit() : void
+ {
+ $builder1 = SelectBuilder::create()
+ ->select(Column::name('id'))
+ ->from(new Table('users'));
+ $builder2 = $builder1->limit(10);
+
+ self::assertNotSame($builder1, $builder2);
+ }
+
+ public function test_immutability_offset() : void
+ {
+ $builder1 = SelectBuilder::create()
+ ->select(Column::name('id'))
+ ->from(new Table('users'));
+ $builder2 = $builder1->offset(20);
+
+ self::assertNotSame($builder1, $builder2);
+ }
+
+ public function test_immutability_order_by() : void
+ {
+ $builder1 = SelectBuilder::create()
+ ->select(Column::name('id'))
+ ->from(new Table('users'));
+ $builder2 = $builder1->orderBy(new OrderByItem(Column::name('id')));
+
+ self::assertNotSame($builder1, $builder2);
+ }
+
+ public function test_immutability_select() : void
+ {
+ $builder1 = SelectBuilder::create();
+ $builder2 = $builder1->select(Column::name('id'));
+
+ self::assertNotSame($builder1, $builder2);
+ }
+
+ public function test_immutability_where() : void
+ {
+ $builder1 = SelectBuilder::create()
+ ->select(Column::name('id'))
+ ->from(new Table('users'));
+ $builder2 = $builder1->where(new Comparison(Column::name('active'), ComparisonOperator::EQ, Literal::bool(true)));
+
+ self::assertNotSame($builder1, $builder2);
+ }
+
+ public function test_round_trip_simple() : void
+ {
+ $original = SelectBuilder::create()
+ ->select(Column::name('id'), Column::name('name'))
+ ->from(new Table('users'))
+ ->where(new Comparison(Column::name('active'), ComparisonOperator::EQ, Literal::bool(true)))
+ ->orderBy(new OrderByItem(Column::name('name')))
+ ->limit(10);
+
+ $ast = $original->toAst();
+ $node = new Node();
+ $node->setSelectStmt($ast);
+
+ $restored = SelectBuilder::fromAst($node);
+ $restoredAst = $restored->toAst();
+
+ self::assertEquals($ast->serializeToString(), $restoredAst->serializeToString());
+ }
+
+ public function test_round_trip_with_aggregate() : void
+ {
+ $original = SelectBuilder::create()
+ ->select(
+ Column::name('category'),
+ new AggregateCall(['count'], [], true),
+ new AggregateCall(['sum'], [Column::name('price')])
+ )
+ ->from(new Table('products'))
+ ->groupBy(Column::name('category'))
+ ->having(new Comparison(new AggregateCall(['count'], [], true), ComparisonOperator::GT, Literal::int(5)))
+ ->orderBy(new OrderByItem(Column::name('category')));
+
+ $ast = $original->toAst();
+ $node = new Node();
+ $node->setSelectStmt($ast);
+
+ $restored = SelectBuilder::fromAst($node);
+ $restoredAst = $restored->toAst();
+
+ self::assertEquals($ast->serializeToString(), $restoredAst->serializeToString());
+ }
+
+ public function test_round_trip_with_joins() : void
+ {
+ $original = SelectBuilder::create()
+ ->select(Column::tableColumn('u', 'name'), Column::tableColumn('o', 'total'))
+ ->from((new Table('users'))->as('u'))
+ ->leftJoin(
+ (new Table('orders'))->as('o'),
+ new Comparison(Column::tableColumn('u', 'id'), ComparisonOperator::EQ, Column::tableColumn('o', 'user_id'))
+ )
+ ->where(new Comparison(Column::tableColumn('o', 'total'), ComparisonOperator::GT, Literal::int(100)))
+ ->orderBy(new OrderByItem(Column::tableColumn('o', 'total'), SortDirection::DESC));
+
+ $ast = $original->toAst();
+ $node = new Node();
+ $node->setSelectStmt($ast);
+
+ $restored = SelectBuilder::fromAst($node);
+ $restoredAst = $restored->toAst();
+
+ self::assertEquals($ast->serializeToString(), $restoredAst->serializeToString());
+ }
+
+ public function test_round_trip_with_set_operation() : void
+ {
+ $query1 = SelectBuilder::create()
+ ->select(Column::name('id'))
+ ->from(new Table('table1'))
+ ->where(new Comparison(Column::name('active'), ComparisonOperator::EQ, Literal::bool(true)));
+
+ $query2 = SelectBuilder::create()
+ ->select(Column::name('id'))
+ ->from(new Table('table2'));
+
+ $original = $query1->union($query2)
+ ->orderBy(new OrderByItem(Column::name('id')))
+ ->limit(20);
+
+ $ast = $original->toAst();
+ $node = new Node();
+ $node->setSelectStmt($ast);
+
+ $restored = SelectBuilder::fromAst($node);
+ $restoredAst = $restored->toAst();
+
+ self::assertEquals($ast->serializeToString(), $restoredAst->serializeToString());
+ }
+
+ public function test_select_distinct() : void
+ {
+ $query = SelectBuilder::create()
+ ->selectDistinct(Column::name('city'))
+ ->from(new Table('users'));
+
+ $ast = $query->toAst();
+ $distinctClause = $ast->getDistinctClause();
+
+ self::assertNotNull($distinctClause);
+ }
+
+ public function test_select_distinct_on() : void
+ {
+ $query = SelectBuilder::create()
+ ->selectDistinctOn([Column::name('category')], Column::name('category'), Column::name('product_name'))
+ ->from(new Table('products'));
+
+ $ast = $query->toAst();
+ $distinctClause = $ast->getDistinctClause();
+
+ self::assertNotNull($distinctClause);
+ self::assertCount(1, $distinctClause);
+ }
+
+ public function test_select_from_multiple_tables() : void
+ {
+ $query = SelectBuilder::create()
+ ->select(Star::all())
+ ->from(new Table('users'), new Table('orders'));
+
+ $ast = $query->toAst();
+ $fromClause = $ast->getFromClause();
+
+ self::assertNotNull($fromClause);
+ self::assertCount(2, $fromClause);
+ }
+
+ public function test_select_only_limit() : void
+ {
+ $query = SelectBuilder::create()
+ ->select(Star::all())
+ ->from(new Table('users'))
+ ->limit(10);
+
+ $ast = $query->toAst();
+ $limitCount = $ast->getLimitCount();
+ $limitOffset = $ast->getLimitOffset();
+
+ self::assertNotNull($limitCount);
+ self::assertNull($limitOffset);
+ }
+
+ public function test_select_only_offset() : void
+ {
+ $query = SelectBuilder::create()
+ ->select(Star::all())
+ ->from(new Table('users'))
+ ->offset(20);
+
+ $ast = $query->toAst();
+ $limitCount = $ast->getLimitCount();
+ $limitOffset = $ast->getLimitOffset();
+
+ self::assertNull($limitCount);
+ self::assertNotNull($limitOffset);
+ }
+
+ public function test_select_star() : void
+ {
+ $query = SelectBuilder::create()
+ ->select(Star::all())
+ ->from(new Table('users'));
+
+ $ast = $query->toAst();
+ $targetList = $ast->getTargetList();
+
+ self::assertNotNull($targetList);
+ self::assertCount(1, $targetList);
+ }
+
+ public function test_select_with_cross_join() : void
+ {
+ $query = SelectBuilder::create()
+ ->select(Star::all())
+ ->from(new Table('t1'))
+ ->crossJoin(new Table('t2'));
+
+ $ast = $query->toAst();
+ $fromClause = $ast->getFromClause();
+
+ self::assertNotNull($fromClause);
+ }
+
+ public function test_select_with_except() : void
+ {
+ $query1 = SelectBuilder::create()
+ ->select(Column::name('id'))
+ ->from(new Table('table1'));
+
+ $query2 = SelectBuilder::create()
+ ->select(Column::name('id'))
+ ->from(new Table('table2'));
+
+ $exceptQuery = $query1->except($query2);
+
+ $ast = $exceptQuery->toAst();
+
+ self::assertNotNull($ast->getLarg());
+ self::assertNotNull($ast->getRarg());
+ }
+
+ public function test_select_with_for_key_share() : void
+ {
+ $query = SelectBuilder::create()
+ ->select(Star::all())
+ ->from(new Table('users'))
+ ->forKeyShare();
+
+ $ast = $query->toAst();
+ $lockingClause = $ast->getLockingClause();
+
+ self::assertNotNull($lockingClause);
+ self::assertCount(1, $lockingClause);
+ }
+
+ public function test_select_with_for_no_key_update() : void
+ {
+ $query = SelectBuilder::create()
+ ->select(Star::all())
+ ->from(new Table('users'))
+ ->forNoKeyUpdate();
+
+ $ast = $query->toAst();
+ $lockingClause = $ast->getLockingClause();
+
+ self::assertNotNull($lockingClause);
+ self::assertCount(1, $lockingClause);
+ }
+
+ public function test_select_with_for_share() : void
+ {
+ $query = SelectBuilder::create()
+ ->select(Star::all())
+ ->from(new Table('users'))
+ ->forShare();
+
+ $ast = $query->toAst();
+ $lockingClause = $ast->getLockingClause();
+
+ self::assertNotNull($lockingClause);
+ self::assertCount(1, $lockingClause);
+ }
+
+ public function test_select_with_for_update() : void
+ {
+ $query = SelectBuilder::create()
+ ->select(Star::all())
+ ->from(new Table('users'))
+ ->forUpdate();
+
+ $ast = $query->toAst();
+ $lockingClause = $ast->getLockingClause();
+
+ self::assertNotNull($lockingClause);
+ self::assertCount(1, $lockingClause);
+ }
+
+ public function test_select_with_full_join() : void
+ {
+ $query = SelectBuilder::create()
+ ->select(Star::all())
+ ->from((new Table('users'))->as('u'))
+ ->fullJoin(
+ (new Table('orders'))->as('o'),
+ new Comparison(Column::tableColumn('u', 'id'), ComparisonOperator::EQ, Column::tableColumn('o', 'user_id'))
+ );
+
+ $ast = $query->toAst();
+ $fromClause = $ast->getFromClause();
+
+ self::assertNotNull($fromClause);
+ }
+
+ public function test_select_with_group_by_having() : void
+ {
+ $query = SelectBuilder::create()
+ ->select(Column::name('category'), new AggregateCall(['count'], [], true))
+ ->from(new Table('products'))
+ ->groupBy(Column::name('category'))
+ ->having(new Comparison(new AggregateCall(['count'], [], true), ComparisonOperator::GT, Literal::int(5)));
+
+ $ast = $query->toAst();
+ $groupClause = $ast->getGroupClause();
+ $havingClause = $ast->getHavingClause();
+
+ self::assertNotNull($groupClause);
+ self::assertCount(1, $groupClause);
+ self::assertNotNull($havingClause);
+ }
+
+ public function test_select_with_inner_join() : void
+ {
+ $query = SelectBuilder::create()
+ ->select(Star::all())
+ ->from((new Table('users'))->as('u'))
+ ->join(
+ (new Table('orders'))->as('o'),
+ new Comparison(Column::tableColumn('u', 'id'), ComparisonOperator::EQ, Column::tableColumn('o', 'user_id'))
+ );
+
+ $ast = $query->toAst();
+ $fromClause = $ast->getFromClause();
+
+ self::assertNotNull($fromClause);
+ }
+
+ public function test_select_with_intersect() : void
+ {
+ $query1 = SelectBuilder::create()
+ ->select(Column::name('id'))
+ ->from(new Table('table1'));
+
+ $query2 = SelectBuilder::create()
+ ->select(Column::name('id'))
+ ->from(new Table('table2'));
+
+ $intersectQuery = $query1->intersect($query2);
+
+ $ast = $intersectQuery->toAst();
+
+ self::assertNotNull($ast->getLarg());
+ self::assertNotNull($ast->getRarg());
+ }
+
+ public function test_select_with_join() : void
+ {
+ $query = SelectBuilder::create()
+ ->select(Column::tableColumn('u', 'name'), Column::tableColumn('o', 'total'))
+ ->from((new Table('users'))->as('u'))
+ ->leftJoin(
+ (new Table('orders'))->as('o'),
+ new Comparison(Column::tableColumn('u', 'id'), ComparisonOperator::EQ, Column::tableColumn('o', 'user_id'))
+ );
+
+ $ast = $query->toAst();
+ $fromClause = $ast->getFromClause();
+
+ self::assertNotNull($fromClause);
+ self::assertCount(1, $fromClause);
+ }
+
+ public function test_select_with_multiple_joins() : void
+ {
+ $query = SelectBuilder::create()
+ ->select(Star::all())
+ ->from((new Table('users'))->as('u'))
+ ->leftJoin(
+ (new Table('orders'))->as('o'),
+ new Comparison(Column::tableColumn('u', 'id'), ComparisonOperator::EQ, Column::tableColumn('o', 'user_id'))
+ )
+ ->leftJoin(
+ (new Table('payments'))->as('p'),
+ new Comparison(Column::tableColumn('o', 'id'), ComparisonOperator::EQ, Column::tableColumn('p', 'order_id'))
+ );
+
+ $ast = $query->toAst();
+ $fromClause = $ast->getFromClause();
+
+ self::assertNotNull($fromClause);
+ }
+
+ public function test_select_with_order_by_multiple_columns() : void
+ {
+ $query = SelectBuilder::create()
+ ->select(Star::all())
+ ->from(new Table('users'))
+ ->orderBy(
+ new OrderByItem(Column::name('last_name')),
+ new OrderByItem(Column::name('first_name'), SortDirection::DESC)
+ );
+
+ $ast = $query->toAst();
+ $sortClause = $ast->getSortClause();
+
+ self::assertNotNull($sortClause);
+ self::assertCount(2, $sortClause);
+ }
+
+ public function test_select_with_order_limit_offset() : void
+ {
+ $query = SelectBuilder::create()
+ ->select(Star::all())
+ ->from(new Table('events'))
+ ->orderBy(new OrderByItem(Column::name('created_at'), SortDirection::DESC))
+ ->limit(10)
+ ->offset(20);
+
+ $ast = $query->toAst();
+ $sortClause = $ast->getSortClause();
+ $limitCount = $ast->getLimitCount();
+ $limitOffset = $ast->getLimitOffset();
+
+ self::assertNotNull($sortClause);
+ self::assertCount(1, $sortClause);
+ self::assertNotNull($limitCount);
+ self::assertNotNull($limitOffset);
+ }
+
+ public function test_select_with_right_join() : void
+ {
+ $query = SelectBuilder::create()
+ ->select(Star::all())
+ ->from((new Table('users'))->as('u'))
+ ->rightJoin(
+ (new Table('orders'))->as('o'),
+ new Comparison(Column::tableColumn('u', 'id'), ComparisonOperator::EQ, Column::tableColumn('o', 'user_id'))
+ );
+
+ $ast = $query->toAst();
+ $fromClause = $ast->getFromClause();
+
+ self::assertNotNull($fromClause);
+ }
+
+ public function test_select_with_schema_qualified_table() : void
+ {
+ $query = SelectBuilder::create()
+ ->select(Star::all())
+ ->from(new Table('users', 'public'));
+
+ $ast = $query->toAst();
+ $fromClause = $ast->getFromClause();
+
+ self::assertNotNull($fromClause);
+ self::assertCount(1, $fromClause);
+
+ $rangeVar = $fromClause[0]->getRangeVar();
+ self::assertNotNull($rangeVar);
+ self::assertSame('public', $rangeVar->getSchemaname());
+ }
+
+ public function test_select_with_union() : void
+ {
+ $query1 = SelectBuilder::create()
+ ->select(Column::name('name'))
+ ->from(new Table('users'));
+
+ $query2 = SelectBuilder::create()
+ ->select(Column::name('name'))
+ ->from(new Table('admins'));
+
+ $unionQuery = $query1->union($query2);
+
+ $ast = $unionQuery->toAst();
+
+ self::assertNotNull($ast->getLarg());
+ self::assertNotNull($ast->getRarg());
+ }
+
+ public function test_select_with_union_all() : void
+ {
+ $query1 = SelectBuilder::create()
+ ->select(Column::name('id'))
+ ->from(new Table('table1'));
+
+ $query2 = SelectBuilder::create()
+ ->select(Column::name('id'))
+ ->from(new Table('table2'));
+
+ $unionQuery = $query1->unionAll($query2);
+
+ $ast = $unionQuery->toAst();
+
+ self::assertTrue($ast->getAll());
+ }
+
+ public function test_select_with_where() : void
+ {
+ $query = SelectBuilder::create()
+ ->select(Star::all())
+ ->from(new Table('users'))
+ ->where(new Comparison(Column::name('active'), ComparisonOperator::EQ, Literal::bool(true)));
+
+ $ast = $query->toAst();
+ $whereClause = $ast->getWhereClause();
+
+ self::assertNotNull($whereClause);
+ }
+
+ public function test_simple_select() : void
+ {
+ $query = SelectBuilder::create()
+ ->select(Column::name('id'), Column::name('name'))
+ ->from(new Table('users'));
+
+ $ast = $query->toAst();
+ self::assertInstanceOf(SelectStmt::class, $ast);
+
+ $targetList = $ast->getTargetList();
+ self::assertNotNull($targetList);
+ self::assertCount(2, $targetList);
+
+ $fromClause = $ast->getFromClause();
+ self::assertNotNull($fromClause);
+ self::assertCount(1, $fromClause);
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Table/AliasedTableTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Table/AliasedTableTest.php
new file mode 100644
index 000000000..64d0be9e3
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Table/AliasedTableTest.php
@@ -0,0 +1,120 @@
+as('usr');
+
+ self::assertNotSame($aliased, $newAliased);
+ self::assertInstanceOf(AliasedTable::class, $newAliased);
+ self::assertSame('usr', $newAliased->alias);
+ }
+
+ public function test_converts_aliased_table_to_ast() : void
+ {
+ $table = new Table('users', 'public');
+ $aliased = new AliasedTable($table, 'u');
+
+ $node = $aliased->toAst();
+
+ self::assertTrue($node->hasRangeVar());
+
+ $rangeVar = $node->getRangeVar();
+ self::assertInstanceOf(\Flow\PostgreSql\Protobuf\AST\RangeVar::class, $rangeVar);
+ self::assertSame('users', $rangeVar->getRelname());
+ self::assertSame('public', $rangeVar->getSchemaname());
+
+ $alias = $rangeVar->getAlias();
+ self::assertInstanceOf(\Flow\PostgreSql\Protobuf\AST\Alias::class, $alias);
+ self::assertSame('u', $alias->getAliasname());
+ self::assertCount(0, $alias->getColnames());
+ }
+
+ public function test_converts_aliased_table_with_column_aliases_to_ast() : void
+ {
+ $table = new Table('users');
+ $aliased = new AliasedTable($table, 'u', ['id', 'name']);
+
+ $node = $aliased->toAst();
+
+ self::assertTrue($node->hasRangeVar());
+
+ $rangeVar = $node->getRangeVar();
+ self::assertInstanceOf(\Flow\PostgreSql\Protobuf\AST\RangeVar::class, $rangeVar);
+ $alias = $rangeVar->getAlias();
+ self::assertInstanceOf(\Flow\PostgreSql\Protobuf\AST\Alias::class, $alias);
+
+ self::assertSame('u', $alias->getAliasname());
+
+ $colnames = $alias->getColnames();
+ self::assertCount(2, $colnames);
+
+ $col1 = $colnames[0]->getString();
+ self::assertInstanceOf(\Flow\PostgreSql\Protobuf\AST\PBString::class, $col1);
+ self::assertSame('id', $col1->getSval());
+
+ $col2 = $colnames[1]->getString();
+ self::assertInstanceOf(\Flow\PostgreSql\Protobuf\AST\PBString::class, $col2);
+ self::assertSame('name', $col2->getSval());
+ }
+
+ public function test_creates_aliased_table() : void
+ {
+ $table = new Table('users');
+ $aliased = new AliasedTable($table, 'u');
+
+ self::assertSame($table, $aliased->table);
+ self::assertSame('u', $aliased->alias);
+ self::assertNull($aliased->columnAliases);
+ }
+
+ public function test_creates_aliased_table_with_column_aliases() : void
+ {
+ $table = new Table('users');
+ $aliased = new AliasedTable($table, 'u', ['id', 'name']);
+
+ self::assertSame($table, $aliased->table);
+ self::assertSame('u', $aliased->alias);
+ self::assertSame(['id', 'name'], $aliased->columnAliases);
+ }
+
+ public function test_reconstructs_aliased_table_from_ast() : void
+ {
+ $table = new Table('users', 'public');
+ $original = new AliasedTable($table, 'u');
+
+ $node = $original->toAst();
+ $reconstructed = AliasedTable::fromAst($node);
+
+ self::assertInstanceOf(AliasedTable::class, $reconstructed);
+ self::assertSame('u', $reconstructed->alias);
+ self::assertInstanceOf(Table::class, $reconstructed->table);
+ self::assertSame('users', $reconstructed->table->name);
+ self::assertSame('public', $reconstructed->table->schema);
+ self::assertNull($reconstructed->columnAliases);
+ }
+
+ public function test_reconstructs_aliased_table_with_column_aliases_from_ast() : void
+ {
+ $table = new Table('users');
+ $original = new AliasedTable($table, 'u', ['id', 'name']);
+
+ $node = $original->toAst();
+ $reconstructed = AliasedTable::fromAst($node);
+
+ self::assertInstanceOf(AliasedTable::class, $reconstructed);
+ self::assertSame('u', $reconstructed->alias);
+ self::assertSame(['id', 'name'], $reconstructed->columnAliases);
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Table/DerivedTableTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Table/DerivedTableTest.php
new file mode 100644
index 000000000..074cebccf
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Table/DerivedTableTest.php
@@ -0,0 +1,148 @@
+ new SelectStmt()]);
+ $derived = new DerivedTable($subquery, 'subq');
+
+ $aliased = $derived->as('sq');
+
+ self::assertInstanceOf(AliasedTable::class, $aliased);
+ self::assertSame('sq', $aliased->alias);
+ }
+
+ public function test_converts_derived_table_to_ast() : void
+ {
+ $subquery = new Node(['select_stmt' => new SelectStmt()]);
+ $derived = new DerivedTable($subquery, 'subq');
+
+ $node = $derived->toAst();
+
+ self::assertTrue($node->hasRangeSubselect());
+
+ $rangeSubselect = $node->getRangeSubselect();
+ self::assertInstanceOf(\Flow\PostgreSql\Protobuf\AST\RangeSubselect::class, $rangeSubselect);
+
+ $alias = $rangeSubselect->getAlias();
+ self::assertInstanceOf(\Flow\PostgreSql\Protobuf\AST\Alias::class, $alias);
+ self::assertSame('subq', $alias->getAliasname());
+ self::assertCount(0, $alias->getColnames());
+
+ self::assertFalse($rangeSubselect->getLateral());
+
+ $subqueryNode = $rangeSubselect->getSubquery();
+ self::assertInstanceOf(\Flow\PostgreSql\Protobuf\AST\Node::class, $subqueryNode);
+ self::assertTrue($subqueryNode->hasSelectStmt());
+ }
+
+ public function test_converts_derived_table_with_column_aliases_to_ast() : void
+ {
+ $subquery = new Node(['select_stmt' => new SelectStmt()]);
+ $derived = new DerivedTable($subquery, 'subq', ['id', 'name']);
+
+ $node = $derived->toAst();
+
+ $rangeSubselect = $node->getRangeSubselect();
+ self::assertInstanceOf(\Flow\PostgreSql\Protobuf\AST\RangeSubselect::class, $rangeSubselect);
+ $alias = $rangeSubselect->getAlias();
+
+ self::assertInstanceOf(\Flow\PostgreSql\Protobuf\AST\Alias::class, $alias);
+ self::assertSame('subq', $alias->getAliasname());
+
+ $colnames = $alias->getColnames();
+ self::assertCount(2, $colnames);
+
+ $col1 = $colnames[0]->getString();
+ self::assertInstanceOf(\Flow\PostgreSql\Protobuf\AST\PBString::class, $col1);
+ self::assertSame('id', $col1->getSval());
+
+ $col2 = $colnames[1]->getString();
+ self::assertInstanceOf(\Flow\PostgreSql\Protobuf\AST\PBString::class, $col2);
+ self::assertSame('name', $col2->getSval());
+ }
+
+ public function test_converts_lateral_derived_table_to_ast() : void
+ {
+ $subquery = new Node(['select_stmt' => new SelectStmt()]);
+ $derived = new DerivedTable($subquery, 'subq', null, true);
+
+ $node = $derived->toAst();
+
+ $rangeSubselect = $node->getRangeSubselect();
+ self::assertInstanceOf(\Flow\PostgreSql\Protobuf\AST\RangeSubselect::class, $rangeSubselect);
+ self::assertTrue($rangeSubselect->getLateral());
+ }
+
+ public function test_creates_derived_table() : void
+ {
+ $subquery = new Node(['select_stmt' => new SelectStmt()]);
+ $derived = new DerivedTable($subquery, 'subq');
+
+ self::assertSame($subquery, $derived->subquery);
+ self::assertSame('subq', $derived->alias);
+ self::assertNull($derived->columnAliases);
+ self::assertFalse($derived->lateral);
+ }
+
+ public function test_creates_derived_table_with_column_aliases() : void
+ {
+ $subquery = new Node(['select_stmt' => new SelectStmt()]);
+ $derived = new DerivedTable($subquery, 'subq', ['id', 'name']);
+
+ self::assertSame(['id', 'name'], $derived->columnAliases);
+ }
+
+ public function test_creates_lateral_derived_table() : void
+ {
+ $subquery = new Node(['select_stmt' => new SelectStmt()]);
+ $derived = new DerivedTable($subquery, 'subq', null, true);
+
+ self::assertTrue($derived->lateral);
+ }
+
+ public function test_reconstructs_derived_table_from_ast() : void
+ {
+ $subquery = new Node(['select_stmt' => new SelectStmt()]);
+ $original = new DerivedTable($subquery, 'subq');
+
+ $node = $original->toAst();
+ $reconstructed = DerivedTable::fromAst($node);
+
+ self::assertInstanceOf(DerivedTable::class, $reconstructed);
+ self::assertSame('subq', $reconstructed->alias);
+ self::assertNull($reconstructed->columnAliases);
+ self::assertFalse($reconstructed->lateral);
+ }
+
+ public function test_reconstructs_derived_table_with_column_aliases_from_ast() : void
+ {
+ $subquery = new Node(['select_stmt' => new SelectStmt()]);
+ $original = new DerivedTable($subquery, 'subq', ['id', 'name']);
+
+ $node = $original->toAst();
+ $reconstructed = DerivedTable::fromAst($node);
+
+ self::assertSame(['id', 'name'], $reconstructed->columnAliases);
+ }
+
+ public function test_reconstructs_lateral_derived_table_from_ast() : void
+ {
+ $subquery = new Node(['select_stmt' => new SelectStmt()]);
+ $original = new DerivedTable($subquery, 'subq', null, true);
+
+ $node = $original->toAst();
+ $reconstructed = DerivedTable::fromAst($node);
+
+ self::assertTrue($reconstructed->lateral);
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Table/JoinedTableTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Table/JoinedTableTest.php
new file mode 100644
index 000000000..bd3c47654
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Table/JoinedTableTest.php
@@ -0,0 +1,194 @@
+as('j');
+
+ self::assertInstanceOf(AliasedTable::class, $aliased);
+ self::assertSame('j', $aliased->alias);
+ }
+
+ public function test_converts_inner_join_with_on_condition_to_ast() : void
+ {
+ $left = new Table('users');
+ $right = new Table('orders');
+ $condition = new Comparison(
+ Column::name('user_id'),
+ ComparisonOperator::EQ,
+ Column::name('id')
+ );
+
+ $joined = new JoinedTable($left, $right, JoinType::INNER, $condition);
+
+ $node = $joined->toAst();
+
+ self::assertTrue($node->hasJoinExpr());
+
+ $joinExpr = $node->getJoinExpr();
+ self::assertInstanceOf(\Flow\PostgreSql\Protobuf\AST\JoinExpr::class, $joinExpr);
+ self::assertSame(ProtobufJoinType::JOIN_INNER, $joinExpr->getJointype());
+
+ $larg = $joinExpr->getLarg();
+ self::assertInstanceOf(\Flow\PostgreSql\Protobuf\AST\Node::class, $larg);
+ self::assertTrue($larg->hasRangeVar());
+ $largRangeVar = $larg->getRangeVar();
+ self::assertInstanceOf(\Flow\PostgreSql\Protobuf\AST\RangeVar::class, $largRangeVar);
+ self::assertSame('users', $largRangeVar->getRelname());
+
+ $rarg = $joinExpr->getRarg();
+ self::assertInstanceOf(\Flow\PostgreSql\Protobuf\AST\Node::class, $rarg);
+ self::assertTrue($rarg->hasRangeVar());
+ $rargRangeVar = $rarg->getRangeVar();
+ self::assertInstanceOf(\Flow\PostgreSql\Protobuf\AST\RangeVar::class, $rargRangeVar);
+ self::assertSame('orders', $rargRangeVar->getRelname());
+
+ $quals = $joinExpr->getQuals();
+ self::assertInstanceOf(\Flow\PostgreSql\Protobuf\AST\Node::class, $quals);
+
+ self::assertFalse($joinExpr->getIsNatural());
+ }
+
+ public function test_converts_left_join_to_ast() : void
+ {
+ $left = new Table('users');
+ $right = new Table('orders');
+ $condition = new Comparison(
+ Column::name('user_id'),
+ ComparisonOperator::EQ,
+ Column::name('id')
+ );
+
+ $joined = new JoinedTable($left, $right, JoinType::LEFT, $condition);
+
+ $node = $joined->toAst();
+
+ $joinExpr = $node->getJoinExpr();
+ self::assertInstanceOf(\Flow\PostgreSql\Protobuf\AST\JoinExpr::class, $joinExpr);
+ self::assertSame(ProtobufJoinType::JOIN_LEFT, $joinExpr->getJointype());
+ }
+
+ public function test_converts_natural_join_to_ast() : void
+ {
+ $left = new Table('users');
+ $right = new Table('orders');
+
+ $joined = new JoinedTable($left, $right, JoinType::INNER, null, null, true);
+
+ $node = $joined->toAst();
+
+ $joinExpr = $node->getJoinExpr();
+ self::assertInstanceOf(\Flow\PostgreSql\Protobuf\AST\JoinExpr::class, $joinExpr);
+ self::assertTrue($joinExpr->getIsNatural());
+ self::assertNull($joinExpr->getQuals());
+ }
+
+ public function test_converts_using_clause_to_ast() : void
+ {
+ $left = new Table('users');
+ $right = new Table('orders');
+
+ $joined = new JoinedTable($left, $right, JoinType::INNER, null, ['user_id']);
+
+ $node = $joined->toAst();
+
+ $joinExpr = $node->getJoinExpr();
+ self::assertInstanceOf(\Flow\PostgreSql\Protobuf\AST\JoinExpr::class, $joinExpr);
+ $usingClause = $joinExpr->getUsingClause();
+
+ self::assertCount(1, $usingClause);
+
+ $col = $usingClause[0]->getString();
+ self::assertInstanceOf(\Flow\PostgreSql\Protobuf\AST\PBString::class, $col);
+ self::assertSame('user_id', $col->getSval());
+ }
+
+ public function test_creates_joined_table_with_condition() : void
+ {
+ $left = new Table('users');
+ $right = new Table('orders');
+ $condition = new Comparison(
+ Column::name('user_id'),
+ ComparisonOperator::EQ,
+ Column::name('id')
+ );
+
+ $joined = new JoinedTable($left, $right, JoinType::INNER, $condition);
+
+ self::assertSame($left, $joined->left);
+ self::assertSame($right, $joined->right);
+ self::assertSame(JoinType::INNER, $joined->joinType);
+ self::assertSame($condition, $joined->onCondition);
+ self::assertNull($joined->usingColumns);
+ self::assertFalse($joined->natural);
+ }
+
+ public function test_creates_joined_table_with_using_clause() : void
+ {
+ $left = new Table('users');
+ $right = new Table('orders');
+
+ $joined = new JoinedTable($left, $right, JoinType::INNER, null, ['user_id']);
+
+ self::assertSame(['user_id'], $joined->usingColumns);
+ self::assertNull($joined->onCondition);
+ }
+
+ public function test_reconstructs_joined_table_from_ast() : void
+ {
+ $left = new Table('users');
+ $right = new Table('orders');
+ $condition = new Comparison(
+ Column::name('user_id'),
+ ComparisonOperator::EQ,
+ Column::name('id')
+ );
+
+ $original = new JoinedTable($left, $right, JoinType::LEFT, $condition);
+
+ $node = $original->toAst();
+ $reconstructed = JoinedTable::fromAst($node);
+
+ self::assertInstanceOf(JoinedTable::class, $reconstructed);
+ self::assertSame(JoinType::LEFT, $reconstructed->joinType);
+ self::assertInstanceOf(Table::class, $reconstructed->left);
+ self::assertInstanceOf(Table::class, $reconstructed->right);
+ self::assertNotNull($reconstructed->onCondition);
+ }
+
+ public function test_reconstructs_joined_table_with_using_from_ast() : void
+ {
+ $left = new Table('users');
+ $right = new Table('orders');
+
+ $original = new JoinedTable($left, $right, JoinType::INNER, null, ['user_id', 'status']);
+
+ $node = $original->toAst();
+ $reconstructed = JoinedTable::fromAst($node);
+
+ self::assertInstanceOf(JoinedTable::class, $reconstructed);
+ self::assertSame(['user_id', 'status'], $reconstructed->usingColumns);
+ self::assertNull($reconstructed->onCondition);
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Table/LateralTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Table/LateralTest.php
new file mode 100644
index 000000000..cbf71649f
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Table/LateralTest.php
@@ -0,0 +1,180 @@
+createSubqueryNode();
+ $lateral = new Lateral(new SubqueryReference($subquery));
+
+ $aliased = $lateral->as('l');
+
+ self::assertInstanceOf(AliasedTable::class, $aliased);
+ self::assertSame('l', $aliased->alias);
+ }
+
+ public function test_as_method_with_column_aliases_returns_aliased_table() : void
+ {
+ $subquery = $this->createSubqueryNode();
+ $lateral = new Lateral(new SubqueryReference($subquery));
+
+ $aliased = $lateral->as('l', ['col1', 'col2']);
+
+ self::assertInstanceOf(AliasedTable::class, $aliased);
+ self::assertSame('l', $aliased->alias);
+ self::assertSame(['col1', 'col2'], $aliased->columnAliases);
+ }
+
+ public function test_converts_lateral_function_to_ast() : void
+ {
+ $func = new FunctionCall(['unnest'], []);
+ $tableFunc = new TableFunction($func);
+ $lateral = new Lateral($tableFunc);
+
+ $node = $lateral->toAst();
+
+ self::assertTrue($node->hasRangeFunction());
+
+ $rangeFunction = $node->getRangeFunction();
+ self::assertInstanceOf(\Flow\PostgreSql\Protobuf\AST\RangeFunction::class, $rangeFunction);
+ self::assertTrue($rangeFunction->getLateral());
+ self::assertFalse($rangeFunction->getOrdinality());
+ }
+
+ public function test_converts_lateral_subquery_to_ast() : void
+ {
+ $subquery = $this->createSubqueryNode();
+ $lateral = new Lateral(new SubqueryReference($subquery));
+
+ $node = $lateral->toAst();
+
+ self::assertTrue($node->hasRangeSubselect());
+
+ $rangeSubselect = $node->getRangeSubselect();
+ self::assertInstanceOf(\Flow\PostgreSql\Protobuf\AST\RangeSubselect::class, $rangeSubselect);
+ self::assertTrue($rangeSubselect->getLateral());
+ $subqueryNode = $rangeSubselect->getSubquery();
+ self::assertInstanceOf(\Flow\PostgreSql\Protobuf\AST\Node::class, $subqueryNode);
+ }
+
+ public function test_creates_lateral_with_function() : void
+ {
+ $func = new FunctionCall(['generate_series'], []);
+ $tableFunc = new TableFunction($func);
+ $lateral = new Lateral($tableFunc);
+
+ self::assertInstanceOf(TableFunction::class, $lateral->getReference());
+ }
+
+ public function test_creates_lateral_with_subquery() : void
+ {
+ $subquery = $this->createSubqueryNode();
+ $lateral = new Lateral(new SubqueryReference($subquery));
+
+ self::assertInstanceOf(SubqueryReference::class, $lateral->getReference());
+ }
+
+ public function test_reconstructs_lateral_function_from_ast() : void
+ {
+ $func = new FunctionCall(['unnest'], []);
+ $tableFunc = new TableFunction($func);
+ $original = new Lateral($tableFunc);
+
+ $node = $original->toAst();
+ $reconstructed = Lateral::fromAst($node);
+
+ self::assertInstanceOf(TableFunction::class, $reconstructed->getReference());
+ }
+
+ public function test_reconstructs_lateral_subquery_from_ast() : void
+ {
+ $subquery = $this->createSubqueryNode();
+ $original = new Lateral(new SubqueryReference($subquery));
+
+ $node = $original->toAst();
+ $reconstructed = Lateral::fromAst($node);
+
+ self::assertInstanceOf(SubqueryReference::class, $reconstructed->getReference());
+ }
+
+ public function test_round_trip_conversion_with_function() : void
+ {
+ $func = new FunctionCall(['generate_series'], []);
+ $tableFunc = new TableFunction($func);
+ $lateral = new Lateral($tableFunc);
+
+ $node = $lateral->toAst();
+ $restored = Lateral::fromAst($node);
+
+ self::assertTrue($node->hasRangeFunction());
+ self::assertInstanceOf(TableFunction::class, $restored->getReference());
+ }
+
+ public function test_round_trip_conversion_with_subquery() : void
+ {
+ $subquery = $this->createSubqueryNode();
+ $lateral = new Lateral(new SubqueryReference($subquery));
+
+ $node = $lateral->toAst();
+ $restored = Lateral::fromAst($node);
+
+ self::assertTrue($node->hasRangeSubselect());
+ self::assertInstanceOf(SubqueryReference::class, $restored->getReference());
+ }
+
+ public function test_throws_exception_when_reconstructing_from_invalid_node_type() : void
+ {
+ $node = new Node();
+
+ $this->expectException(InvalidAstException::class);
+
+ Lateral::fromAst($node);
+ }
+
+ public function test_throws_exception_when_reconstructing_from_range_function_without_lateral() : void
+ {
+ $rangeFunction = new RangeFunction();
+ $rangeFunction->setLateral(false);
+
+ $node = new Node();
+ $node->setRangeFunction($rangeFunction);
+
+ $this->expectException(InvalidAstException::class);
+
+ Lateral::fromAst($node);
+ }
+
+ public function test_throws_exception_when_reconstructing_from_range_subselect_without_lateral() : void
+ {
+ $rangeSubselect = new RangeSubselect();
+ $rangeSubselect->setLateral(false);
+ $rangeSubselect->setSubquery($this->createSubqueryNode());
+
+ $node = new Node();
+ $node->setRangeSubselect($rangeSubselect);
+
+ $this->expectException(InvalidAstException::class);
+
+ Lateral::fromAst($node);
+ }
+
+ private function createSubqueryNode() : Node
+ {
+ $selectStmt = new SelectStmt();
+
+ $node = new Node();
+ $node->setSelectStmt($selectStmt);
+
+ return $node;
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Table/TableFunctionTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Table/TableFunctionTest.php
new file mode 100644
index 000000000..904922e39
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Table/TableFunctionTest.php
@@ -0,0 +1,174 @@
+as('g');
+
+ self::assertInstanceOf(AliasedTable::class, $aliased);
+ self::assertSame('g', $aliased->alias);
+ }
+
+ public function test_as_method_with_column_aliases_returns_aliased_table() : void
+ {
+ $func = new FunctionCall(['unnest'], []);
+ $tableFunc = new TableFunction($func);
+
+ $aliased = $tableFunc->as('u', ['value']);
+
+ self::assertInstanceOf(AliasedTable::class, $aliased);
+ self::assertSame('u', $aliased->alias);
+ self::assertSame(['value'], $aliased->columnAliases);
+ }
+
+ public function test_converts_table_function_to_ast() : void
+ {
+ $func = new FunctionCall(['generate_series'], [Literal::int(1), Literal::int(10)]);
+ $tableFunc = new TableFunction($func);
+
+ $node = $tableFunc->toAst();
+
+ self::assertTrue($node->hasRangeFunction());
+
+ $rangeFunction = $node->getRangeFunction();
+ self::assertInstanceOf(\Flow\PostgreSql\Protobuf\AST\RangeFunction::class, $rangeFunction);
+ self::assertFalse($rangeFunction->getLateral());
+ self::assertFalse($rangeFunction->getOrdinality());
+ self::assertFalse($rangeFunction->getIsRowsfrom());
+
+ $functions = $rangeFunction->getFunctions();
+ self::assertCount(1, $functions);
+
+ $listNode = $functions[0];
+ self::assertTrue($listNode->hasList());
+
+ $list = $listNode->getList();
+ self::assertInstanceOf(\Flow\PostgreSql\Protobuf\AST\PBList::class, $list);
+ $items = $list->getItems();
+ self::assertCount(1, $items);
+ }
+
+ public function test_converts_table_function_with_ordinality_to_ast() : void
+ {
+ $func = new FunctionCall(['unnest'], []);
+ $tableFunc = new TableFunction($func, true);
+
+ $node = $tableFunc->toAst();
+
+ self::assertTrue($node->hasRangeFunction());
+
+ $rangeFunction = $node->getRangeFunction();
+ self::assertInstanceOf(\Flow\PostgreSql\Protobuf\AST\RangeFunction::class, $rangeFunction);
+ self::assertTrue($rangeFunction->getOrdinality());
+ }
+
+ public function test_creates_table_function_with_function() : void
+ {
+ $func = new FunctionCall(['generate_series'], []);
+ $tableFunc = new TableFunction($func);
+
+ self::assertSame($func, $tableFunc->getFunction());
+ self::assertFalse($tableFunc->isWithOrdinality());
+ }
+
+ public function test_creates_table_function_with_ordinality() : void
+ {
+ $func = new FunctionCall(['unnest'], []);
+ $tableFunc = new TableFunction($func, true);
+
+ self::assertSame($func, $tableFunc->getFunction());
+ self::assertTrue($tableFunc->isWithOrdinality());
+ }
+
+ public function test_reconstructs_table_function_from_ast() : void
+ {
+ $func = new FunctionCall(['generate_series'], [Literal::int(1), Literal::int(5)]);
+ $original = new TableFunction($func, false);
+
+ $node = $original->toAst();
+ $reconstructed = TableFunction::fromAst($node);
+
+ self::assertSame($func->getFuncName(), $reconstructed->getFunction()->getFuncName());
+ self::assertFalse($reconstructed->isWithOrdinality());
+ }
+
+ public function test_reconstructs_table_function_with_ordinality_from_ast() : void
+ {
+ $func = new FunctionCall(['unnest'], []);
+ $original = new TableFunction($func, true);
+
+ $node = $original->toAst();
+ $reconstructed = TableFunction::fromAst($node);
+
+ self::assertTrue($reconstructed->isWithOrdinality());
+ }
+
+ public function test_round_trip_conversion() : void
+ {
+ $func = new FunctionCall(['json_array_elements'], []);
+ $tableFunc = new TableFunction($func, true);
+
+ $node = $tableFunc->toAst();
+ $restored = TableFunction::fromAst($node);
+
+ self::assertSame($func->getFuncName(), $restored->getFunction()->getFuncName());
+ self::assertTrue($restored->isWithOrdinality());
+ }
+
+ public function test_throws_exception_when_reconstructing_from_invalid_node_type() : void
+ {
+ $node = new Node();
+
+ $this->expectException(InvalidAstException::class);
+
+ TableFunction::fromAst($node);
+ }
+
+ public function test_throws_exception_when_reconstructing_from_range_function_without_functions() : void
+ {
+ $rangeFunction = new RangeFunction();
+
+ $node = new Node();
+ $node->setRangeFunction($rangeFunction);
+
+ $this->expectException(InvalidAstException::class);
+
+ TableFunction::fromAst($node);
+ }
+
+ public function test_with_ordinality_creates_new_instance() : void
+ {
+ $func = new FunctionCall(['generate_series'], []);
+ $tableFunc = new TableFunction($func, false);
+
+ $withOrdinality = $tableFunc->withOrdinality(true);
+
+ self::assertNotSame($tableFunc, $withOrdinality);
+ self::assertFalse($tableFunc->isWithOrdinality());
+ self::assertTrue($withOrdinality->isWithOrdinality());
+ }
+
+ public function test_with_ordinality_default_parameter() : void
+ {
+ $func = new FunctionCall(['generate_series'], []);
+ $tableFunc = new TableFunction($func, false);
+
+ $withOrdinality = $tableFunc->withOrdinality();
+
+ self::assertTrue($withOrdinality->isWithOrdinality());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Table/TableTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Table/TableTest.php
new file mode 100644
index 000000000..d7e6ed9b5
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Table/TableTest.php
@@ -0,0 +1,124 @@
+as('u');
+
+ self::assertInstanceOf(AliasedTable::class, $aliased);
+ }
+
+ public function test_as_method_with_column_aliases_returns_aliased_table() : void
+ {
+ $table = new Table('users');
+
+ $aliased = $table->as('u', ['id', 'name']);
+
+ self::assertInstanceOf(AliasedTable::class, $aliased);
+ self::assertSame(['id', 'name'], $aliased->columnAliases);
+ }
+
+ public function test_converts_table_to_ast() : void
+ {
+ $table = new Table('users', 'public');
+
+ $node = $table->toAst();
+
+ self::assertTrue($node->hasRangeVar());
+
+ $rangeVar = $node->getRangeVar();
+ self::assertInstanceOf(\Flow\PostgreSql\Protobuf\AST\RangeVar::class, $rangeVar);
+ self::assertSame('users', $rangeVar->getRelname());
+ self::assertSame('public', $rangeVar->getSchemaname());
+ self::assertTrue($rangeVar->getInh());
+ }
+
+ public function test_converts_table_without_schema_to_ast() : void
+ {
+ $table = new Table('users');
+
+ $node = $table->toAst();
+
+ self::assertTrue($node->hasRangeVar());
+
+ $rangeVar = $node->getRangeVar();
+ self::assertInstanceOf(\Flow\PostgreSql\Protobuf\AST\RangeVar::class, $rangeVar);
+ self::assertSame('users', $rangeVar->getRelname());
+ self::assertSame('', $rangeVar->getSchemaname());
+ self::assertTrue($rangeVar->getInh());
+ }
+
+ public function test_creates_table_with_name_only() : void
+ {
+ $table = new Table('users');
+
+ self::assertSame('users', $table->name);
+ self::assertNull($table->schema);
+ self::assertTrue($table->inherits);
+ }
+
+ public function test_creates_table_with_schema_and_name() : void
+ {
+ $table = new Table('users', 'public');
+
+ self::assertSame('users', $table->name);
+ self::assertSame('public', $table->schema);
+ self::assertTrue($table->inherits);
+ }
+
+ public function test_reconstructs_table_from_ast() : void
+ {
+ $original = new Table('users', 'public', false);
+
+ $node = $original->toAst();
+ $reconstructed = Table::fromAst($node);
+
+ self::assertSame('users', $reconstructed->name);
+ self::assertSame('public', $reconstructed->schema);
+ self::assertFalse($reconstructed->inherits);
+ }
+
+ public function test_reconstructs_table_without_schema_from_ast() : void
+ {
+ $original = new Table('users');
+
+ $node = $original->toAst();
+ $reconstructed = Table::fromAst($node);
+
+ self::assertSame('users', $reconstructed->name);
+ self::assertNull($reconstructed->schema);
+ self::assertTrue($reconstructed->inherits);
+ }
+
+ public function test_with_name_returns_new_instance() : void
+ {
+ $table = new Table('users', 'public');
+
+ $newTable = $table->withName('orders');
+
+ self::assertNotSame($table, $newTable);
+ self::assertSame('orders', $newTable->name);
+ self::assertSame('public', $newTable->schema);
+ }
+
+ public function test_with_schema_returns_new_instance() : void
+ {
+ $table = new Table('users', 'public');
+
+ $newTable = $table->withSchema('private');
+
+ self::assertNotSame($table, $newTable);
+ self::assertSame('users', $newTable->name);
+ self::assertSame('private', $newTable->schema);
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Transaction/BeginBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Transaction/BeginBuilderTest.php
new file mode 100644
index 000000000..8826a06ae
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Transaction/BeginBuilderTest.php
@@ -0,0 +1,170 @@
+toAst();
+
+ self::assertInstanceOf(TransactionStmt::class, $ast);
+ self::assertSame(TransactionStmtKind::TRANS_STMT_BEGIN, $ast->getKind());
+ self::assertCount(0, $ast->getOptions());
+ }
+
+ public function test_begin_deparsed_basic() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = BeginBuilder::create();
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame('BEGIN', $deparsed);
+ }
+
+ public function test_begin_deparsed_with_deferrable() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = BeginBuilder::create()
+ ->deferrable();
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame('BEGIN DEFERRABLE', $deparsed);
+ }
+
+ public function test_begin_deparsed_with_isolation_level_read_committed() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = BeginBuilder::create()
+ ->isolationLevel(IsolationLevel::READ_COMMITTED);
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame('BEGIN ISOLATION LEVEL READ COMMITTED', $deparsed);
+ }
+
+ public function test_begin_deparsed_with_isolation_level_repeatable_read() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = BeginBuilder::create()
+ ->isolationLevel(IsolationLevel::REPEATABLE_READ);
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame('BEGIN ISOLATION LEVEL REPEATABLE READ', $deparsed);
+ }
+
+ public function test_begin_deparsed_with_isolation_level_serializable() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = BeginBuilder::create()
+ ->isolationLevel(IsolationLevel::SERIALIZABLE);
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame('BEGIN ISOLATION LEVEL SERIALIZABLE', $deparsed);
+ }
+
+ public function test_begin_deparsed_with_multiple_options() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = BeginBuilder::create()
+ ->isolationLevel(IsolationLevel::SERIALIZABLE)
+ ->readOnly()
+ ->deferrable();
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame('BEGIN ISOLATION LEVEL SERIALIZABLE, READ ONLY, DEFERRABLE', $deparsed);
+ }
+
+ public function test_begin_deparsed_with_not_deferrable() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = BeginBuilder::create()
+ ->notDeferrable();
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame('BEGIN NOT DEFERRABLE', $deparsed);
+ }
+
+ public function test_begin_deparsed_with_read_only() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = BeginBuilder::create()
+ ->readOnly();
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame('BEGIN READ ONLY', $deparsed);
+ }
+
+ public function test_begin_deparsed_with_read_write() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = BeginBuilder::create()
+ ->readWrite();
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame('BEGIN READ WRITE', $deparsed);
+ }
+
+ public function test_immutability() : void
+ {
+ $original = BeginBuilder::create();
+ $modified = $original->isolationLevel(IsolationLevel::SERIALIZABLE);
+
+ self::assertNotSame($original, $modified);
+ }
+
+ private function deparse(TransactionStmt $stmt) : string
+ {
+ $parser = new Parser();
+ $node = new Node();
+ $node->setTransactionStmt($stmt);
+ $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/Unit/QueryBuilder/Transaction/CommitBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Transaction/CommitBuilderTest.php
new file mode 100644
index 000000000..ebde269c1
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Transaction/CommitBuilderTest.php
@@ -0,0 +1,87 @@
+toAst();
+
+ self::assertInstanceOf(TransactionStmt::class, $ast);
+ self::assertSame(TransactionStmtKind::TRANS_STMT_COMMIT, $ast->getKind());
+ self::assertFalse($ast->getChain());
+ }
+
+ public function test_commit_deparsed_basic() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = CommitBuilder::create();
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame('COMMIT', $deparsed);
+ }
+
+ public function test_commit_deparsed_with_and_chain() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = CommitBuilder::create()
+ ->andChain();
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame('COMMIT AND CHAIN', $deparsed);
+ }
+
+ public function test_commit_with_and_no_chain_has_chain_false() : void
+ {
+ $query = CommitBuilder::create()
+ ->andNoChain();
+
+ $ast = $query->toAst();
+
+ self::assertFalse($ast->getChain());
+ }
+
+ public function test_immutability() : void
+ {
+ $original = CommitBuilder::create();
+ $modified = $original->andChain();
+
+ self::assertNotSame($original, $modified);
+ }
+
+ private function deparse(TransactionStmt $stmt) : string
+ {
+ $parser = new Parser();
+ $node = new Node();
+ $node->setTransactionStmt($stmt);
+ $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/Unit/QueryBuilder/Transaction/PreparedTransactionBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Transaction/PreparedTransactionBuilderTest.php
new file mode 100644
index 000000000..ef15439bc
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Transaction/PreparedTransactionBuilderTest.php
@@ -0,0 +1,102 @@
+toAst();
+
+ self::assertInstanceOf(TransactionStmt::class, $ast);
+ self::assertSame(TransactionStmtKind::TRANS_STMT_COMMIT_PREPARED, $ast->getKind());
+ self::assertSame('my_transaction', $ast->getGid());
+ }
+
+ public function test_commit_prepared_deparsed() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = PreparedTransactionBuilder::commitPrepared('my_transaction');
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame("COMMIT PREPARED 'my_transaction'", $deparsed);
+ }
+
+ public function test_prepare_transaction_ast_has_correct_kind() : void
+ {
+ $query = PreparedTransactionBuilder::prepare('my_transaction');
+
+ $ast = $query->toAst();
+
+ self::assertInstanceOf(TransactionStmt::class, $ast);
+ self::assertSame(TransactionStmtKind::TRANS_STMT_PREPARE, $ast->getKind());
+ self::assertSame('my_transaction', $ast->getGid());
+ }
+
+ public function test_prepare_transaction_deparsed() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = PreparedTransactionBuilder::prepare('my_transaction');
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame("PREPARE TRANSACTION 'my_transaction'", $deparsed);
+ }
+
+ public function test_rollback_prepared_ast_has_correct_kind() : void
+ {
+ $query = PreparedTransactionBuilder::rollbackPrepared('my_transaction');
+
+ $ast = $query->toAst();
+
+ self::assertInstanceOf(TransactionStmt::class, $ast);
+ self::assertSame(TransactionStmtKind::TRANS_STMT_ROLLBACK_PREPARED, $ast->getKind());
+ self::assertSame('my_transaction', $ast->getGid());
+ }
+
+ public function test_rollback_prepared_deparsed() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = PreparedTransactionBuilder::rollbackPrepared('my_transaction');
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame("ROLLBACK PREPARED 'my_transaction'", $deparsed);
+ }
+
+ private function deparse(TransactionStmt $stmt) : string
+ {
+ $parser = new Parser();
+ $node = new Node();
+ $node->setTransactionStmt($stmt);
+ $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/Unit/QueryBuilder/Transaction/RollbackBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Transaction/RollbackBuilderTest.php
new file mode 100644
index 000000000..9b8d94b45
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Transaction/RollbackBuilderTest.php
@@ -0,0 +1,100 @@
+toSavepoint('test');
+
+ self::assertNotSame($original, $modified);
+ }
+
+ public function test_rollback_ast_has_correct_kind() : void
+ {
+ $query = RollbackBuilder::create();
+
+ $ast = $query->toAst();
+
+ self::assertInstanceOf(TransactionStmt::class, $ast);
+ self::assertSame(TransactionStmtKind::TRANS_STMT_ROLLBACK, $ast->getKind());
+ }
+
+ public function test_rollback_deparsed_basic() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = RollbackBuilder::create();
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame('ROLLBACK', $deparsed);
+ }
+
+ public function test_rollback_deparsed_to_savepoint() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = RollbackBuilder::create()
+ ->toSavepoint('my_savepoint');
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame('ROLLBACK TO SAVEPOINT my_savepoint', $deparsed);
+ }
+
+ public function test_rollback_deparsed_with_and_chain() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = RollbackBuilder::create()
+ ->andChain();
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame('ROLLBACK AND CHAIN', $deparsed);
+ }
+
+ public function test_rollback_to_savepoint_has_correct_kind() : void
+ {
+ $query = RollbackBuilder::create()
+ ->toSavepoint('my_savepoint');
+
+ $ast = $query->toAst();
+
+ self::assertSame(TransactionStmtKind::TRANS_STMT_ROLLBACK_TO, $ast->getKind());
+ self::assertSame('my_savepoint', $ast->getSavepointName());
+ }
+
+ private function deparse(TransactionStmt $stmt) : string
+ {
+ $parser = new Parser();
+ $node = new Node();
+ $node->setTransactionStmt($stmt);
+ $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/Unit/QueryBuilder/Transaction/SavepointBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Transaction/SavepointBuilderTest.php
new file mode 100644
index 000000000..fb044a30d
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Transaction/SavepointBuilderTest.php
@@ -0,0 +1,79 @@
+toAst();
+
+ self::assertInstanceOf(TransactionStmt::class, $ast);
+ self::assertSame(TransactionStmtKind::TRANS_STMT_RELEASE, $ast->getKind());
+ self::assertSame('my_savepoint', $ast->getSavepointName());
+ }
+
+ public function test_release_savepoint_deparsed() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = SavepointBuilder::release('my_savepoint');
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame('RELEASE my_savepoint', $deparsed);
+ }
+
+ public function test_savepoint_ast_has_correct_kind() : void
+ {
+ $query = SavepointBuilder::create('my_savepoint');
+
+ $ast = $query->toAst();
+
+ self::assertInstanceOf(TransactionStmt::class, $ast);
+ self::assertSame(TransactionStmtKind::TRANS_STMT_SAVEPOINT, $ast->getKind());
+ self::assertSame('my_savepoint', $ast->getSavepointName());
+ }
+
+ public function test_savepoint_deparsed() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = SavepointBuilder::create('my_savepoint');
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame('SAVEPOINT my_savepoint', $deparsed);
+ }
+
+ private function deparse(TransactionStmt $stmt) : string
+ {
+ $parser = new Parser();
+ $node = new Node();
+ $node->setTransactionStmt($stmt);
+ $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/Unit/QueryBuilder/Transaction/SetTransactionBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Transaction/SetTransactionBuilderTest.php
new file mode 100644
index 000000000..f6804cc96
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Transaction/SetTransactionBuilderTest.php
@@ -0,0 +1,133 @@
+isolationLevel(IsolationLevel::SERIALIZABLE);
+
+ self::assertNotSame($original, $modified);
+ }
+
+ public function test_set_session_transaction_deparsed() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = SetTransactionBuilder::session()
+ ->isolationLevel(IsolationLevel::SERIALIZABLE);
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame('SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE', $deparsed);
+ }
+
+ public function test_set_transaction_ast_has_correct_kind() : void
+ {
+ $query = SetTransactionBuilder::create()
+ ->isolationLevel(IsolationLevel::SERIALIZABLE);
+
+ $ast = $query->toAst();
+
+ self::assertInstanceOf(VariableSetStmt::class, $ast);
+ self::assertSame(VariableSetKind::VAR_SET_MULTI, $ast->getKind());
+ self::assertSame('TRANSACTION', $ast->getName());
+ }
+
+ public function test_set_transaction_deparsed_with_isolation_level() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = SetTransactionBuilder::create()
+ ->isolationLevel(IsolationLevel::READ_COMMITTED);
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame('SET TRANSACTION ISOLATION LEVEL READ COMMITTED', $deparsed);
+ }
+
+ public function test_set_transaction_deparsed_with_multiple_options() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = SetTransactionBuilder::create()
+ ->isolationLevel(IsolationLevel::SERIALIZABLE)
+ ->readOnly()
+ ->deferrable();
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame('SET TRANSACTION ISOLATION LEVEL SERIALIZABLE, READ ONLY, DEFERRABLE', $deparsed);
+ }
+
+ public function test_set_transaction_deparsed_with_read_only() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = SetTransactionBuilder::create()
+ ->readOnly();
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame('SET TRANSACTION READ ONLY', $deparsed);
+ }
+
+ public function test_set_transaction_deparsed_with_read_write() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = SetTransactionBuilder::create()
+ ->readWrite();
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame('SET TRANSACTION READ WRITE', $deparsed);
+ }
+
+ public function test_set_transaction_snapshot_deparsed() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $query = SetTransactionBuilder::create()
+ ->snapshot('00000003-0000001A-1');
+
+ $deparsed = $this->deparse($query->toAst());
+ self::assertSame("SET TRANSACTION SNAPSHOT '00000003-0000001A-1'", $deparsed);
+ }
+
+ private function deparse(VariableSetStmt $stmt) : string
+ {
+ $parser = new Parser();
+ $node = new Node();
+ $node->setVariableSetStmt($stmt);
+ $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/Unit/QueryBuilder/Update/UpdateBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Update/UpdateBuilderTest.php
new file mode 100644
index 000000000..185b86335
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Update/UpdateBuilderTest.php
@@ -0,0 +1,695 @@
+update('users')
+ ->set('first_name', Literal::string('John'))
+ ->set('last_name', Literal::string('Doe'))
+ ->set('email', Literal::string('john.doe@example.com'))
+ ->setAll([]);
+
+ $ast = $query->toAst();
+ $targetList = $ast->getTargetList();
+ self::assertNotNull($targetList);
+ self::assertCount(3, $targetList);
+ }
+
+ public function test_complex_update_with_all_clauses() : void
+ {
+ $query = UpdateBuilder::create()
+ ->update('orders', 'o')
+ ->set('status', Literal::string('shipped'))
+ ->set('shipped_at', new FunctionCall(['now']))
+ ->setAll([])
+ ->from((new Table('shipments'))->as('s'))
+ ->where(new Comparison(Column::name('o.id'), ComparisonOperator::EQ, Column::name('s.order_id')))
+ ->returning(Column::name('o.id'), Column::name('o.status'));
+
+ $ast = $query->toAst();
+
+ self::assertNotNull($ast->getRelation());
+ self::assertNotNull($ast->getTargetList());
+ self::assertNotNull($ast->getFromClause());
+ self::assertTrue($ast->hasWhereClause());
+ self::assertNotNull($ast->getReturningList());
+ }
+
+ public function test_from_ast_throws_on_empty_target_list() : void
+ {
+ $this->expectException(InvalidAstException::class);
+
+ $updateStmt = new UpdateStmt();
+ $rangeVar = new \Flow\PostgreSql\Protobuf\AST\RangeVar(['relname' => 'users']);
+ $updateStmt->setRelation($rangeVar);
+
+ $node = new Node();
+ $node->setUpdateStmt($updateStmt);
+
+ UpdateBuilder::fromAst($node);
+ }
+
+ public function test_from_ast_throws_on_missing_relation() : void
+ {
+ $this->expectException(InvalidAstException::class);
+
+ $updateStmt = new UpdateStmt();
+
+ $node = new Node();
+ $node->setUpdateStmt($updateStmt);
+
+ UpdateBuilder::fromAst($node);
+ }
+
+ public function test_from_ast_throws_on_non_update_stmt() : void
+ {
+ $this->expectException(InvalidAstException::class);
+
+ $node = new Node();
+ UpdateBuilder::fromAst($node);
+ }
+
+ public function test_immutability_from() : void
+ {
+ $builder1 = UpdateBuilder::create()->update('users')->set('name', Literal::string('John'))->setAll([]);
+ $builder2 = $builder1->from(new Table('other_table'));
+
+ self::assertNotSame($builder1, $builder2);
+ }
+
+ public function test_immutability_returning() : void
+ {
+ $builder1 = UpdateBuilder::create()->update('users')->set('name', Literal::string('John'))->setAll([]);
+ $builder2 = $builder1->returning(Column::name('id'));
+
+ self::assertNotSame($builder1, $builder2);
+ }
+
+ public function test_immutability_returning_all() : void
+ {
+ $builder1 = UpdateBuilder::create()->update('users')->set('name', Literal::string('John'))->setAll([]);
+ $builder2 = $builder1->returningAll();
+
+ self::assertNotSame($builder1, $builder2);
+ }
+
+ public function test_immutability_set() : void
+ {
+ $builder1 = UpdateBuilder::create()->update('users');
+ $builder2 = $builder1->set('name', Literal::string('John'));
+
+ self::assertNotSame($builder1, $builder2);
+ }
+
+ public function test_immutability_set_all() : void
+ {
+ $builder1 = UpdateBuilder::create()->update('users')->set('name', Literal::string('John'));
+ $builder2 = $builder1->setAll(['email' => Literal::string('john@example.com')]);
+
+ self::assertNotSame($builder1, $builder2);
+ }
+
+ public function test_immutability_update() : void
+ {
+ $builder1 = UpdateBuilder::create();
+ $builder2 = $builder1->update('users');
+
+ self::assertNotSame($builder1, $builder2);
+ }
+
+ public function test_immutability_where() : void
+ {
+ $builder1 = UpdateBuilder::create()->update('users')->set('name', Literal::string('John'))->setAll([]);
+ $builder2 = $builder1->where(new Comparison(Column::name('id'), ComparisonOperator::EQ, Literal::int(1)));
+
+ self::assertNotSame($builder1, $builder2);
+ }
+
+ public function test_round_trip_complex() : void
+ {
+ $original = UpdateBuilder::create()
+ ->update('orders', 'o')
+ ->set('status', Literal::string('completed'))
+ ->set('completed_at', new FunctionCall(['now']))
+ ->setAll([])
+ ->from((new Table('order_items'))->as('oi'))
+ ->where(new Comparison(Column::name('o.id'), ComparisonOperator::EQ, Column::name('oi.order_id')))
+ ->returning(Column::name('o.id'));
+
+ $ast = $original->toAst();
+
+ $node = new Node();
+ $node->setUpdateStmt($ast);
+
+ $restored = UpdateBuilder::fromAst($node);
+ $restoredAst = $restored->toAst();
+
+ self::assertNotNull($restoredAst->getRelation());
+ self::assertNotNull($restoredAst->getTargetList());
+ self::assertNotNull($restoredAst->getFromClause());
+ self::assertTrue($restoredAst->hasWhereClause());
+ self::assertNotNull($restoredAst->getReturningList());
+ }
+
+ public function test_round_trip_simple() : void
+ {
+ $original = UpdateBuilder::create()
+ ->update('users')
+ ->set('name', Literal::string('John'))
+ ->setAll([]);
+
+ $ast = $original->toAst();
+
+ $node = new Node();
+ $node->setUpdateStmt($ast);
+
+ $restored = UpdateBuilder::fromAst($node);
+ $restoredAst = $restored->toAst();
+
+ $originalRelation = $ast->getRelation();
+ self::assertNotNull($originalRelation);
+
+ $restoredRelation = $restoredAst->getRelation();
+ self::assertNotNull($restoredRelation);
+
+ self::assertSame($originalRelation->getRelname(), $restoredRelation->getRelname());
+
+ $originalTargetList = $ast->getTargetList();
+ $restoredTargetList = $restoredAst->getTargetList();
+ self::assertCount(\count($originalTargetList), $restoredTargetList);
+ }
+
+ public function test_round_trip_with_from() : void
+ {
+ $original = UpdateBuilder::create()
+ ->update('orders', 'o')
+ ->set('status', Column::name('s.status'))
+ ->setAll([])
+ ->from((new Table('order_status'))->as('s'));
+
+ $ast = $original->toAst();
+
+ $node = new Node();
+ $node->setUpdateStmt($ast);
+
+ $restored = UpdateBuilder::fromAst($node);
+ $restoredAst = $restored->toAst();
+
+ $fromClause = $restoredAst->getFromClause();
+ self::assertNotNull($fromClause);
+ self::assertCount(1, $fromClause);
+ }
+
+ public function test_round_trip_with_returning() : void
+ {
+ $original = UpdateBuilder::create()
+ ->update('users')
+ ->set('name', Literal::string('John'))
+ ->setAll([])
+ ->returning(Column::name('id'), Column::name('name'));
+
+ $ast = $original->toAst();
+
+ $node = new Node();
+ $node->setUpdateStmt($ast);
+
+ $restored = UpdateBuilder::fromAst($node);
+ $restoredAst = $restored->toAst();
+
+ $returningList = $restoredAst->getReturningList();
+ self::assertNotNull($returningList);
+ self::assertCount(2, $returningList);
+ }
+
+ public function test_round_trip_with_where() : void
+ {
+ $original = UpdateBuilder::create()
+ ->update('users')
+ ->set('name', Literal::string('John'))
+ ->setAll(['email' => Literal::string('john@example.com')])
+ ->where(new Comparison(Column::name('id'), ComparisonOperator::EQ, Literal::int(1)));
+
+ $ast = $original->toAst();
+
+ $node = new Node();
+ $node->setUpdateStmt($ast);
+
+ $restored = UpdateBuilder::fromAst($node);
+ $restoredAst = $restored->toAst();
+
+ self::assertTrue($restoredAst->hasWhereClause());
+ }
+
+ public function test_simple_update() : void
+ {
+ $query = UpdateBuilder::create()
+ ->update('users')
+ ->set('name', Literal::string('John'))
+ ->setAll(['email' => Literal::string('john@example.com')]);
+
+ $ast = $query->toAst();
+ self::assertInstanceOf(UpdateStmt::class, $ast);
+
+ $relation = $ast->getRelation();
+ self::assertNotNull($relation);
+ self::assertSame('users', $relation->getRelname());
+ self::assertFalse($relation->hasAlias());
+
+ $targetList = $ast->getTargetList();
+ self::assertNotNull($targetList);
+ self::assertCount(2, $targetList);
+
+ $nameTarget = $targetList->offsetGet(0)->getResTarget();
+ self::assertNotNull($nameTarget);
+ self::assertSame('name', $nameTarget->getName());
+
+ $emailTarget = $targetList->offsetGet(1)->getResTarget();
+ self::assertNotNull($emailTarget);
+ self::assertSame('email', $emailTarget->getName());
+ }
+
+ public function test_simple_update_deparsed_output() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $update = UpdateBuilder::create()
+ ->update('users')
+ ->set('name', Literal::string('John'))
+ ->setAll([]);
+
+ $deparsed = $this->deparse($update->toAst());
+ self::assertSame("UPDATE users SET name = 'John'", $deparsed);
+ }
+
+ public function test_throws_on_empty_assignments() : void
+ {
+ $this->expectException(InvalidExpressionException::class);
+ $this->expectExceptionMessage('assignments cannot be empty');
+
+ UpdateBuilder::create()
+ ->update('users')
+ ->toAst();
+ }
+
+ public function test_throws_on_missing_table() : void
+ {
+ $this->expectException(InvalidExpressionException::class);
+
+ UpdateBuilder::create()
+ ->update('')
+ ->set('name', Literal::string('John'))
+ ->setAll([])
+ ->toAst();
+ }
+
+ public function test_update_combining_set_and_set_all() : void
+ {
+ $query = UpdateBuilder::create()
+ ->update('users')
+ ->set('first_name', Literal::string('John'))
+ ->set('last_name', Literal::string('Doe'))
+ ->setAll([
+ 'email' => Literal::string('john.doe@example.com'),
+ 'updated_at' => new FunctionCall(['now']),
+ ]);
+
+ $ast = $query->toAst();
+ $targetList = $ast->getTargetList();
+ self::assertNotNull($targetList);
+ self::assertCount(4, $targetList);
+ }
+
+ public function test_update_multiple_columns() : void
+ {
+ $query = UpdateBuilder::create()
+ ->update('products')
+ ->setAll([
+ 'price' => Literal::float(99.99),
+ 'updated_at' => new FunctionCall(['now']),
+ 'version' => new BinaryExpression(Column::name('version'), '+', Literal::int(1)),
+ ]);
+
+ $ast = $query->toAst();
+ $targetList = $ast->getTargetList();
+ self::assertNotNull($targetList);
+ self::assertCount(3, $targetList);
+
+ $priceTarget = $targetList->offsetGet(0)->getResTarget();
+ self::assertNotNull($priceTarget);
+ self::assertSame('price', $priceTarget->getName());
+
+ $updatedAtTarget = $targetList->offsetGet(1)->getResTarget();
+ self::assertNotNull($updatedAtTarget);
+ self::assertSame('updated_at', $updatedAtTarget->getName());
+
+ $versionTarget = $targetList->offsetGet(2)->getResTarget();
+ self::assertNotNull($versionTarget);
+ self::assertSame('version', $versionTarget->getName());
+ }
+
+ public function test_update_multiple_columns_deparsed_output() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $update = UpdateBuilder::create()
+ ->update('products')
+ ->set('price', Literal::float(99.99))
+ ->set('stock', Literal::int(100))
+ ->setAll([]);
+
+ $deparsed = $this->deparse($update->toAst());
+ self::assertSame('UPDATE products SET price = 99.99, stock = 100', $deparsed);
+ }
+
+ public function test_update_only_with_set_all() : void
+ {
+ $query = UpdateBuilder::create()
+ ->update('users')
+ ->setAll([
+ 'first_name' => Literal::string('John'),
+ 'last_name' => Literal::string('Doe'),
+ ]);
+
+ $ast = $query->toAst();
+ $targetList = $ast->getTargetList();
+ self::assertNotNull($targetList);
+ self::assertCount(2, $targetList);
+ }
+
+ public function test_update_with_alias() : void
+ {
+ $query = UpdateBuilder::create()
+ ->update('users', 'u')
+ ->set('name', Literal::string('Jane'))
+ ->setAll([]);
+
+ $ast = $query->toAst();
+ $relation = $ast->getRelation();
+ self::assertNotNull($relation);
+ self::assertSame('users', $relation->getRelname());
+ self::assertTrue($relation->hasAlias());
+
+ $alias = $relation->getAlias();
+ self::assertNotNull($alias);
+ self::assertSame('u', $alias->getAliasname());
+ }
+
+ public function test_update_with_binary_expression() : void
+ {
+ $query = UpdateBuilder::create()
+ ->update('counters')
+ ->set('count', new BinaryExpression(Column::name('count'), '+', Literal::int(1)))
+ ->setAll([]);
+
+ $ast = $query->toAst();
+ $targetList = $ast->getTargetList();
+ self::assertNotNull($targetList);
+
+ $target = $targetList->offsetGet(0)->getResTarget();
+ self::assertNotNull($target);
+ self::assertSame('count', $target->getName());
+
+ $val = $target->getVal();
+ self::assertNotNull($val);
+ self::assertTrue($val->hasAExpr());
+ }
+
+ public function test_update_with_binary_expression_deparsed_output() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $update = UpdateBuilder::create()
+ ->update('counters')
+ ->set('count', new BinaryExpression(Column::name('count'), '+', Literal::int(1)))
+ ->setAll([]);
+
+ $deparsed = $this->deparse($update->toAst());
+ self::assertSame('UPDATE counters SET count = count + 1', $deparsed);
+ }
+
+ public function test_update_with_column_reference() : void
+ {
+ $query = UpdateBuilder::create()
+ ->update('employees')
+ ->set('manager_id', Column::name('senior_manager_id'))
+ ->setAll([]);
+
+ $ast = $query->toAst();
+ $targetList = $ast->getTargetList();
+ self::assertNotNull($targetList);
+
+ $target = $targetList->offsetGet(0)->getResTarget();
+ self::assertNotNull($target);
+ self::assertSame('manager_id', $target->getName());
+
+ $val = $target->getVal();
+ self::assertNotNull($val);
+ self::assertTrue($val->hasColumnRef());
+ }
+
+ public function test_update_with_from() : void
+ {
+ $query = UpdateBuilder::create()
+ ->update('orders', 'o')
+ ->set('status', Column::name('s.status'))
+ ->setAll([])
+ ->from((new Table('order_status'))->as('s'))
+ ->where(new Comparison(Column::name('o.status_id'), ComparisonOperator::EQ, Column::name('s.id')));
+
+ $ast = $query->toAst();
+ $fromClause = $ast->getFromClause();
+ self::assertNotNull($fromClause);
+ self::assertCount(1, $fromClause);
+
+ $fromNode = $fromClause->offsetGet(0);
+ self::assertTrue($fromNode->hasRangeVar());
+
+ $rangeVar = $fromNode->getRangeVar();
+ self::assertNotNull($rangeVar);
+ self::assertSame('order_status', $rangeVar->getRelname());
+
+ $alias = $rangeVar->getAlias();
+ self::assertNotNull($alias);
+ self::assertSame('s', $alias->getAliasname());
+ }
+
+ public function test_update_with_from_deparsed_output() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $update = UpdateBuilder::create()
+ ->update('orders', 'o')
+ ->set('status', Column::tableColumn('s', 'status'))
+ ->setAll([])
+ ->from((new Table('order_status'))->as('s'))
+ ->where(new Comparison(Column::tableColumn('o', 'status_id'), ComparisonOperator::EQ, Column::tableColumn('s', 'id')));
+
+ $deparsed = $this->deparse($update->toAst());
+ self::assertSame('UPDATE orders o SET status = s.status FROM order_status s WHERE o.status_id = s.id', $deparsed);
+ }
+
+ public function test_update_with_function_call() : void
+ {
+ $query = UpdateBuilder::create()
+ ->update('logs')
+ ->set('logged_at', new FunctionCall(['now']))
+ ->setAll([]);
+
+ $ast = $query->toAst();
+ $targetList = $ast->getTargetList();
+ self::assertNotNull($targetList);
+
+ $target = $targetList->offsetGet(0)->getResTarget();
+ self::assertNotNull($target);
+ self::assertSame('logged_at', $target->getName());
+
+ $val = $target->getVal();
+ self::assertNotNull($val);
+ self::assertTrue($val->hasFuncCall());
+ }
+
+ public function test_update_with_multiple_from_tables() : void
+ {
+ $query = UpdateBuilder::create()
+ ->update('products', 'p')
+ ->set('price', Column::name('pp.price'))
+ ->setAll([])
+ ->from(
+ (new Table('product_prices'))->as('pp'),
+ (new Table('categories'))->as('c')
+ );
+
+ $ast = $query->toAst();
+ $fromClause = $ast->getFromClause();
+ self::assertNotNull($fromClause);
+ self::assertCount(2, $fromClause);
+ }
+
+ public function test_update_with_returning() : void
+ {
+ $query = UpdateBuilder::create()
+ ->update('users')
+ ->set('updated_at', new FunctionCall(['now']))
+ ->setAll([])
+ ->where(new Comparison(Column::name('id'), ComparisonOperator::EQ, Literal::int(1)))
+ ->returning(Column::name('id'), Column::name('updated_at'));
+
+ $ast = $query->toAst();
+ $returningList = $ast->getReturningList();
+ self::assertNotNull($returningList);
+ self::assertCount(2, $returningList);
+ }
+
+ public function test_update_with_returning_all() : void
+ {
+ $query = UpdateBuilder::create()
+ ->update('users')
+ ->set('name', Literal::string('John'))
+ ->setAll([])
+ ->returningAll();
+
+ $ast = $query->toAst();
+ $returningList = $ast->getReturningList();
+ self::assertNotNull($returningList);
+ self::assertCount(1, $returningList);
+
+ $returningNode = $returningList->offsetGet(0);
+ $resTarget = $returningNode->getResTarget();
+ self::assertNotNull($resTarget);
+ $val = $resTarget->getVal();
+ self::assertNotNull($val);
+
+ // Star.toAst() produces a ColumnRef with A_Star inside
+ self::assertTrue($val->hasColumnRef());
+ $columnRef = $val->getColumnRef();
+ self::assertNotNull($columnRef);
+ $fields = $columnRef->getFields();
+ self::assertNotNull($fields);
+ self::assertCount(1, $fields);
+ self::assertTrue($fields[0]->hasAStar());
+ }
+
+ public function test_update_with_returning_deparsed_output() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $update = UpdateBuilder::create()
+ ->update('users')
+ ->set('last_login', new FunctionCall(['now']))
+ ->setAll([])
+ ->where(new Comparison(Column::name('id'), ComparisonOperator::EQ, Literal::int(1)))
+ ->returning(Column::name('id'), Column::name('last_login'));
+
+ $deparsed = $this->deparse($update->toAst());
+ self::assertSame('UPDATE users SET last_login = now() WHERE id = 1 RETURNING id, last_login', $deparsed);
+ }
+
+ public function test_update_with_where() : void
+ {
+ $query = UpdateBuilder::create()
+ ->update('users')
+ ->set('active', Literal::bool(false))
+ ->setAll([])
+ ->where(new Comparison(Column::name('last_login'), ComparisonOperator::LT, Literal::string('2024-01-01')));
+
+ $ast = $query->toAst();
+ self::assertTrue($ast->hasWhereClause());
+
+ $whereClause = $ast->getWhereClause();
+ self::assertNotNull($whereClause);
+ self::assertTrue($whereClause->hasAExpr());
+ }
+
+ public function test_update_with_where_deparsed_output() : void
+ {
+ if (!\function_exists('pg_query_deparse')) {
+ self::markTestSkipped('pg_query_deparse function not available. Rebuild the pg_query extension.');
+ }
+
+ $update = UpdateBuilder::create()
+ ->update('users')
+ ->set('status', Literal::string('active'))
+ ->setAll([])
+ ->where(new Comparison(Column::name('id'), ComparisonOperator::EQ, Literal::int(1)));
+
+ $deparsed = $this->deparse($update->toAst());
+ self::assertSame("UPDATE users SET status = 'active' WHERE id = 1", $deparsed);
+ }
+
+ public function test_update_with_with_clause() : void
+ {
+ $selectStmt = SelectBuilder::create()
+ ->select(Column::name('id'))
+ ->from(new Table('users'))
+ ->where(new Comparison(Column::name('active'), ComparisonOperator::EQ, Literal::bool(true)))
+ ->toAst();
+
+ $selectNode = new Node();
+ $selectNode->setSelectStmt($selectStmt);
+
+ $cte = new CTE('updated_users', $selectNode);
+
+ $query = UpdateBuilder::with(new WithClause([$cte]))
+ ->update('orders')
+ ->set('processed', Literal::bool(true))
+ ->setAll([]);
+
+ $ast = $query->toAst();
+ self::assertTrue($ast->hasWithClause());
+
+ $withClause = $ast->getWithClause();
+ self::assertNotNull($withClause);
+
+ $ctes = $withClause->getCtes();
+ self::assertNotNull($ctes);
+ self::assertCount(1, $ctes);
+ }
+
+ private function deparse(UpdateStmt $updateStmt) : string
+ {
+ $parser = new Parser();
+ $node = new Node();
+ $node->setUpdateStmt($updateStmt);
+ $rawStmt = new RawStmt();
+ $rawStmt->setStmt($node);
+ $parsed = $parser->parse('UPDATE dummy SET x = 1');
+ $parseResult = $parsed->raw();
+ $parseResult->setStmts([$rawStmt]);
+
+ return (new ParsedQuery($parseResult))->deparse();
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Utility/AnalyzeBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Utility/AnalyzeBuilderTest.php
new file mode 100644
index 000000000..44c86cf67
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Utility/AnalyzeBuilderTest.php
@@ -0,0 +1,129 @@
+tables('users', 'orders');
+
+ $ast = $builder->toAst();
+
+ self::assertCount(2, $ast->getRels());
+ $rel0 = $ast->getRels()[0]->getVacuumRelation();
+ $rel1 = $ast->getRels()[1]->getVacuumRelation();
+ self::assertNotNull($rel0);
+ self::assertNotNull($rel1);
+ self::assertSame('users', $rel0->getRelation()?->getRelname());
+ self::assertSame('orders', $rel1->getRelation()?->getRelname());
+ }
+
+ public function test_analyze_skip_locked_option() : void
+ {
+ $builder = AnalyzeBuilder::create()->skipLocked();
+
+ $ast = $builder->toAst();
+
+ $options = $ast->getOptions();
+ self::assertNotEmpty($options);
+ $optionNames = [];
+
+ foreach ($options as $opt) {
+ $optionNames[] = $opt->getDefElem()?->getDefname();
+ }
+ self::assertContains('skip_locked', $optionNames);
+ }
+
+ public function test_analyze_table_with_schema() : void
+ {
+ $builder = AnalyzeBuilder::create()->table('public.users');
+
+ $ast = $builder->toAst();
+
+ self::assertCount(1, $ast->getRels());
+ $rel = $ast->getRels()[0]->getVacuumRelation();
+ self::assertNotNull($rel);
+ $relation = $rel->getRelation();
+ self::assertNotNull($relation);
+ self::assertSame('public', $relation->getSchemaname());
+ self::assertSame('users', $relation->getRelname());
+ }
+
+ public function test_analyze_verbose_option() : void
+ {
+ $builder = AnalyzeBuilder::create()->verbose();
+
+ $ast = $builder->toAst();
+
+ $options = $ast->getOptions();
+ self::assertNotEmpty($options);
+ $optionNames = [];
+
+ foreach ($options as $opt) {
+ $optionNames[] = $opt->getDefElem()?->getDefname();
+ }
+ self::assertContains('verbose', $optionNames);
+ }
+
+ public function test_analyze_with_table() : void
+ {
+ $builder = AnalyzeBuilder::create()->table('users');
+
+ $ast = $builder->toAst();
+
+ self::assertCount(1, $ast->getRels());
+ $rel = $ast->getRels()[0]->getVacuumRelation();
+ self::assertNotNull($rel);
+ self::assertSame('users', $rel->getRelation()?->getRelname());
+ }
+
+ public function test_analyze_with_table_and_columns() : void
+ {
+ $builder = AnalyzeBuilder::create()->table('users', 'email', 'name');
+
+ $ast = $builder->toAst();
+
+ self::assertCount(1, $ast->getRels());
+ $rel = $ast->getRels()[0]->getVacuumRelation();
+ self::assertNotNull($rel);
+ self::assertSame('users', $rel->getRelation()?->getRelname());
+ self::assertCount(2, $rel->getVaCols());
+ }
+
+ public function test_basic_analyze() : void
+ {
+ $builder = AnalyzeBuilder::create();
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(VacuumStmt::class, $ast);
+ self::assertFalse($ast->getIsVacuumcmd());
+ self::assertCount(0, $ast->getRels());
+ }
+
+ public function test_immutability() : void
+ {
+ $original = AnalyzeBuilder::create();
+ $modified = $original->verbose();
+
+ $originalAst = $original->toAst();
+ $modifiedAst = $modified->toAst();
+
+ self::assertCount(0, $originalAst->getOptions());
+ self::assertCount(1, $modifiedAst->getOptions());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Utility/ClusterBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Utility/ClusterBuilderTest.php
new file mode 100644
index 000000000..edd4e01da
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Utility/ClusterBuilderTest.php
@@ -0,0 +1,81 @@
+toAst();
+
+ self::assertInstanceOf(ClusterStmt::class, $ast);
+ self::assertNull($ast->getRelation());
+ }
+
+ public function test_cluster_table() : void
+ {
+ $builder = ClusterBuilder::create()->table('users');
+
+ $ast = $builder->toAst();
+
+ self::assertNotNull($ast->getRelation());
+ self::assertSame('users', $ast->getRelation()->getRelname());
+ }
+
+ public function test_cluster_table_using_index() : void
+ {
+ $builder = ClusterBuilder::create()->table('users')->using('idx_users_pkey');
+
+ $ast = $builder->toAst();
+
+ self::assertSame('users', $ast->getRelation()?->getRelname());
+ self::assertSame('idx_users_pkey', $ast->getIndexname());
+ }
+
+ public function test_cluster_table_with_schema() : void
+ {
+ $builder = ClusterBuilder::create()->table('public.users');
+
+ $ast = $builder->toAst();
+
+ self::assertSame('public', $ast->getRelation()?->getSchemaname());
+ self::assertSame('users', $ast->getRelation()?->getRelname());
+ }
+
+ public function test_cluster_verbose() : void
+ {
+ $builder = ClusterBuilder::create()->verbose()->table('users');
+
+ $ast = $builder->toAst();
+
+ self::assertCount(1, $ast->getParams());
+ self::assertSame('verbose', $ast->getParams()[0]->getDefElem()?->getDefname());
+ }
+
+ public function test_immutability() : void
+ {
+ $original = ClusterBuilder::create();
+ $modified = $original->table('users');
+
+ $originalAst = $original->toAst();
+ $modifiedAst = $modified->toAst();
+
+ self::assertNull($originalAst->getRelation());
+ self::assertNotNull($modifiedAst->getRelation());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Utility/CommentBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Utility/CommentBuilderTest.php
new file mode 100644
index 000000000..539477edb
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Utility/CommentBuilderTest.php
@@ -0,0 +1,143 @@
+is('Email column');
+
+ $ast = $builder->toAst();
+
+ self::assertSame(ObjectType::OBJECT_COLUMN, $ast->getObjtype());
+ self::assertSame('Email column', $ast->getComment());
+ self::assertCount(2, $ast->getObject()?->getList()?->getItems() ?? []);
+ }
+
+ public function test_comment_on_extension() : void
+ {
+ $builder = CommentBuilder::create(CommentTarget::EXTENSION, 'uuid-ossp')->is('Extension comment');
+
+ $ast = $builder->toAst();
+
+ self::assertSame(ObjectType::OBJECT_EXTENSION, $ast->getObjtype());
+ self::assertSame('Extension comment', $ast->getComment());
+ }
+
+ public function test_comment_on_function() : void
+ {
+ $builder = CommentBuilder::create(CommentTarget::FUNCTION, 'get_user')->is('Function comment');
+
+ $ast = $builder->toAst();
+
+ self::assertSame(ObjectType::OBJECT_FUNCTION, $ast->getObjtype());
+ self::assertSame('Function comment', $ast->getComment());
+ }
+
+ public function test_comment_on_index() : void
+ {
+ $builder = CommentBuilder::create(CommentTarget::INDEX, 'idx_users_email')->is('Index comment');
+
+ $ast = $builder->toAst();
+
+ self::assertSame(ObjectType::OBJECT_INDEX, $ast->getObjtype());
+ self::assertSame('Index comment', $ast->getComment());
+ }
+
+ public function test_comment_on_schema() : void
+ {
+ $builder = CommentBuilder::create(CommentTarget::SCHEMA, 'public')->is('Default schema');
+
+ $ast = $builder->toAst();
+
+ self::assertSame(ObjectType::OBJECT_SCHEMA, $ast->getObjtype());
+ self::assertSame('Default schema', $ast->getComment());
+ }
+
+ public function test_comment_on_sequence() : void
+ {
+ $builder = CommentBuilder::create(CommentTarget::SEQUENCE, 'users_id_seq')->is('Sequence comment');
+
+ $ast = $builder->toAst();
+
+ self::assertSame(ObjectType::OBJECT_SEQUENCE, $ast->getObjtype());
+ self::assertSame('Sequence comment', $ast->getComment());
+ }
+
+ public function test_comment_on_table() : void
+ {
+ $builder = CommentBuilder::create(CommentTarget::TABLE, 'users')->is('A comment');
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(CommentStmt::class, $ast);
+ self::assertSame(ObjectType::OBJECT_TABLE, $ast->getObjtype());
+ self::assertSame('A comment', $ast->getComment());
+ }
+
+ public function test_comment_on_table_with_schema() : void
+ {
+ $builder = CommentBuilder::create(CommentTarget::TABLE, 'public.users')->is('Comment');
+
+ $ast = $builder->toAst();
+
+ self::assertSame(ObjectType::OBJECT_TABLE, $ast->getObjtype());
+ self::assertSame('Comment', $ast->getComment());
+ self::assertCount(2, $ast->getObject()?->getList()?->getItems() ?? []);
+ }
+
+ public function test_comment_on_type() : void
+ {
+ $builder = CommentBuilder::create(CommentTarget::TYPE, 'my_type')->is('Type comment');
+
+ $ast = $builder->toAst();
+
+ self::assertSame(ObjectType::OBJECT_TYPE, $ast->getObjtype());
+ self::assertSame('Type comment', $ast->getComment());
+ }
+
+ public function test_comment_on_view() : void
+ {
+ $builder = CommentBuilder::create(CommentTarget::VIEW, 'active_users')->is('View comment');
+
+ $ast = $builder->toAst();
+
+ self::assertSame(ObjectType::OBJECT_VIEW, $ast->getObjtype());
+ self::assertSame('View comment', $ast->getComment());
+ }
+
+ public function test_comment_remove_null() : void
+ {
+ $builder = CommentBuilder::create(CommentTarget::TABLE, 'users')->isNull();
+
+ $ast = $builder->toAst();
+
+ self::assertSame('', $ast->getComment());
+ }
+
+ public function test_immutability() : void
+ {
+ $original = CommentBuilder::create(CommentTarget::TABLE, 'users');
+ $modified = $original->is('Test');
+
+ $originalAst = $original->toAst();
+ $modifiedAst = $modified->toAst();
+
+ self::assertSame('', $originalAst->getComment());
+ self::assertSame('Test', $modifiedAst->getComment());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Utility/DiscardBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Utility/DiscardBuilderTest.php
new file mode 100644
index 000000000..5ad17ced6
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Utility/DiscardBuilderTest.php
@@ -0,0 +1,56 @@
+toAst();
+
+ self::assertInstanceOf(DiscardStmt::class, $ast);
+ self::assertSame(DiscardMode::DISCARD_ALL, $ast->getTarget());
+ }
+
+ public function test_discard_plans() : void
+ {
+ $builder = DiscardBuilder::create(DiscardType::PLANS);
+
+ $ast = $builder->toAst();
+
+ self::assertSame(DiscardMode::DISCARD_PLANS, $ast->getTarget());
+ }
+
+ public function test_discard_sequences() : void
+ {
+ $builder = DiscardBuilder::create(DiscardType::SEQUENCES);
+
+ $ast = $builder->toAst();
+
+ self::assertSame(DiscardMode::DISCARD_SEQUENCES, $ast->getTarget());
+ }
+
+ public function test_discard_temp() : void
+ {
+ $builder = DiscardBuilder::create(DiscardType::TEMP);
+
+ $ast = $builder->toAst();
+
+ self::assertSame(DiscardMode::DISCARD_TEMP, $ast->getTarget());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Utility/EnumsTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Utility/EnumsTest.php
new file mode 100644
index 000000000..929e5e4fb
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Utility/EnumsTest.php
@@ -0,0 +1,65 @@
+value);
+ self::assertSame(ObjectType::OBJECT_COLUMN, CommentTarget::COLUMN->value);
+ self::assertSame(ObjectType::OBJECT_INDEX, CommentTarget::INDEX->value);
+ self::assertSame(ObjectType::OBJECT_SCHEMA, CommentTarget::SCHEMA->value);
+ self::assertSame(ObjectType::OBJECT_SEQUENCE, CommentTarget::SEQUENCE->value);
+ self::assertSame(ObjectType::OBJECT_VIEW, CommentTarget::VIEW->value);
+ self::assertSame(ObjectType::OBJECT_MATVIEW, CommentTarget::MATERIALIZED_VIEW->value);
+ self::assertSame(ObjectType::OBJECT_FUNCTION, CommentTarget::FUNCTION->value);
+ self::assertSame(ObjectType::OBJECT_PROCEDURE, CommentTarget::PROCEDURE->value);
+ self::assertSame(ObjectType::OBJECT_TRIGGER, CommentTarget::TRIGGER->value);
+ self::assertSame(ObjectType::OBJECT_TYPE, CommentTarget::TYPE->value);
+ self::assertSame(ObjectType::OBJECT_EXTENSION, CommentTarget::EXTENSION->value);
+ self::assertSame(ObjectType::OBJECT_ROLE, CommentTarget::ROLE->value);
+ self::assertSame(ObjectType::OBJECT_DATABASE, CommentTarget::DATABASE->value);
+ }
+
+ public function test_discard_type_values() : void
+ {
+ self::assertSame(DiscardMode::DISCARD_ALL, DiscardType::ALL->value);
+ self::assertSame(DiscardMode::DISCARD_PLANS, DiscardType::PLANS->value);
+ self::assertSame(DiscardMode::DISCARD_SEQUENCES, DiscardType::SEQUENCES->value);
+ self::assertSame(DiscardMode::DISCARD_TEMP, DiscardType::TEMP->value);
+ }
+
+ public function test_explain_format_values() : void
+ {
+ self::assertSame('text', ExplainFormat::TEXT->value);
+ self::assertSame('xml', ExplainFormat::XML->value);
+ self::assertSame('json', ExplainFormat::JSON->value);
+ self::assertSame('yaml', ExplainFormat::YAML->value);
+ }
+
+ public function test_index_cleanup_values() : void
+ {
+ self::assertSame('auto', IndexCleanup::AUTO->value);
+ self::assertSame('on', IndexCleanup::ON->value);
+ self::assertSame('off', IndexCleanup::OFF->value);
+ }
+
+ public function test_lock_mode_values() : void
+ {
+ self::assertSame(1, LockMode::ACCESS_SHARE->value);
+ self::assertSame(2, LockMode::ROW_SHARE->value);
+ self::assertSame(3, LockMode::ROW_EXCLUSIVE->value);
+ self::assertSame(4, LockMode::SHARE_UPDATE_EXCLUSIVE->value);
+ self::assertSame(5, LockMode::SHARE->value);
+ self::assertSame(6, LockMode::SHARE_ROW_EXCLUSIVE->value);
+ self::assertSame(7, LockMode::EXCLUSIVE->value);
+ self::assertSame(8, LockMode::ACCESS_EXCLUSIVE->value);
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Utility/ExplainBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Utility/ExplainBuilderTest.php
new file mode 100644
index 000000000..979ca65bf
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Utility/ExplainBuilderTest.php
@@ -0,0 +1,194 @@
+select(star())->from(table('users'));
+ $builder = ExplainBuilder::create($query);
+
+ $ast = $builder->toAst();
+
+ self::assertInstanceOf(ExplainStmt::class, $ast);
+ self::assertNotNull($ast->getQuery());
+ self::assertCount(0, $ast->getOptions());
+ }
+
+ public function test_explain_analyze_option() : void
+ {
+ $query = SelectBuilder::create()->select(star())->from(table('users'));
+ $builder = ExplainBuilder::create($query)->analyze();
+
+ $ast = $builder->toAst();
+
+ $options = $ast->getOptions();
+ self::assertNotEmpty($options);
+ $optionNames = [];
+
+ foreach ($options as $opt) {
+ $optionNames[] = $opt->getDefElem()?->getDefname();
+ }
+ self::assertContains('analyze', $optionNames);
+ }
+
+ public function test_explain_buffers_option() : void
+ {
+ $query = SelectBuilder::create()->select(star())->from(table('users'));
+ $builder = ExplainBuilder::create($query)->buffers(true);
+
+ $ast = $builder->toAst();
+
+ $options = $ast->getOptions();
+ self::assertNotEmpty($options);
+ $buffersFound = false;
+
+ foreach ($options as $opt) {
+ $defElem = $opt->getDefElem();
+
+ if ($defElem?->getDefname() === 'buffers') {
+ $buffersFound = true;
+ /** @phpstan-ignore method.nonObject (protobuf PHPDoc incorrectly returns int instead of Integer class) */
+ self::assertSame(1, $defElem->getArg()?->getInteger()?->getIval());
+ }
+ }
+ self::assertTrue($buffersFound);
+ }
+
+ public function test_explain_costs_option() : void
+ {
+ $query = SelectBuilder::create()->select(star())->from(table('users'));
+ $builder = ExplainBuilder::create($query)->costs(true);
+
+ $ast = $builder->toAst();
+
+ $options = $ast->getOptions();
+ self::assertNotEmpty($options);
+ $costsFound = false;
+
+ foreach ($options as $opt) {
+ $defElem = $opt->getDefElem();
+
+ if ($defElem?->getDefname() === 'costs') {
+ $costsFound = true;
+ /** @phpstan-ignore method.nonObject (protobuf PHPDoc incorrectly returns int instead of Integer class) */
+ self::assertSame(1, $defElem->getArg()?->getInteger()?->getIval());
+ }
+ }
+ self::assertTrue($costsFound);
+ }
+
+ public function test_explain_format_json() : void
+ {
+ $query = SelectBuilder::create()->select(star())->from(table('users'));
+ $builder = ExplainBuilder::create($query)->format(ExplainFormat::JSON);
+
+ $ast = $builder->toAst();
+
+ $options = $ast->getOptions();
+ self::assertNotEmpty($options);
+ $formatFound = false;
+
+ foreach ($options as $opt) {
+ $defElem = $opt->getDefElem();
+
+ if ($defElem?->getDefname() === 'format') {
+ $formatFound = true;
+ self::assertSame('json', $defElem->getArg()?->getString()?->getSval());
+ }
+ }
+ self::assertTrue($formatFound);
+ }
+
+ public function test_explain_format_yaml() : void
+ {
+ $query = SelectBuilder::create()->select(star())->from(table('users'));
+ $builder = ExplainBuilder::create($query)->format(ExplainFormat::YAML);
+
+ $ast = $builder->toAst();
+
+ $options = $ast->getOptions();
+ self::assertNotEmpty($options);
+ $formatFound = false;
+
+ foreach ($options as $opt) {
+ $defElem = $opt->getDefElem();
+
+ if ($defElem?->getDefname() === 'format') {
+ $formatFound = true;
+ self::assertSame('yaml', $defElem->getArg()?->getString()?->getSval());
+ }
+ }
+ self::assertTrue($formatFound);
+ }
+
+ public function test_explain_timing_option() : void
+ {
+ $query = SelectBuilder::create()->select(star())->from(table('users'));
+ $builder = ExplainBuilder::create($query)->timing(true);
+
+ $ast = $builder->toAst();
+
+ $options = $ast->getOptions();
+ self::assertNotEmpty($options);
+ $timingFound = false;
+
+ foreach ($options as $opt) {
+ $defElem = $opt->getDefElem();
+
+ if ($defElem?->getDefname() === 'timing') {
+ $timingFound = true;
+ /** @phpstan-ignore method.nonObject (protobuf PHPDoc incorrectly returns int instead of Integer class) */
+ self::assertSame(1, $defElem->getArg()?->getInteger()?->getIval());
+ }
+ }
+ self::assertTrue($timingFound);
+ }
+
+ public function test_explain_verbose_option() : void
+ {
+ $query = SelectBuilder::create()->select(star())->from(table('users'));
+ $builder = ExplainBuilder::create($query)->verbose();
+
+ $ast = $builder->toAst();
+
+ $options = $ast->getOptions();
+ self::assertNotEmpty($options);
+ $optionNames = [];
+
+ foreach ($options as $opt) {
+ $optionNames[] = $opt->getDefElem()?->getDefname();
+ }
+ self::assertContains('verbose', $optionNames);
+ }
+
+ public function test_immutability() : void
+ {
+ $query = SelectBuilder::create()->select(star())->from(table('users'));
+ $original = ExplainBuilder::create($query);
+ $modified = $original->analyze();
+
+ $originalAst = $original->toAst();
+ $modifiedAst = $modified->toAst();
+
+ self::assertCount(0, $originalAst->getOptions());
+ self::assertCount(1, $modifiedAst->getOptions());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Utility/LockBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Utility/LockBuilderTest.php
new file mode 100644
index 000000000..95dc733c5
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Utility/LockBuilderTest.php
@@ -0,0 +1,153 @@
+toAst();
+
+ self::assertInstanceOf(LockStmt::class, $ast);
+ self::assertCount(1, $ast->getRelations());
+ self::assertSame('users', $ast->getRelations()[0]->getRangeVar()?->getRelname());
+ }
+
+ public function test_immutability() : void
+ {
+ $original = LockBuilder::create('users');
+ $modified = $original->share();
+
+ $originalAst = $original->toAst();
+ $modifiedAst = $modified->toAst();
+
+ self::assertSame(LockMode::ACCESS_EXCLUSIVE->value, $originalAst->getMode());
+ self::assertSame(LockMode::SHARE->value, $modifiedAst->getMode());
+ }
+
+ public function test_lock_access_exclusive_mode() : void
+ {
+ $builder = LockBuilder::create('users')->accessExclusive();
+
+ $ast = $builder->toAst();
+
+ self::assertSame(LockMode::ACCESS_EXCLUSIVE->value, $ast->getMode());
+ }
+
+ public function test_lock_access_share_mode() : void
+ {
+ $builder = LockBuilder::create('users')->accessShare();
+
+ $ast = $builder->toAst();
+
+ self::assertSame(LockMode::ACCESS_SHARE->value, $ast->getMode());
+ }
+
+ public function test_lock_exclusive_mode() : void
+ {
+ $builder = LockBuilder::create('users')->exclusive();
+
+ $ast = $builder->toAst();
+
+ self::assertSame(LockMode::EXCLUSIVE->value, $ast->getMode());
+ }
+
+ public function test_lock_in_mode() : void
+ {
+ $builder = LockBuilder::create('users')->inMode(LockMode::SHARE);
+
+ $ast = $builder->toAst();
+
+ self::assertSame(LockMode::SHARE->value, $ast->getMode());
+ }
+
+ public function test_lock_multiple_tables() : void
+ {
+ $builder = LockBuilder::create('users', 'orders');
+
+ $ast = $builder->toAst();
+
+ self::assertCount(2, $ast->getRelations());
+ self::assertSame('users', $ast->getRelations()[0]->getRangeVar()?->getRelname());
+ self::assertSame('orders', $ast->getRelations()[1]->getRangeVar()?->getRelname());
+ }
+
+ public function test_lock_nowait() : void
+ {
+ $builder = LockBuilder::create('users')->exclusive()->nowait();
+
+ $ast = $builder->toAst();
+
+ self::assertTrue($ast->getNowait());
+ }
+
+ public function test_lock_row_exclusive_mode() : void
+ {
+ $builder = LockBuilder::create('users')->rowExclusive();
+
+ $ast = $builder->toAst();
+
+ self::assertSame(LockMode::ROW_EXCLUSIVE->value, $ast->getMode());
+ }
+
+ public function test_lock_row_share_mode() : void
+ {
+ $builder = LockBuilder::create('users')->rowShare();
+
+ $ast = $builder->toAst();
+
+ self::assertSame(LockMode::ROW_SHARE->value, $ast->getMode());
+ }
+
+ public function test_lock_share_mode() : void
+ {
+ $builder = LockBuilder::create('users')->share();
+
+ $ast = $builder->toAst();
+
+ self::assertSame(LockMode::SHARE->value, $ast->getMode());
+ }
+
+ public function test_lock_share_row_exclusive_mode() : void
+ {
+ $builder = LockBuilder::create('users')->shareRowExclusive();
+
+ $ast = $builder->toAst();
+
+ self::assertSame(LockMode::SHARE_ROW_EXCLUSIVE->value, $ast->getMode());
+ }
+
+ public function test_lock_share_update_exclusive_mode() : void
+ {
+ $builder = LockBuilder::create('users')->shareUpdateExclusive();
+
+ $ast = $builder->toAst();
+
+ self::assertSame(LockMode::SHARE_UPDATE_EXCLUSIVE->value, $ast->getMode());
+ }
+
+ public function test_lock_table_with_schema() : void
+ {
+ $builder = LockBuilder::create('public.users');
+
+ $ast = $builder->toAst();
+
+ self::assertSame('public', $ast->getRelations()[0]->getRangeVar()?->getSchemaname());
+ self::assertSame('users', $ast->getRelations()[0]->getRangeVar()?->getRelname());
+ }
+}
diff --git a/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Utility/VacuumBuilderTest.php b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Utility/VacuumBuilderTest.php
new file mode 100644
index 000000000..855b5ff43
--- /dev/null
+++ b/src/lib/postgresql/tests/Flow/PostgreSql/Tests/Unit/QueryBuilder/Utility/VacuumBuilderTest.php
@@ -0,0 +1,237 @@
+toAst();
+
+ self::assertInstanceOf(VacuumStmt::class, $ast);
+ self::assertTrue($ast->getIsVacuumcmd());
+ self::assertCount(0, $ast->getRels());
+ }
+
+ public function test_immutability() : void
+ {
+ $original = VacuumBuilder::create();
+ $modified = $original->full();
+
+ $originalAst = $original->toAst();
+ $modifiedAst = $modified->toAst();
+
+ self::assertCount(0, $originalAst->getOptions());
+ self::assertCount(1, $modifiedAst->getOptions());
+ }
+
+ public function test_vacuum_analyze_option() : void
+ {
+ $builder = VacuumBuilder::create()->analyze();
+
+ $ast = $builder->toAst();
+
+ $options = $ast->getOptions();
+ self::assertNotEmpty($options);
+ $optionNames = [];
+
+ foreach ($options as $opt) {
+ $optionNames[] = $opt->getDefElem()?->getDefname();
+ }
+ self::assertContains('analyze', $optionNames);
+ }
+
+ public function test_vacuum_disable_page_skipping_option() : void
+ {
+ $builder = VacuumBuilder::create()->disablePageSkipping();
+
+ $ast = $builder->toAst();
+
+ $options = $ast->getOptions();
+ self::assertNotEmpty($options);
+ $optionNames = [];
+
+ foreach ($options as $opt) {
+ $optionNames[] = $opt->getDefElem()?->getDefname();
+ }
+ self::assertContains('disable_page_skipping', $optionNames);
+ }
+
+ public function test_vacuum_freeze_option() : void
+ {
+ $builder = VacuumBuilder::create()->freeze();
+
+ $ast = $builder->toAst();
+
+ $options = $ast->getOptions();
+ self::assertNotEmpty($options);
+ $optionNames = [];
+
+ foreach ($options as $opt) {
+ $optionNames[] = $opt->getDefElem()?->getDefname();
+ }
+ self::assertContains('freeze', $optionNames);
+ }
+
+ public function test_vacuum_full_option() : void
+ {
+ $builder = VacuumBuilder::create()->full();
+
+ $ast = $builder->toAst();
+
+ $options = $ast->getOptions();
+ self::assertNotEmpty($options);
+ $optionNames = [];
+
+ foreach ($options as $opt) {
+ $optionNames[] = $opt->getDefElem()?->getDefname();
+ }
+ self::assertContains('full', $optionNames);
+ }
+
+ public function test_vacuum_index_cleanup_option() : void
+ {
+ $builder = VacuumBuilder::create()->indexCleanup(IndexCleanup::ON);
+
+ $ast = $builder->toAst();
+
+ $options = $ast->getOptions();
+ self::assertNotEmpty($options);
+ $indexCleanupFound = false;
+
+ foreach ($options as $opt) {
+ $defElem = $opt->getDefElem();
+
+ if ($defElem?->getDefname() === 'index_cleanup') {
+ $indexCleanupFound = true;
+ self::assertSame('on', $defElem->getArg()?->getString()?->getSval());
+ }
+ }
+ self::assertTrue($indexCleanupFound);
+ }
+
+ public function test_vacuum_multiple_tables() : void
+ {
+ $builder = VacuumBuilder::create()->tables('users', 'orders', 'products');
+
+ $ast = $builder->toAst();
+
+ self::assertCount(3, $ast->getRels());
+ $rel0 = $ast->getRels()[0]->getVacuumRelation();
+ $rel1 = $ast->getRels()[1]->getVacuumRelation();
+ $rel2 = $ast->getRels()[2]->getVacuumRelation();
+ self::assertNotNull($rel0);
+ self::assertNotNull($rel1);
+ self::assertNotNull($rel2);
+ self::assertSame('users', $rel0->getRelation()?->getRelname());
+ self::assertSame('orders', $rel1->getRelation()?->getRelname());
+ self::assertSame('products', $rel2->getRelation()?->getRelname());
+ }
+
+ public function test_vacuum_parallel_option() : void
+ {
+ $builder = VacuumBuilder::create()->parallel(4);
+
+ $ast = $builder->toAst();
+
+ $options = $ast->getOptions();
+ self::assertNotEmpty($options);
+ $parallelFound = false;
+
+ foreach ($options as $opt) {
+ $defElem = $opt->getDefElem();
+
+ if ($defElem?->getDefname() === 'parallel') {
+ $parallelFound = true;
+ /** @phpstan-ignore method.nonObject (protobuf PHPDoc incorrectly returns int instead of Integer class) */
+ self::assertSame(4, $defElem->getArg()?->getInteger()?->getIval());
+ }
+ }
+ self::assertTrue($parallelFound);
+ }
+
+ public function test_vacuum_skip_locked_option() : void
+ {
+ $builder = VacuumBuilder::create()->skipLocked();
+
+ $ast = $builder->toAst();
+
+ $options = $ast->getOptions();
+ self::assertNotEmpty($options);
+ $optionNames = [];
+
+ foreach ($options as $opt) {
+ $optionNames[] = $opt->getDefElem()?->getDefname();
+ }
+ self::assertContains('skip_locked', $optionNames);
+ }
+
+ public function test_vacuum_table_with_schema() : void
+ {
+ $builder = VacuumBuilder::create()->table('public.users');
+
+ $ast = $builder->toAst();
+
+ self::assertCount(1, $ast->getRels());
+ $rel = $ast->getRels()[0]->getVacuumRelation();
+ self::assertNotNull($rel);
+ self::assertSame('public', $rel->getRelation()?->getSchemaname());
+ self::assertSame('users', $rel->getRelation()?->getRelname());
+ }
+
+ public function test_vacuum_verbose_option() : void
+ {
+ $builder = VacuumBuilder::create()->verbose();
+
+ $ast = $builder->toAst();
+
+ $options = $ast->getOptions();
+ self::assertNotEmpty($options);
+ $optionNames = [];
+
+ foreach ($options as $opt) {
+ $optionNames[] = $opt->getDefElem()?->getDefname();
+ }
+ self::assertContains('verbose', $optionNames);
+ }
+
+ public function test_vacuum_with_table() : void
+ {
+ $builder = VacuumBuilder::create()->table('users');
+
+ $ast = $builder->toAst();
+
+ self::assertCount(1, $ast->getRels());
+ $rel = $ast->getRels()[0]->getVacuumRelation();
+ self::assertNotNull($rel);
+ self::assertSame('users', $rel->getRelation()?->getRelname());
+ }
+
+ public function test_vacuum_with_table_and_columns() : void
+ {
+ $builder = VacuumBuilder::create()->table('users', 'email', 'name');
+
+ $ast = $builder->toAst();
+
+ self::assertCount(1, $ast->getRels());
+ $rel = $ast->getRels()[0]->getVacuumRelation();
+ self::assertNotNull($rel);
+ self::assertSame('users', $rel->getRelation()?->getRelname());
+ self::assertCount(2, $rel->getVaCols());
+ }
+}
diff --git a/web/landing/assets/controllers/toc_controller.js b/web/landing/assets/controllers/toc_controller.js
new file mode 100644
index 000000000..fde2ad7e7
--- /dev/null
+++ b/web/landing/assets/controllers/toc_controller.js
@@ -0,0 +1,7 @@
+import { Controller } from "@hotwired/stimulus"
+
+export default class extends Controller {
+ toggle() {
+ this.element.classList.toggle('open');
+ }
+}
diff --git a/web/landing/assets/styles/app.css b/web/landing/assets/styles/app.css
index 188d60c07..94efc04c9 100644
--- a/web/landing/assets/styles/app.css
+++ b/web/landing/assets/styles/app.css
@@ -111,30 +111,6 @@ code {
@apply text-orange-100;
}
-#blog-post .table-of-contents {
- @apply rounded p-4 mt-4 mb-6 border-gray border-2 shadow-2xl shadow-gray list-none;
-}
-
-#blog-post .table-of-contents::before {
- content: "Table of Contents";
- @apply block font-bold text-lg mb-2;
-}
-
-#blog-post .table-of-contents li {
- @apply mb-1 list-none;
-}
-
-#blog-post .table-of-contents ul {
- @apply list-none pl-4;
-}
-
-#blog-post .table-of-contents a {
- @apply no-underline hover:underline;
-}
-
-#blog-post .table-of-contents:not(:has(li:nth-child(2))) {
- display: none;
-}
#example-description h1 {
@apply font-bold text-2xl;
@@ -237,30 +213,6 @@ code {
@apply border-l-4 border-orange-100 p-2 bg-blue-300 mb-3;
}
-#documentation-page .table-of-contents {
- @apply rounded p-4 mt-4 mb-6 border-gray border-2 shadow-2xl shadow-gray list-none;
-}
-
-#documentation-page .table-of-contents::before {
- content: "Table of Contents";
- @apply block font-bold text-lg mb-2;
-}
-
-#documentation-page .table-of-contents li {
- @apply mb-1 list-none;
-}
-
-#documentation-page .table-of-contents ul {
- @apply list-none pl-4;
-}
-
-#documentation-page .table-of-contents a {
- @apply no-underline hover:underline;
-}
-
-#documentation-page .table-of-contents:not(:has(li:nth-child(2))) {
- display: none;
-}
.mermaid-wrapper {
@apply relative;
@@ -287,6 +239,55 @@ code {
@apply z-0 !p-0;
}
+/* Foldable Table of Contents */
+.toc-wrapper {
+ @apply rounded mt-4 mb-6 border-gray border-2 shadow-2xl shadow-gray overflow-hidden;
+}
+
+.toc-header {
+ @apply grid grid-cols-[1fr_auto] items-center p-4 cursor-pointer select-none;
+ @apply font-bold text-lg;
+}
+
+.toc-arrow {
+ transition: transform 0.3s ease;
+}
+
+.toc-wrapper.open .toc-arrow {
+ transform: rotate(180deg);
+}
+
+.toc-content {
+ max-height: 0;
+ overflow: hidden;
+ transition: max-height 0.3s ease;
+}
+
+.toc-wrapper.open .toc-content {
+ max-height: 2000px;
+}
+
+.toc-content .table-of-contents {
+ @apply px-4 pb-4 list-disc ml-4;
+}
+
+.toc-content .table-of-contents li {
+ @apply mb-1;
+}
+
+.toc-content .table-of-contents ul {
+ @apply list-disc pl-4 mt-1;
+}
+
+.toc-content .table-of-contents a {
+ @apply no-underline hover:underline;
+}
+
+/* Hide TOC with less than 2 items */
+.toc-wrapper:has(.table-of-contents:not(:has(li:nth-child(2)))) {
+ display: none;
+}
+
#playground {
@apply py-10 px-2 sm:px-4 mx-auto max-w-screen-2xl;
diff --git a/web/landing/assets/wasm/tools/flow.phar b/web/landing/assets/wasm/tools/flow.phar
index e01c0129f..f529838bd 100755
Binary files a/web/landing/assets/wasm/tools/flow.phar and b/web/landing/assets/wasm/tools/flow.phar differ
diff --git a/web/landing/resources/dsl.json b/web/landing/resources/dsl.json
index 080c6e325..144732ee0 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":231,"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":239,"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":247,"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":254,"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":266,"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":283,"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":299,"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":305,"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":311,"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":317,"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":326,"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":339,"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":350,"slug":"chunks-from","name":"chunks_from","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":"chunk_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":"LyoqCiAqIEBwYXJhbSBpbnQ8MSwgbWF4PiAkY2h1bmtfc2l6ZQogKgogKiBAZGVwcmVjYXRlZCB1c2UgYmF0Y2hlcygpIGluc3RlYWQKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":356,"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":362,"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":368,"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":377,"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":386,"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":395,"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":401,"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":415,"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":422,"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":428,"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":434,"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":440,"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":446,"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":452,"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":458,"slug":"rename-style","name":"rename_style","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"style","type":[{"name":"StringStyles","namespace":"Flow\\ETL\\Function\\StyleConverter","is_nullable":false,"is_variadic":false},{"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":468,"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":477,"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":486,"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":495,"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":504,"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":513,"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":522,"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":531,"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":540,"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":549,"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":560,"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":"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+fHN0cmluZyAkZGF0YQogKgogKiBAcmV0dXJuIEVudHJ5PD9hcnJheTxtaXhlZD4+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":573,"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":"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+fHN0cmluZyAkZGF0YQogKgogKiBAdGhyb3dzIEludmFsaWRBcmd1bWVudEV4Y2VwdGlvbgogKgogKiBAcmV0dXJuIEVudHJ5PG1peGVkPgogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":586,"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":604,"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":613,"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":622,"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":631,"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":640,"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":649,"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":658,"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":667,"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":681,"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":"Type","namespace":"Flow\\Types","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\/YXJyYXk8c3RyaW5nLCBtaXhlZD4gJHZhbHVlCiAqIEBwYXJhbSBUeXBlPGFycmF5PHN0cmluZywgVD4+ICR0eXBlCiAqCiAqIEByZXR1cm4gRW50cnk8P2FycmF5PHN0cmluZywgVD4+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":695,"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":"Type","namespace":"Flow\\Types","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\/YXJyYXk8c3RyaW5nLCBtaXhlZD4gJHZhbHVlCiAqIEBwYXJhbSBUeXBlPGFycmF5PHN0cmluZywgVD4+ICR0eXBlCiAqCiAqIEByZXR1cm4gRW50cnk8P2FycmF5PHN0cmluZywgVD4+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":805,"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":851,"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":"Type","namespace":"Flow\\Types","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\/YXJyYXk8YXJyYXkta2V5LCBtaXhlZD4gJHZhbHVlCiAqIEBwYXJhbSBUeXBlPGFycmF5PFRLZXksIFRWYWx1ZT4+ICRtYXBUeXBlCiAqCiAqIEByZXR1cm4gRW50cnk8P2FycmF5PFRLZXksIFRWYWx1ZT4+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":884,"slug":"type-date","name":"type_date","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBkZXByZWNhdGVkIHBsZWFzZSB1c2UgXEZsb3dcVHlwZXNcRFNMXHR5cGVfZGF0ZSgpIDogRGF0ZVR5cGUKICoKICogQHJldHVybiBUeXBlPFxEYXRlVGltZUludGVyZmFjZT4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":939,"slug":"type-int","name":"type_int","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBkZXByZWNhdGVkIHBsZWFzZSB1c2UgXEZsb3dcVHlwZXNcRFNMXHR5cGVfaW50ZWdlcigpIDogSW50ZWdlclR5cGUKICoKICogQHJldHVybiBUeXBlPGludD4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1066,"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":1072,"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":1082,"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":1091,"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":1101,"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":1108,"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":1114,"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":1120,"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":1126,"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":1132,"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":1138,"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":1144,"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":1153,"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":1159,"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":1168,"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":1174,"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":1181,"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":1187,"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":1193,"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":1199,"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":1208,"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":1214,"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":1223,"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":1233,"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":1242,"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":1248,"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":1254,"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\\Function\\StyleConverter","is_nullable":false,"is_variadic":false},{"name":"StringStyles","namespace":"Flow\\ETL\\String","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":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":1264,"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":1277,"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":1283,"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":1289,"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":1295,"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":1301,"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":1307,"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":1313,"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":1323,"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":1332,"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":1341,"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":1347,"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":1356,"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":1362,"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":1368,"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":1381,"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":1410,"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":1436,"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":1442,"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":1448,"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":1454,"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":1460,"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":1466,"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":1472,"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":1478,"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":1484,"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":1490,"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":1496,"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":1502,"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":1508,"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":1514,"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":1520,"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":1526,"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":1532,"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":1538,"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":1544,"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":1550,"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":1556,"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":1562,"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":1568,"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":1574,"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":1585,"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":1596,"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":1641,"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":1670,"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":1676,"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":1682,"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":1688,"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":1694,"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":1700,"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":1706,"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":1712,"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":1718,"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":1724,"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":1730,"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":1736,"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":1742,"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":1748,"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":1754,"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":1760,"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":1771,"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":1780,"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":1789,"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":1798,"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":1808,"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":1814,"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":1820,"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":1826,"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":1835,"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":1847,"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":1858,"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":"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":"LyoqCiAqIEFsaWFzIGZvciBgaW50X3NjaGVtYWAuCiAqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxpbnQ+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1867,"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":"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":"LyoqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxpbnQ+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1878,"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":"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":"LyoqCiAqIEFsaWFzIGZvciBgc3RyaW5nX3NjaGVtYWAuCiAqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxzdHJpbmc+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1887,"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":"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":"LyoqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxzdHJpbmc+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1896,"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":"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":"LyoqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxib29sPgogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1905,"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":"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":"LyoqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxmbG9hdD4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1919,"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":"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":"LyoqCiAqIEB0ZW1wbGF0ZSBUS2V5IG9mIGFycmF5LWtleQogKiBAdGVtcGxhdGUgVFZhbHVlCiAqCiAqIEBwYXJhbSBUeXBlPGFycmF5PFRLZXksIFRWYWx1ZT4+ICR0eXBlCiAqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxhcnJheTxUS2V5LCBUVmFsdWU+PgogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1932,"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":"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":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBUeXBlPGxpc3Q8VD4+ICR0eXBlCiAqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxsaXN0PFQ+PgogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1945,"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":"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":"LyoqCiAqIEB0ZW1wbGF0ZSBUIG9mIFxVbml0RW51bQogKgogKiBAcGFyYW0gY2xhc3Mtc3RyaW5nPFQ+ICR0eXBlCiAqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxUPgogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1954,"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":"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":"LyoqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxzdHJpbmc+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1963,"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":"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":"LyoqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxcRGF0ZVRpbWVJbnRlcmZhY2U+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1972,"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":"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":"LyoqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxcRGF0ZUludGVydmFsPgogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1981,"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":"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":"LyoqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxcRGF0ZVRpbWVJbnRlcmZhY2U+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1990,"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":"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":"LyoqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxzdHJpbmc+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1999,"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":"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":"LyoqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxIVE1MRG9jdW1lbnQ+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2008,"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":"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":"LyoqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxIVE1MRWxlbWVudD4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2017,"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":"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":"LyoqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxcRE9NRG9jdW1lbnQ+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2026,"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":"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":"LyoqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxcRE9NRWxlbWVudD4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2041,"slug":"struct-schema","name":"struct_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","type":[{"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":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBUeXBlPFQ+ICR0eXBlCiAqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxUPgogKgogKiBAZGVwcmVjYXRlZCBVc2UgYHN0cnVjdHVyZV9zY2hlbWEoKWAgaW5zdGVhZAogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2054,"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":"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":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBUeXBlPFQ+ICR0eXBlCiAqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxUPgogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2063,"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":"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":"LyoqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxcRmxvd1xUeXBlc1xWYWx1ZVxVdWlkPgogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2069,"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":2075,"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":2081,"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":2087,"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":2096,"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":2102,"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":2111,"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":2117,"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":2126,"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":2132,"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":2141,"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":2147,"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":2157,"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":2166,"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":2177,"slug":"get-type","name":"get_type","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":"Type","namespace":"Flow\\Types","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":"LyoqCiAqIEByZXR1cm4gVHlwZTxtaXhlZD4KICoKICogQGRlcHJlY2F0ZWQgUGxlYXNlIHVzZSBcRmxvd1xUeXBlc1xEU0xcZ2V0X3R5cGUoJHZhbHVlKSBpbnN0ZWFkCiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2188,"slug":"print-schema","name":"print_schema","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":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBTY2hlbWEgJHNjaGVtYQogKgogKiBAZGVwcmVjYXRlZCBQbGVhc2UgdXNlIHNjaGVtYV90b19hc2NpaSgkc2NoZW1hKSBpbnN0ZWFkCiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2194,"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":2200,"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":2206,"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":2212,"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":2218,"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":2229,"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":2235,"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":2241,"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":2250,"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":2259,"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":2268,"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":2281,"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":2344,"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":2350,"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":2356,"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":2367,"slug":"dom-element-to-string","name":"dom_element_to_string","namespace":"Flow\\ETL\\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":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBkZXByZWNhdGVkIFBsZWFzZSB1c2UgXEZsb3dcVHlwZXNcRFNMXGRvbV9lbGVtZW50X3RvX3N0cmluZygpIGluc3RlYWQKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2373,"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":2390,"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":2407,"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":2424,"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":2430,"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":2436,"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":2447,"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":2456,"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":2462,"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":2468,"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":2477,"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":2483,"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":2489,"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":2498,"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":2504,"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":2510,"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":2516,"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":2522,"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":2528,"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":2534,"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\/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":19,"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"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_reading","option":"excel"}}],"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":26,"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-meilisearch\/src\/Flow\/ETL\/Adapter\/Meilisearch\/functions.php","start_line_in_file":17,"slug":"to-meilisearch-bulk-index","name":"to_meilisearch_bulk_index","namespace":"Flow\\ETL\\Adapter\\Meilisearch","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}],"return_type":[{"name":"Loader","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"MEILI_SEARCH","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheXt1cmw6IHN0cmluZywgYXBpS2V5OiBzdHJpbmcsIGh0dHBDbGllbnQ6ID9DbGllbnRJbnRlcmZhY2V9ICRjb25maWcKICov"},{"repository_path":"src\/adapter\/etl-adapter-meilisearch\/src\/Flow\/ETL\/Adapter\/Meilisearch\/functions.php","start_line_in_file":28,"slug":"to-meilisearch-bulk-update","name":"to_meilisearch_bulk_update","namespace":"Flow\\ETL\\Adapter\\Meilisearch","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}],"return_type":[{"name":"Loader","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"MEILI_SEARCH","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheXt1cmw6IHN0cmluZywgYXBpS2V5OiBzdHJpbmcsIGh0dHBDbGllbnQ6ID9DbGllbnRJbnRlcmZhY2V9ICRjb25maWcKICov"},{"repository_path":"src\/adapter\/etl-adapter-meilisearch\/src\/Flow\/ETL\/Adapter\/Meilisearch\/functions.php","start_line_in_file":39,"slug":"meilisearch-hits-to-rows","name":"meilisearch_hits_to_rows","namespace":"Flow\\ETL\\Adapter\\Meilisearch","parameters":[],"return_type":[{"name":"HitsIntoRowsTransformer","namespace":"Flow\\ETL\\Adapter\\Meilisearch\\MeilisearchPHP","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"MEILI_SEARCH","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFRyYW5zZm9ybXMgTWVpbGlzZWFyY2ggcmVzdWx0cyBpbnRvIGNsZWFyIEZsb3cgUm93cy4KICov"},{"repository_path":"src\/adapter\/etl-adapter-meilisearch\/src\/Flow\/ETL\/Adapter\/Meilisearch\/functions.php","start_line_in_file":49,"slug":"from-meilisearch","name":"from_meilisearch","namespace":"Flow\\ETL\\Adapter\\Meilisearch","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":"params","type":[{"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}],"return_type":[{"name":"MeilisearchExtractor","namespace":"Flow\\ETL\\Adapter\\Meilisearch\\MeilisearchPHP","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"MEILI_SEARCH","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheXt1cmw6IHN0cmluZywgYXBpS2V5OiBzdHJpbmd9ICRjb25maWcKICogQHBhcmFtIGFycmF5e3E6IHN0cmluZywgbGltaXQ\/OiA\/aW50LCBvZmZzZXQ\/OiA\/aW50LCBhdHRyaWJ1dGVzVG9SZXRyaWV2ZT86ID9hcnJheTxzdHJpbmc+LCBzb3J0PzogP2FycmF5PHN0cmluZz59ICRwYXJhbXMKICov"},{"repository_path":"src\/adapter\/etl-adapter-parquet\/src\/Flow\/ETL\/Adapter\/Parquet\/functions.php","start_line_in_file":27,"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","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Parquet\\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":57,"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":85,"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":93,"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":99,"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":105,"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":20,"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":26,"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":32,"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":51,"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":64,"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":78,"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":89,"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":95,"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":105,"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":114,"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":125,"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\/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":"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":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBhcnJheTxzdHJpbmcsIFR5cGU8VD4+ICRlbGVtZW50cwogKiBAcGFyYW0gYXJyYXk8c3RyaW5nLCBUeXBlPFQ+PiAkb3B0aW9uYWxfZWxlbWVudHMKICoKICogQHJldHVybiBUeXBlPGFycmF5PHN0cmluZywgVD4+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":"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":"LyoqCiAqIEB0ZW1wbGF0ZSBUS2V5IG9mIGFycmF5LWtleQogKiBAdGVtcGxhdGUgVFZhbHVlCiAqCiAqIEBwYXJhbSBUeXBlPFRLZXk+ICRrZXlfdHlwZQogKiBAcGFyYW0gVHlwZTxUVmFsdWU+ICR2YWx1ZV90eXBlCiAqCiAqIEByZXR1cm4gVHlwZTxhcnJheTxUS2V5LCBUVmFsdWU+PgogKi8="},{"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":"LyoqCiAqIEByZXR1cm4gVHlwZTxzdHJpbmc+CiAqLw=="},{"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\/pg-query\/src\/Flow\/PgQuery\/DSL\/functions.php","start_line_in_file":13,"slug":"pg-parser","name":"pg_parser","namespace":"Flow\\PgQuery\\DSL","parameters":[],"return_type":[{"name":"Parser","namespace":"Flow\\PgQuery","is_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\/pg-query\/src\/Flow\/PgQuery\/DSL\/functions.php","start_line_in_file":19,"slug":"pg-parse","name":"pg_parse","namespace":"Flow\\PgQuery\\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\\PgQuery","is_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\/pg-query\/src\/Flow\/PgQuery\/DSL\/functions.php","start_line_in_file":29,"slug":"pg-fingerprint","name":"pg_fingerprint","namespace":"Flow\\PgQuery\\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\/pg-query\/src\/Flow\/PgQuery\/DSL\/functions.php","start_line_in_file":40,"slug":"pg-normalize","name":"pg_normalize","namespace":"Flow\\PgQuery\\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\/pg-query\/src\/Flow\/PgQuery\/DSL\/functions.php","start_line_in_file":50,"slug":"pg-normalize-utility","name":"pg_normalize_utility","namespace":"Flow\\PgQuery\\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\/pg-query\/src\/Flow\/PgQuery\/DSL\/functions.php","start_line_in_file":61,"slug":"pg-split","name":"pg_split","namespace":"Flow\\PgQuery\\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\/pg-query\/src\/Flow\/PgQuery\/DSL\/functions.php","start_line_in_file":70,"slug":"pg-deparse-options","name":"pg_deparse_options","namespace":"Flow\\PgQuery\\DSL","parameters":[],"return_type":[{"name":"DeparseOptions","namespace":"Flow\\PgQuery","is_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\/pg-query\/src\/Flow\/PgQuery\/DSL\/functions.php","start_line_in_file":84,"slug":"pg-deparse","name":"pg_deparse","namespace":"Flow\\PgQuery\\DSL","parameters":[{"name":"query","type":[{"name":"ParsedQuery","namespace":"Flow\\PgQuery","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\\PgQuery","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\/pg-query\/src\/Flow\/PgQuery\/DSL\/functions.php","start_line_in_file":100,"slug":"pg-format","name":"pg_format","namespace":"Flow\\PgQuery\\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\\PgQuery","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\/pg-query\/src\/Flow\/PgQuery\/DSL\/functions.php","start_line_in_file":110,"slug":"pg-summary","name":"pg_summary","namespace":"Flow\\PgQuery\\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\/pg-query\/src\/Flow\/PgQuery\/DSL\/functions.php","start_line_in_file":125,"slug":"pg-to-paginated-query","name":"pg_to_paginated_query","namespace":"Flow\\PgQuery\\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\/pg-query\/src\/Flow\/PgQuery\/DSL\/functions.php","start_line_in_file":144,"slug":"pg-to-count-query","name":"pg_to_count_query","namespace":"Flow\\PgQuery\\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\/pg-query\/src\/Flow\/PgQuery\/DSL\/functions.php","start_line_in_file":165,"slug":"pg-to-keyset-query","name":"pg_to_keyset_query","namespace":"Flow\\PgQuery\\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":"LyoqCiAqIFRyYW5zZm9ybSBhIFNRTCBxdWVyeSBpbnRvIGEga2V5c2V0IChjdXJzb3ItYmFzZWQpIHBhZ2luYXRlZCBxdWVyeS4KICoKICogTW9yZSBlZmZpY2llbnQgdGhhbiBPRkZTRVQgZm9yIGxhcmdlIGRhdGFzZXRzIC0gdXNlcyBpbmRleGVkIFdIRVJFIGNvbmRpdGlvbnMuCiAqCiAqIEBwYXJhbSBzdHJpbmcgJHNxbCBUaGUgU1FMIHF1ZXJ5IHRvIHBhZ2luYXRlIChtdXN0IGhhdmUgT1JERVIgQlkpCiAqIEBwYXJhbSBpbnQgJGxpbWl0IE1heGltdW0gbnVtYmVyIG9mIHJvd3MgdG8gcmV0dXJuCiAqIEBwYXJhbSBsaXN0PEtleXNldENvbHVtbj4gJGNvbHVtbnMgQ29sdW1ucyBmb3Iga2V5c2V0IHBhZ2luYXRpb24gKG11c3QgbWF0Y2ggT1JERVIgQlkpCiAqIEBwYXJhbSBudWxsfGxpc3Q8bnVsbHxib29sfGZsb2F0fGludHxzdHJpbmc+ICRjdXJzb3IgVmFsdWVzIGZyb20gbGFzdCByb3cgb2YgcHJldmlvdXMgcGFnZSAobnVsbCBmb3IgZmlyc3QgcGFnZSkKICoKICogQHJldHVybiBzdHJpbmcgVGhlIHBhZ2luYXRlZCBTUUwgcXVlcnkKICov"},{"repository_path":"src\/lib\/pg-query\/src\/Flow\/PgQuery\/DSL\/functions.php","start_line_in_file":180,"slug":"pg-pagination-config","name":"pg_pagination_config","namespace":"Flow\\PgQuery\\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},{"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":"PaginationConfig","namespace":"Flow\\PgQuery\\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":"LyoqCiAqIENyZWF0ZSBhIFBhZ2luYXRpb25Db25maWcgZm9yIG9mZnNldC1iYXNlZCBwYWdpbmF0aW9uLgogKgogKiBAcGFyYW0gaW50ICRsaW1pdCBNYXhpbXVtIG51bWJlciBvZiByb3dzIHRvIHJldHVybgogKiBAcGFyYW0gaW50ICRvZmZzZXQgTnVtYmVyIG9mIHJvd3MgdG8gc2tpcCAocmVxdWlyZXMgT1JERVIgQlkgaW4gcXVlcnkpCiAqLw=="},{"repository_path":"src\/lib\/pg-query\/src\/Flow\/PgQuery\/DSL\/functions.php","start_line_in_file":194,"slug":"pg-pagination","name":"pg_pagination","namespace":"Flow\\PgQuery\\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},{"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":"PaginationModifier","namespace":"Flow\\PgQuery\\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":"LyoqCiAqIENyZWF0ZSBhIFBhZ2luYXRpb25Nb2RpZmllciBmb3Igb2Zmc2V0LWJhc2VkIHBhZ2luYXRpb24uCiAqCiAqIEFwcGxpZXMgTElNSVQgYW5kIE9GRlNFVCB0byB0aGUgcXVlcnkuIE9GRlNFVCB3aXRob3V0IE9SREVSIEJZIHdpbGwgdGhyb3cgYW4gZXhjZXB0aW9uLgogKgogKiBAcGFyYW0gaW50ICRsaW1pdCBNYXhpbXVtIG51bWJlciBvZiByb3dzIHRvIHJldHVybgogKiBAcGFyYW0gaW50ICRvZmZzZXQgTnVtYmVyIG9mIHJvd3MgdG8gc2tpcCAocmVxdWlyZXMgT1JERVIgQlkgaW4gcXVlcnkpCiAqLw=="},{"repository_path":"src\/lib\/pg-query\/src\/Flow\/PgQuery\/DSL\/functions.php","start_line_in_file":206,"slug":"pg-count-modifier","name":"pg_count_modifier","namespace":"Flow\\PgQuery\\DSL","parameters":[],"return_type":[{"name":"CountModifier","namespace":"Flow\\PgQuery\\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":"LyoqCiAqIENyZWF0ZSBhIENvdW50TW9kaWZpZXIgdGhhdCB0cmFuc2Zvcm1zIGEgU0VMRUNUIHF1ZXJ5IGludG8gYSBDT1VOVCBxdWVyeS4KICoKICogVGhlIG9yaWdpbmFsIHF1ZXJ5IGlzIHdyYXBwZWQgaW46IFNFTEVDVCBDT1VOVCgqKSBGUk9NICguLi4pIEFTIF9jb3VudF9zdWJxCiAqIE9SREVSIEJZIGFuZCBMSU1JVC9PRkZTRVQgYXJlIHJlbW92ZWQgZnJvbSB0aGUgaW5uZXIgcXVlcnkuCiAqLw=="},{"repository_path":"src\/lib\/pg-query\/src\/Flow\/PgQuery\/DSL\/functions.php","start_line_in_file":218,"slug":"pg-keyset-column","name":"pg_keyset_column","namespace":"Flow\\PgQuery\\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\\PgQuery\\AST\\Transformers","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\PgQuery\\AST\\Transformers\\SortOrder::..."}],"return_type":[{"name":"KeysetColumn","namespace":"Flow\\PgQuery\\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\/pg-query\/src\/Flow\/PgQuery\/DSL\/functions.php","start_line_in_file":231,"slug":"pg-keyset-pagination-config","name":"pg_keyset_pagination_config","namespace":"Flow\\PgQuery\\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},{"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":"KeysetPaginationConfig","namespace":"Flow\\PgQuery\\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":"LyoqCiAqIENyZWF0ZSBhIEtleXNldFBhZ2luYXRpb25Db25maWcgZm9yIGN1cnNvci1iYXNlZCBwYWdpbmF0aW9uLgogKgogKiBAcGFyYW0gaW50ICRsaW1pdCBNYXhpbXVtIG51bWJlciBvZiByb3dzIHRvIHJldHVybgogKiBAcGFyYW0gbGlzdDxLZXlzZXRDb2x1bW4+ICRjb2x1bW5zIENvbHVtbnMgdG8gdXNlIGZvciBrZXlzZXQgcGFnaW5hdGlvbiAobXVzdCBtYXRjaCBPUkRFUiBCWSkKICogQHBhcmFtIG51bGx8bGlzdDxudWxsfGJvb2x8ZmxvYXR8aW50fHN0cmluZz4gJGN1cnNvciBDdXJzb3IgdmFsdWVzIGZyb20gdGhlIGxhc3Qgcm93IG9mIHByZXZpb3VzIHBhZ2UgKG51bGwgZm9yIGZpcnN0IHBhZ2UpCiAqLw=="},{"repository_path":"src\/lib\/pg-query\/src\/Flow\/PgQuery\/DSL\/functions.php","start_line_in_file":247,"slug":"pg-keyset-pagination","name":"pg_keyset_pagination","namespace":"Flow\\PgQuery\\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},{"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":"KeysetPaginationModifier","namespace":"Flow\\PgQuery\\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":"LyoqCiAqIENyZWF0ZSBhIEtleXNldFBhZ2luYXRpb25Nb2RpZmllciBmb3IgY3Vyc29yLWJhc2VkIHBhZ2luYXRpb24uCiAqCiAqIEtleXNldCBwYWdpbmF0aW9uIGlzIG1vcmUgZWZmaWNpZW50IHRoYW4gT0ZGU0VUIGZvciBsYXJnZSBkYXRhc2V0cyBiZWNhdXNlIGl0IHVzZXMKICogaW5kZXhlZCBXSEVSRSBjb25kaXRpb25zIGluc3RlYWQgb2Ygc2Nhbm5pbmcgYW5kIHNraXBwaW5nIHJvd3MuCiAqCiAqIEBwYXJhbSBpbnQgJGxpbWl0IE1heGltdW0gbnVtYmVyIG9mIHJvd3MgdG8gcmV0dXJuCiAqIEBwYXJhbSBsaXN0PEtleXNldENvbHVtbj4gJGNvbHVtbnMgQ29sdW1ucyB0byB1c2UgZm9yIGtleXNldCBwYWdpbmF0aW9uIChtdXN0IG1hdGNoIE9SREVSIEJZKQogKiBAcGFyYW0gbnVsbHxsaXN0PG51bGx8Ym9vbHxmbG9hdHxpbnR8c3RyaW5nPiAkY3Vyc29yIEN1cnNvciB2YWx1ZXMgZnJvbSB0aGUgbGFzdCByb3cgb2YgcHJldmlvdXMgcGFnZSAobnVsbCBmb3IgZmlyc3QgcGFnZSkKICov"},{"repository_path":"src\/lib\/pg-query\/src\/Flow\/PgQuery\/DSL\/functions.php","start_line_in_file":256,"slug":"pg-query-columns","name":"pg_query_columns","namespace":"Flow\\PgQuery\\DSL","parameters":[{"name":"query","type":[{"name":"ParsedQuery","namespace":"Flow\\PgQuery","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\\PgQuery\\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\/pg-query\/src\/Flow\/PgQuery\/DSL\/functions.php","start_line_in_file":265,"slug":"pg-query-tables","name":"pg_query_tables","namespace":"Flow\\PgQuery\\DSL","parameters":[{"name":"query","type":[{"name":"ParsedQuery","namespace":"Flow\\PgQuery","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\\PgQuery\\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\/pg-query\/src\/Flow\/PgQuery\/DSL\/functions.php","start_line_in_file":274,"slug":"pg-query-functions","name":"pg_query_functions","namespace":"Flow\\PgQuery\\DSL","parameters":[{"name":"query","type":[{"name":"ParsedQuery","namespace":"Flow\\PgQuery","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\\PgQuery\\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\/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\/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}]
\ No newline at end of file
+[{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":231,"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":239,"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":247,"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":254,"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":266,"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":283,"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":299,"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":305,"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":311,"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":317,"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":326,"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":339,"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":350,"slug":"chunks-from","name":"chunks_from","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":"chunk_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":"LyoqCiAqIEBwYXJhbSBpbnQ8MSwgbWF4PiAkY2h1bmtfc2l6ZQogKgogKiBAZGVwcmVjYXRlZCB1c2UgYmF0Y2hlcygpIGluc3RlYWQKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":356,"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":362,"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":368,"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":377,"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":386,"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":395,"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":401,"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":415,"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":422,"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":428,"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":434,"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":440,"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":446,"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":452,"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":458,"slug":"rename-style","name":"rename_style","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"style","type":[{"name":"StringStyles","namespace":"Flow\\ETL\\Function\\StyleConverter","is_nullable":false,"is_variadic":false},{"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":468,"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":477,"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":486,"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":495,"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":504,"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":513,"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":522,"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":531,"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":540,"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":549,"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":560,"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":"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+fHN0cmluZyAkZGF0YQogKgogKiBAcmV0dXJuIEVudHJ5PD9hcnJheTxtaXhlZD4+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":573,"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":"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+fHN0cmluZyAkZGF0YQogKgogKiBAdGhyb3dzIEludmFsaWRBcmd1bWVudEV4Y2VwdGlvbgogKgogKiBAcmV0dXJuIEVudHJ5PG1peGVkPgogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":586,"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":604,"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":613,"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":622,"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":631,"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":640,"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":649,"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":658,"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":667,"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":681,"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":"Type","namespace":"Flow\\Types","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\/YXJyYXk8c3RyaW5nLCBtaXhlZD4gJHZhbHVlCiAqIEBwYXJhbSBUeXBlPGFycmF5PHN0cmluZywgVD4+ICR0eXBlCiAqCiAqIEByZXR1cm4gRW50cnk8P2FycmF5PHN0cmluZywgVD4+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":695,"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":"Type","namespace":"Flow\\Types","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\/YXJyYXk8c3RyaW5nLCBtaXhlZD4gJHZhbHVlCiAqIEBwYXJhbSBUeXBlPGFycmF5PHN0cmluZywgVD4+ICR0eXBlCiAqCiAqIEByZXR1cm4gRW50cnk8P2FycmF5PHN0cmluZywgVD4+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":805,"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":851,"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":"Type","namespace":"Flow\\Types","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\/YXJyYXk8YXJyYXkta2V5LCBtaXhlZD4gJHZhbHVlCiAqIEBwYXJhbSBUeXBlPGFycmF5PFRLZXksIFRWYWx1ZT4+ICRtYXBUeXBlCiAqCiAqIEByZXR1cm4gRW50cnk8P2FycmF5PFRLZXksIFRWYWx1ZT4+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":884,"slug":"type-date","name":"type_date","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBkZXByZWNhdGVkIHBsZWFzZSB1c2UgXEZsb3dcVHlwZXNcRFNMXHR5cGVfZGF0ZSgpIDogRGF0ZVR5cGUKICoKICogQHJldHVybiBUeXBlPFxEYXRlVGltZUludGVyZmFjZT4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":939,"slug":"type-int","name":"type_int","namespace":"Flow\\ETL\\DSL","parameters":[],"return_type":[{"name":"Type","namespace":"Flow\\Types","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"CORE","type":"TYPE"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBkZXByZWNhdGVkIHBsZWFzZSB1c2UgXEZsb3dcVHlwZXNcRFNMXHR5cGVfaW50ZWdlcigpIDogSW50ZWdlclR5cGUKICoKICogQHJldHVybiBUeXBlPGludD4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1066,"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":1072,"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":1082,"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":1091,"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":1101,"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":1108,"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":1114,"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":1120,"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":1126,"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":1132,"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":1138,"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":1144,"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":1153,"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":1159,"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":1168,"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":1174,"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":1181,"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":1187,"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":1193,"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":1199,"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":1208,"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":1214,"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":1223,"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":1233,"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":1242,"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":1248,"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":1254,"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\\Function\\StyleConverter","is_nullable":false,"is_variadic":false},{"name":"StringStyles","namespace":"Flow\\ETL\\String","is_nullable":false,"is_variadic":false},{"name":"string","namespace":null,"is_nullable":false,"is_variadic":false}],"has_default_value":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":1264,"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":1277,"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":1283,"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":1289,"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":1295,"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":1301,"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":1307,"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":1313,"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":1323,"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":1332,"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":1341,"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":1347,"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":1356,"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":1362,"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":1368,"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":1381,"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":1410,"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":1436,"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":1442,"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":1448,"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":1454,"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":1460,"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":1466,"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":1472,"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":1478,"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":1484,"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":1490,"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":1496,"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":1502,"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":1508,"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":1514,"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":1520,"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":1526,"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":1532,"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":1538,"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":1544,"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":1550,"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":1556,"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":1562,"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":1568,"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":1574,"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":1585,"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":1596,"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":1641,"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":1670,"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":1676,"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":1682,"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":1688,"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":1694,"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":1700,"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":1706,"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":1712,"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":1718,"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":1724,"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":1730,"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":1736,"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":1742,"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":1748,"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":1754,"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":1760,"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":1771,"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":1780,"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":1789,"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":1798,"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":1808,"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":1814,"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":1820,"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":1826,"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":1835,"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":1847,"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":1858,"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":"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":"LyoqCiAqIEFsaWFzIGZvciBgaW50X3NjaGVtYWAuCiAqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxpbnQ+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1867,"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":"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":"LyoqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxpbnQ+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1878,"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":"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":"LyoqCiAqIEFsaWFzIGZvciBgc3RyaW5nX3NjaGVtYWAuCiAqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxzdHJpbmc+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1887,"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":"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":"LyoqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxzdHJpbmc+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1896,"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":"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":"LyoqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxib29sPgogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1905,"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":"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":"LyoqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxmbG9hdD4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1919,"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":"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":"LyoqCiAqIEB0ZW1wbGF0ZSBUS2V5IG9mIGFycmF5LWtleQogKiBAdGVtcGxhdGUgVFZhbHVlCiAqCiAqIEBwYXJhbSBUeXBlPGFycmF5PFRLZXksIFRWYWx1ZT4+ICR0eXBlCiAqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxhcnJheTxUS2V5LCBUVmFsdWU+PgogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1932,"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":"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":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBUeXBlPGxpc3Q8VD4+ICR0eXBlCiAqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxsaXN0PFQ+PgogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1945,"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":"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":"LyoqCiAqIEB0ZW1wbGF0ZSBUIG9mIFxVbml0RW51bQogKgogKiBAcGFyYW0gY2xhc3Mtc3RyaW5nPFQ+ICR0eXBlCiAqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxUPgogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1954,"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":"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":"LyoqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxzdHJpbmc+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1963,"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":"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":"LyoqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxcRGF0ZVRpbWVJbnRlcmZhY2U+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1972,"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":"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":"LyoqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxcRGF0ZUludGVydmFsPgogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1981,"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":"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":"LyoqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxcRGF0ZVRpbWVJbnRlcmZhY2U+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1990,"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":"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":"LyoqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxzdHJpbmc+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":1999,"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":"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":"LyoqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxIVE1MRG9jdW1lbnQ+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2008,"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":"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":"LyoqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxIVE1MRWxlbWVudD4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2017,"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":"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":"LyoqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxcRE9NRG9jdW1lbnQ+CiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2026,"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":"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":"LyoqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxcRE9NRWxlbWVudD4KICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2041,"slug":"struct-schema","name":"struct_schema","namespace":"Flow\\ETL\\DSL","parameters":[{"name":"name","type":[{"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":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBUeXBlPFQ+ICR0eXBlCiAqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxUPgogKgogKiBAZGVwcmVjYXRlZCBVc2UgYHN0cnVjdHVyZV9zY2hlbWEoKWAgaW5zdGVhZAogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2054,"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":"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":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBUeXBlPFQ+ICR0eXBlCiAqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxUPgogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2063,"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":"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":"LyoqCiAqIEByZXR1cm4gRGVmaW5pdGlvbjxcRmxvd1xUeXBlc1xWYWx1ZVxVdWlkPgogKi8="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2069,"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":2075,"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":2081,"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":2087,"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":2096,"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":2102,"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":2111,"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":2117,"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":2126,"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":2132,"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":2141,"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":2147,"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":2157,"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":2166,"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":2177,"slug":"get-type","name":"get_type","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":"Type","namespace":"Flow\\Types","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":"LyoqCiAqIEByZXR1cm4gVHlwZTxtaXhlZD4KICoKICogQGRlcHJlY2F0ZWQgUGxlYXNlIHVzZSBcRmxvd1xUeXBlc1xEU0xcZ2V0X3R5cGUoJHZhbHVlKSBpbnN0ZWFkCiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2188,"slug":"print-schema","name":"print_schema","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":"SCHEMA"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBTY2hlbWEgJHNjaGVtYQogKgogKiBAZGVwcmVjYXRlZCBQbGVhc2UgdXNlIHNjaGVtYV90b19hc2NpaSgkc2NoZW1hKSBpbnN0ZWFkCiAqLw=="},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2194,"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":2200,"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":2206,"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":2212,"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":2218,"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":2229,"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":2235,"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":2241,"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":2250,"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":2259,"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":2268,"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":2281,"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":2344,"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":2350,"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":2356,"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":2367,"slug":"dom-element-to-string","name":"dom_element_to_string","namespace":"Flow\\ETL\\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":"CORE","type":"DATA_FRAME"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBkZXByZWNhdGVkIFBsZWFzZSB1c2UgXEZsb3dcVHlwZXNcRFNMXGRvbV9lbGVtZW50X3RvX3N0cmluZygpIGluc3RlYWQKICov"},{"repository_path":"src\/core\/etl\/src\/Flow\/ETL\/DSL\/functions.php","start_line_in_file":2373,"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":2390,"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":2407,"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":2424,"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":2430,"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":2436,"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":2447,"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":2456,"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":2462,"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":2468,"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":2477,"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":2483,"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":2489,"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":2498,"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":2504,"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":2510,"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":2516,"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":2522,"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":2528,"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":2534,"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\/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":19,"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"}},{"name":"DocumentationExample","namespace":"Flow\\ETL\\Attribute","arguments":{"topic":"data_frame","example":"data_reading","option":"excel"}}],"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":26,"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-meilisearch\/src\/Flow\/ETL\/Adapter\/Meilisearch\/functions.php","start_line_in_file":17,"slug":"to-meilisearch-bulk-index","name":"to_meilisearch_bulk_index","namespace":"Flow\\ETL\\Adapter\\Meilisearch","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}],"return_type":[{"name":"Loader","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"MEILI_SEARCH","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheXt1cmw6IHN0cmluZywgYXBpS2V5OiBzdHJpbmcsIGh0dHBDbGllbnQ6ID9DbGllbnRJbnRlcmZhY2V9ICRjb25maWcKICov"},{"repository_path":"src\/adapter\/etl-adapter-meilisearch\/src\/Flow\/ETL\/Adapter\/Meilisearch\/functions.php","start_line_in_file":28,"slug":"to-meilisearch-bulk-update","name":"to_meilisearch_bulk_update","namespace":"Flow\\ETL\\Adapter\\Meilisearch","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}],"return_type":[{"name":"Loader","namespace":"Flow\\ETL","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"MEILI_SEARCH","type":"LOADER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheXt1cmw6IHN0cmluZywgYXBpS2V5OiBzdHJpbmcsIGh0dHBDbGllbnQ6ID9DbGllbnRJbnRlcmZhY2V9ICRjb25maWcKICov"},{"repository_path":"src\/adapter\/etl-adapter-meilisearch\/src\/Flow\/ETL\/Adapter\/Meilisearch\/functions.php","start_line_in_file":39,"slug":"meilisearch-hits-to-rows","name":"meilisearch_hits_to_rows","namespace":"Flow\\ETL\\Adapter\\Meilisearch","parameters":[],"return_type":[{"name":"HitsIntoRowsTransformer","namespace":"Flow\\ETL\\Adapter\\Meilisearch\\MeilisearchPHP","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"MEILI_SEARCH","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFRyYW5zZm9ybXMgTWVpbGlzZWFyY2ggcmVzdWx0cyBpbnRvIGNsZWFyIEZsb3cgUm93cy4KICov"},{"repository_path":"src\/adapter\/etl-adapter-meilisearch\/src\/Flow\/ETL\/Adapter\/Meilisearch\/functions.php","start_line_in_file":49,"slug":"from-meilisearch","name":"from_meilisearch","namespace":"Flow\\ETL\\Adapter\\Meilisearch","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":"params","type":[{"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}],"return_type":[{"name":"MeilisearchExtractor","namespace":"Flow\\ETL\\Adapter\\Meilisearch\\MeilisearchPHP","is_nullable":false,"is_variadic":false}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"MEILI_SEARCH","type":"EXTRACTOR"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIEBwYXJhbSBhcnJheXt1cmw6IHN0cmluZywgYXBpS2V5OiBzdHJpbmd9ICRjb25maWcKICogQHBhcmFtIGFycmF5e3E6IHN0cmluZywgbGltaXQ\/OiA\/aW50LCBvZmZzZXQ\/OiA\/aW50LCBhdHRyaWJ1dGVzVG9SZXRyaWV2ZT86ID9hcnJheTxzdHJpbmc+LCBzb3J0PzogP2FycmF5PHN0cmluZz59ICRwYXJhbXMKICov"},{"repository_path":"src\/adapter\/etl-adapter-parquet\/src\/Flow\/ETL\/Adapter\/Parquet\/functions.php","start_line_in_file":27,"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","is_nullable":false,"is_variadic":false}],"has_default_value":true,"is_nullable":false,"is_variadic":false,"default_value":"Flow\\Parquet\\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":57,"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":85,"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":93,"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":99,"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":105,"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":20,"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":26,"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":32,"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":51,"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":64,"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":78,"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":89,"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":95,"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":105,"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":114,"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":125,"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\/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":"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":"LyoqCiAqIEB0ZW1wbGF0ZSBUCiAqCiAqIEBwYXJhbSBhcnJheTxzdHJpbmcsIFR5cGU8VD4+ICRlbGVtZW50cwogKiBAcGFyYW0gYXJyYXk8c3RyaW5nLCBUeXBlPFQ+PiAkb3B0aW9uYWxfZWxlbWVudHMKICoKICogQHJldHVybiBUeXBlPGFycmF5PHN0cmluZywgVD4+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":"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":"LyoqCiAqIEB0ZW1wbGF0ZSBUS2V5IG9mIGFycmF5LWtleQogKiBAdGVtcGxhdGUgVFZhbHVlCiAqCiAqIEBwYXJhbSBUeXBlPFRLZXk+ICRrZXlfdHlwZQogKiBAcGFyYW0gVHlwZTxUVmFsdWU+ICR2YWx1ZV90eXBlCiAqCiAqIEByZXR1cm4gVHlwZTxhcnJheTxUS2V5LCBUVmFsdWU+PgogKi8="},{"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":"LyoqCiAqIEByZXR1cm4gVHlwZTxzdHJpbmc+CiAqLw=="},{"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":161,"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":167,"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":177,"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":188,"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":198,"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":209,"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":218,"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":232,"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":248,"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":258,"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":273,"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":292,"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":313,"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":"LyoqCiAqIFRyYW5zZm9ybSBhIFNRTCBxdWVyeSBpbnRvIGEga2V5c2V0IChjdXJzb3ItYmFzZWQpIHBhZ2luYXRlZCBxdWVyeS4KICoKICogTW9yZSBlZmZpY2llbnQgdGhhbiBPRkZTRVQgZm9yIGxhcmdlIGRhdGFzZXRzIC0gdXNlcyBpbmRleGVkIFdIRVJFIGNvbmRpdGlvbnMuCiAqCiAqIEBwYXJhbSBzdHJpbmcgJHNxbCBUaGUgU1FMIHF1ZXJ5IHRvIHBhZ2luYXRlIChtdXN0IGhhdmUgT1JERVIgQlkpCiAqIEBwYXJhbSBpbnQgJGxpbWl0IE1heGltdW0gbnVtYmVyIG9mIHJvd3MgdG8gcmV0dXJuCiAqIEBwYXJhbSBsaXN0PEtleXNldENvbHVtbj4gJGNvbHVtbnMgQ29sdW1ucyBmb3Iga2V5c2V0IHBhZ2luYXRpb24gKG11c3QgbWF0Y2ggT1JERVIgQlkpCiAqIEBwYXJhbSBudWxsfGxpc3Q8bnVsbHxib29sfGZsb2F0fGludHxzdHJpbmc+ICRjdXJzb3IgVmFsdWVzIGZyb20gbGFzdCByb3cgb2YgcHJldmlvdXMgcGFnZSAobnVsbCBmb3IgZmlyc3QgcGFnZSkKICoKICogQHJldHVybiBzdHJpbmcgVGhlIHBhZ2luYXRlZCBTUUwgcXVlcnkKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":328,"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":337,"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":346,"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":355,"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":366,"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":382,"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":395,"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":404,"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":413,"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":425,"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":439,"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":453,"slug":"sql-to-query-builder","name":"sql_to_query_builder","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":"SelectBuilder","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}],"attributes":[{"name":"DocumentationDSL","namespace":"Flow\\ETL\\Attribute","arguments":{"module":"PG_QUERY","type":"HELPER"}}],"scalar_function_chain":false,"doc_comment":"LyoqCiAqIFBhcnNlIFNRTCBhbmQgY29udmVydCB0byBhIFF1ZXJ5QnVpbGRlciBmb3IgbW9kaWZpY2F0aW9uLgogKgogKiBPbmx5IHdvcmtzIGZvciBzaW5nbGUtc3RhdGVtZW50IHF1ZXJpZXMuIEZvciBtdWx0aXBsZSBzdGF0ZW1lbnRzLAogKiB1c2UgcGdfc3BsaXQoKSB0byBwYXJzZSBzdGF0ZW1lbnRzIGluZGl2aWR1YWxseS4KICoKICogQHRocm93cyBcSW52YWxpZEFyZ3VtZW50RXhjZXB0aW9uIGlmIHF1ZXJ5IGNvbnRhaW5zIG11bHRpcGxlIHN0YXRlbWVudHMgb3IgdW5zdXBwb3J0ZWQgc3RhdGVtZW50IHR5cGUKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":478,"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":507,"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":523,"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":538,"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":550,"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":563,"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":572,"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":585,"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":594,"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":603,"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":612,"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":623,"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":632,"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":643,"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":654,"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":666,"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":"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}],"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":"LyoqCiAqIENyZWF0ZSBhIHR5cGUgY2FzdCBleHByZXNzaW9uLgogKgogKiBAcGFyYW0gRXhwcmVzc2lvbiAkZXhwciBFeHByZXNzaW9uIHRvIGNhc3QKICogQHBhcmFtIHN0cmluZyAkdHlwZSBUYXJnZXQgdHlwZSBuYW1lIChjYW4gaW5jbHVkZSBzY2hlbWEgbGlrZSAicGdfY2F0YWxvZy5pbnQ0IikKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":679,"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":688,"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":697,"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":711,"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":722,"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":731,"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":"LyoqCiAqIENyZWF0ZSBhIHJhdyBTUUwgZXhwcmVzc2lvbiAodXNlIHdpdGggY2F1dGlvbikuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":740,"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":754,"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+ICRhcmdzIEZ1bmN0aW9uIGFyZ3VtZW50cwogKiBAcGFyYW0gbGlzdDxFeHByZXNzaW9uPiAkcGFydGl0aW9uQnkgUEFSVElUSU9OIEJZIGV4cHJlc3Npb25zCiAqIEBwYXJhbSBsaXN0PE9yZGVyQnl8T3JkZXJCeUl0ZW0+ICRvcmRlckJ5IE9SREVSIEJZIGl0ZW1zCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":767,"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":776,"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":785,"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":794,"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":803,"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":812,"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":821,"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":833,"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":842,"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":851,"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":860,"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":869,"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":878,"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":890,"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":902,"slug":"all-sub-selects","name":"all_sub_selects","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":916,"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":927,"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":936,"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":945,"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":"LyoqCiAqIENyZWF0ZSBhIHJhdyBTUUwgY29uZGl0aW9uICh1c2Ugd2l0aCBjYXV0aW9uKS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":957,"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":969,"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":982,"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":995,"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":1008,"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":1021,"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":1033,"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":1045,"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":1057,"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":1069,"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":1081,"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":1093,"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":1107,"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":1121,"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":1135,"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":1149,"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":1161,"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":1180,"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":1195,"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":1209,"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":1221,"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":1234,"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":"OrderByItem","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":1246,"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":"OrderByItem","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":1255,"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":"OrderByItem","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":1269,"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":1291,"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+ICRwYXJ0aXRpb25CeSBQQVJUSVRJT04gQlkgZXhwcmVzc2lvbnMKICogQHBhcmFtIGxpc3Q8T3JkZXJCeXxPcmRlckJ5SXRlbT4gJG9yZGVyQnkgT1JERVIgQlkgaXRlbXMKICogQHBhcmFtIG51bGx8V2luZG93RnJhbWUgJGZyYW1lIFdpbmRvdyBmcmFtZSBzcGVjaWZpY2F0aW9uCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1304,"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":1317,"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":1326,"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":1335,"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":1344,"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":1353,"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":1366,"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":1380,"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":1391,"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":1400,"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":1412,"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":1423,"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":1432,"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":1443,"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":1452,"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":1468,"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":1480,"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":1492,"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":1504,"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":1516,"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":1528,"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":1540,"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":1552,"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":1564,"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":1576,"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":1588,"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":1601,"slug":"sql-type-integer","name":"sql_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":"LyoqCiAqIENyZWF0ZSBhbiBJTlRFR0VSIGRhdGEgdHlwZS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1610,"slug":"sql-type-bigint","name":"sql_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":"LyoqCiAqIENyZWF0ZSBhIEJJR0lOVCBkYXRhIHR5cGUuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1619,"slug":"sql-type-smallint","name":"sql_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":"LyoqCiAqIENyZWF0ZSBhIFNNQUxMSU5UIGRhdGEgdHlwZS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1628,"slug":"sql-type-serial","name":"sql_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":"LyoqCiAqIENyZWF0ZSBhIFNFUklBTCAoYXV0by1pbmNyZW1lbnRpbmcgaW50ZWdlcikgZGF0YSB0eXBlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1637,"slug":"sql-type-bigserial","name":"sql_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":"LyoqCiAqIENyZWF0ZSBhIEJJR1NFUklBTCAoYXV0by1pbmNyZW1lbnRpbmcgYmlnaW50KSBkYXRhIHR5cGUuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1646,"slug":"sql-type-smallserial","name":"sql_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":"LyoqCiAqIENyZWF0ZSBhIFNNQUxMU0VSSUFMIChhdXRvLWluY3JlbWVudGluZyBzbWFsbGludCkgZGF0YSB0eXBlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1655,"slug":"sql-type-text","name":"sql_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":"LyoqCiAqIENyZWF0ZSBhIFRFWFQgZGF0YSB0eXBlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1666,"slug":"sql-type-varchar","name":"sql_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":"LyoqCiAqIENyZWF0ZSBhIFZBUkNIQVIgZGF0YSB0eXBlLgogKgogKiBAcGFyYW0gaW50ICRsZW5ndGggTWF4aW11bSBjaGFyYWN0ZXIgbGVuZ3RoCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1677,"slug":"sql-type-char","name":"sql_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":"LyoqCiAqIENyZWF0ZSBhIENIQVIgZGF0YSB0eXBlLgogKgogKiBAcGFyYW0gaW50ICRsZW5ndGggRml4ZWQgY2hhcmFjdGVyIGxlbmd0aAogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1686,"slug":"sql-type-boolean","name":"sql_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":"LyoqCiAqIENyZWF0ZSBhIEJPT0xFQU4gZGF0YSB0eXBlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1695,"slug":"sql-type-date","name":"sql_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":"LyoqCiAqIENyZWF0ZSBhIERBVEUgZGF0YSB0eXBlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1706,"slug":"sql-type-time","name":"sql_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":"LyoqCiAqIENyZWF0ZSBhIFRJTUUgZGF0YSB0eXBlLgogKgogKiBAcGFyYW0gbnVsbHxpbnQgJHByZWNpc2lvbiBGcmFjdGlvbmFsIHNlY29uZHMgcHJlY2lzaW9uCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1717,"slug":"sql-type-timestamp","name":"sql_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":"LyoqCiAqIENyZWF0ZSBhIFRJTUVTVEFNUCBkYXRhIHR5cGUuCiAqCiAqIEBwYXJhbSBudWxsfGludCAkcHJlY2lzaW9uIEZyYWN0aW9uYWwgc2Vjb25kcyBwcmVjaXNpb24KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1728,"slug":"sql-type-timestamptz","name":"sql_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":"LyoqCiAqIENyZWF0ZSBhIFRJTUVTVEFNUCBXSVRIIFRJTUUgWk9ORSBkYXRhIHR5cGUuCiAqCiAqIEBwYXJhbSBudWxsfGludCAkcHJlY2lzaW9uIEZyYWN0aW9uYWwgc2Vjb25kcyBwcmVjaXNpb24KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1737,"slug":"sql-type-interval","name":"sql_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":"LyoqCiAqIENyZWF0ZSBhbiBJTlRFUlZBTCBkYXRhIHR5cGUuCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1749,"slug":"sql-type-numeric","name":"sql_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":"LyoqCiAqIENyZWF0ZSBhIE5VTUVSSUMgZGF0YSB0eXBlLgogKgogKiBAcGFyYW0gbnVsbHxpbnQgJHByZWNpc2lvbiBUb3RhbCBudW1iZXIgb2YgZGlnaXRzCiAqIEBwYXJhbSBudWxsfGludCAkc2NhbGUgTnVtYmVyIG9mIGRpZ2l0cyBhZnRlciBkZWNpbWFsIHBvaW50CiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1761,"slug":"sql-type-decimal","name":"sql_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":"LyoqCiAqIENyZWF0ZSBhIERFQ0lNQUwgZGF0YSB0eXBlIChhbGlhcyBmb3IgTlVNRVJJQykuCiAqCiAqIEBwYXJhbSBudWxsfGludCAkcHJlY2lzaW9uIFRvdGFsIG51bWJlciBvZiBkaWdpdHMKICogQHBhcmFtIG51bGx8aW50ICRzY2FsZSBOdW1iZXIgb2YgZGlnaXRzIGFmdGVyIGRlY2ltYWwgcG9pbnQKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1770,"slug":"sql-type-real","name":"sql_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":"LyoqCiAqIENyZWF0ZSBhIFJFQUwgZGF0YSB0eXBlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1779,"slug":"sql-type-double","name":"sql_type_double","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":"LyoqCiAqIENyZWF0ZSBhIERPVUJMRSBQUkVDSVNJT04gZGF0YSB0eXBlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1788,"slug":"sql-type-uuid","name":"sql_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":1797,"slug":"sql-type-json","name":"sql_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":1806,"slug":"sql-type-jsonb","name":"sql_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":1815,"slug":"sql-type-bytea","name":"sql_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":"LyoqCiAqIENyZWF0ZSBhIEJZVEVBIGRhdGEgdHlwZS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1824,"slug":"sql-type-inet","name":"sql_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":"LyoqCiAqIENyZWF0ZSBhbiBJTkVUIGRhdGEgdHlwZS4KICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1833,"slug":"sql-type-cidr","name":"sql_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":"LyoqCiAqIENyZWF0ZSBhIENJRFIgZGF0YSB0eXBlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1842,"slug":"sql-type-macaddr","name":"sql_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":"LyoqCiAqIENyZWF0ZSBhIE1BQ0FERFIgZGF0YSB0eXBlLgogKi8="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1853,"slug":"sql-type-array","name":"sql_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":"LyoqCiAqIENyZWF0ZSBhbiBBUlJBWSBkYXRhIHR5cGUuCiAqCiAqIEBwYXJhbSBEYXRhVHlwZSAkZWxlbWVudFR5cGUgVGhlIHR5cGUgb2YgYXJyYXkgZWxlbWVudHMKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1869,"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":1884,"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":1895,"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":1908,"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":1919,"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":1954,"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+dGFibGUoJ3VzZXJzJyktPmNvbHVtbnMoY29sX2RlZignaWQnLCBzcWxfdHlwZV9zZXJpYWwoKSkpCiAqIEV4YW1wbGU6IGNyZWF0ZSgpLT5pbmRleCgnaWR4X2VtYWlsJyktPm9uKCd1c2VycycpLT5jb2x1bW5zKCdlbWFpbCcpCiAqLw=="},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":1983,"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":2017,"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+YWRkQ29sdW1uKGNvbF9kZWYoJ2VtYWlsJywgc3FsX3R5cGVfdGV4dCgpKSkKICogRXhhbXBsZTogYWx0ZXIoKS0+c2VxdWVuY2UoJ3VzZXJfaWRfc2VxJyktPnJlc3RhcnQoMTAwMCkKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2028,"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":2046,"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":2059,"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":2068,"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":2077,"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":2086,"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":2095,"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":2110,"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":2125,"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":2140,"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":2155,"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":2170,"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":2185,"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":2194,"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":2203,"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":2212,"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":2221,"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":2230,"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":2239,"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":2255,"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":2267,"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":2281,"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":2293,"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":2308,"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":2320,"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":2334,"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":2357,"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":2376,"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":2395,"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":2414,"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":2434,"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":2448,"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":2468,"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":2487,"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":2509,"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":"LyoqCiAqIENyZWF0ZXMgYSBuZXcgZnVuY3Rpb24gYXJndW1lbnQgZm9yIHVzZSBpbiBmdW5jdGlvbi9wcm9jZWR1cmUgZGVmaW5pdGlvbnMuCiAqCiAqIEV4YW1wbGU6IGZ1bmNfYXJnKHNxbF90eXBlX2ludGVnZXIoKSkKICogRXhhbXBsZTogZnVuY19hcmcoc3FsX3R5cGVfdGV4dCgpKS0+bmFtZWQoJ3VzZXJuYW1lJykKICogRXhhbXBsZTogZnVuY19hcmcoc3FsX3R5cGVfaW50ZWdlcigpKS0+bmFtZWQoJ2NvdW50JyktPmRlZmF1bHQoJzAnKQogKiBFeGFtcGxlOiBmdW5jX2FyZyhzcWxfdHlwZV90ZXh0KCkpLT5vdXQoKQogKgogKiBAcGFyYW0gRGF0YVR5cGUgJHR5cGUgVGhlIFBvc3RncmVTUUwgZGF0YSB0eXBlIGZvciB0aGUgYXJndW1lbnQKICoKICogQHJldHVybiBGdW5jdGlvbkFyZ3VtZW50IEJ1aWxkZXIgZm9yIGZ1bmN0aW9uIGFyZ3VtZW50IG9wdGlvbnMKICov"},{"repository_path":"src\/lib\/postgresql\/src\/Flow\/PostgreSql\/DSL\/functions.php","start_line_in_file":2528,"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":2547,"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":2571,"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":"LyoqCiAqIENyZWF0ZXMgYSB0eXBlIGF0dHJpYnV0ZSBmb3IgY29tcG9zaXRlIHR5cGVzLgogKgogKiBFeGFtcGxlOiB0eXBlX2F0dHIoJ25hbWUnLCBzcWxfdHlwZV90ZXh0KCkpCiAqIFByb2R1Y2VzOiBuYW1lIHRleHQKICoKICogRXhhbXBsZTogdHlwZV9hdHRyKCdkZXNjcmlwdGlvbicsIHNxbF90eXBlX3RleHQoKSktPmNvbGxhdGUoJ2VuX1VTJykKICogUHJvZHVjZXM6IGRlc2NyaXB0aW9uIHRleHQgQ09MTEFURSAiZW5fVVMiCiAqCiAqIEBwYXJhbSBzdHJpbmcgJG5hbWUgVGhlIGF0dHJpYnV0ZSBuYW1lCiAqIEBwYXJhbSBEYXRhVHlwZSAkdHlwZSBUaGUgYXR0cmlidXRlIHR5cGUKICoKICogQHJldHVybiBUeXBlQXR0cmlidXRlIFR5cGUgYXR0cmlidXRlIHZhbHVlIG9iamVjdAogKi8="},{"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\/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}]
\ No newline at end of file
diff --git a/web/landing/src/Flow/Website/Service/Markdown/LeagueCommonMarkConverterFactory.php b/web/landing/src/Flow/Website/Service/Markdown/LeagueCommonMarkConverterFactory.php
index d034cd29e..691c53679 100644
--- a/web/landing/src/Flow/Website/Service/Markdown/LeagueCommonMarkConverterFactory.php
+++ b/web/landing/src/Flow/Website/Service/Markdown/LeagueCommonMarkConverterFactory.php
@@ -13,6 +13,7 @@
use League\CommonMark\Extension\HeadingPermalink\HeadingPermalinkExtension;
use League\CommonMark\Extension\Mention\MentionExtension;
use League\CommonMark\Extension\Table\TableExtension;
+use League\CommonMark\Extension\TableOfContents\Node\TableOfContents;
use League\CommonMark\Extension\TableOfContents\TableOfContentsExtension;
use Symfony\Component\Asset\Packages;
use Symfony\Component\DependencyInjection\ParameterBag\ContainerBagInterface;
@@ -73,6 +74,7 @@ public function __invoke() : CommonMarkConverter
->addRenderer(FencedCode::class, new MermaidCodeRenderer($this->packages), 100)
->addRenderer(FencedCode::class, new FlowCodeRenderer(), 0)
->addRenderer(Link::class, new FlowLinkRenderer(), 0)
+ ->addRenderer(TableOfContents::class, new TableOfContentsRenderer(), 10)
->addEventListener(DocumentParsedEvent::class, new FlowVersionReplacer($this->parameters->get('flow_version')));
return $converter;
diff --git a/web/landing/src/Flow/Website/Service/Markdown/TableOfContentsRenderer.php b/web/landing/src/Flow/Website/Service/Markdown/TableOfContentsRenderer.php
new file mode 100644
index 000000000..b879c3852
--- /dev/null
+++ b/web/landing/src/Flow/Website/Service/Markdown/TableOfContentsRenderer.php
@@ -0,0 +1,55 @@
+renderNodes($node->children());
+
+ $tocList = new HtmlElement('ul', ['class' => 'table-of-contents'], $tocContent);
+
+ $arrow = new HtmlElement(
+ 'svg',
+ [
+ 'class' => 'toc-arrow',
+ 'xmlns' => 'http://www.w3.org/2000/svg',
+ 'width' => '20',
+ 'height' => '20',
+ 'viewBox' => '0 0 24 24',
+ 'fill' => 'none',
+ 'stroke' => 'currentColor',
+ 'stroke-width' => '2',
+ 'stroke-linecap' => 'round',
+ 'stroke-linejoin' => 'round',
+ ],
+ new HtmlElement('polyline', ['points' => '6 9 12 15 18 9'], '', true)
+ );
+
+ $header = new HtmlElement(
+ 'div',
+ ['class' => 'toc-header', 'data-action' => 'click->toc#toggle'],
+ new HtmlElement('span', [], 'Table of Contents') . $arrow
+ );
+
+ $content = new HtmlElement('div', ['class' => 'toc-content'], $tocList);
+
+ return new HtmlElement(
+ 'div',
+ ['class' => 'toc-wrapper', 'data-controller' => 'toc'],
+ $header . $content
+ );
+ }
+}
diff --git a/web/landing/templates/documentation/navigation_right.html.twig b/web/landing/templates/documentation/navigation_right.html.twig
index 580699d89..fda477e5c 100644
--- a/web/landing/templates/documentation/navigation_right.html.twig
+++ b/web/landing/templates/documentation/navigation_right.html.twig
@@ -89,7 +89,7 @@
Snappy
- PostgreSQL Query
+ Postgresql