Skip to content
Search

DSL References

DSL stands for Domain Specific Language. In Flow, the DSL is a set of small functions that wrap object construction so pipelines read top-to-bottom. See the examples for usage in context.

SCHEMA

/**
 * Create a factory for building ALTER statements.
 *
 * Provides a unified entry point for all ALTER operations:
 * - alter()->table() - ALTER TABLE
 * - alter()->index() - ALTER INDEX
 * - alter()->view() - ALTER VIEW
 * - alter()->materializedView() - ALTER MATERIALIZED VIEW
 * - alter()->sequence() - ALTER SEQUENCE
 * - alter()->schema() - ALTER SCHEMA
 * - alter()->role() - ALTER ROLE
 * - alter()->function() - ALTER FUNCTION
 * - alter()->procedure() - ALTER PROCEDURE
 * - alter()->trigger() - ALTER TRIGGER
 * - alter()->extension() - ALTER EXTENSION
 * - alter()->enumType() - ALTER TYPE (enum)
 * - alter()->domain() - ALTER DOMAIN
 *
 * Rename operations are also under alter():
 * - alter()->index('old')->renameTo('new')
 * - alter()->view('old')->renameTo('new')
 * - alter()->schema('old')->renameTo('new')
 * - alter()->role('old')->renameTo('new')
 * - alter()->trigger('old')->on('table')->renameTo('new')
 *
 * Example: alter()->table('users')->addColumn(col_def('email', column_type_text()))
 * Example: alter()->sequence('user_id_seq')->restart(1000)
 */
alter() : AlterFactory
/**
 * Create a factory for building CREATE statements.
 *
 * Provides a unified entry point for all CREATE operations:
 * - create()->table() - CREATE TABLE
 * - create()->tableAs() - CREATE TABLE AS
 * - create()->index() - CREATE INDEX
 * - create()->view() - CREATE VIEW
 * - create()->materializedView() - CREATE MATERIALIZED VIEW
 * - create()->sequence() - CREATE SEQUENCE
 * - create()->schema() - CREATE SCHEMA
 * - create()->role() - CREATE ROLE
 * - create()->function() - CREATE FUNCTION
 * - create()->procedure() - CREATE PROCEDURE
 * - create()->trigger() - CREATE TRIGGER
 * - create()->rule() - CREATE RULE
 * - create()->extension() - CREATE EXTENSION
 * - create()->compositeType() - CREATE TYPE (composite)
 * - create()->enumType() - CREATE TYPE (enum)
 * - create()->rangeType() - CREATE TYPE (range)
 * - create()->domain() - CREATE DOMAIN
 *
 * Example: create()->table('users')->columns(col_def('id', column_type_serial()))
 * Example: create()->index('idx_email')->on('users')->columns('email')
 */
create() : 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()
 */
drop() : DropFactory
/**
 * 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
 */
index_col(string $name) : IndexColumn
/**
 * 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
 */
index_expr(Expression $expression) : IndexColumn
/**
 * 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)
 */
refresh_materialized_view(string $name, ?string $schema) : RefreshMatViewOptionsStep
/**
 * Start building a REINDEX DATABASE statement.
 *
 * Use chainable methods: ->concurrently(), ->verbose(), ->tablespace()
 *
 * Example: reindex_database('mydb')->concurrently()
 *
 * @param string $name The database name
 */
reindex_database(string $name) : ReindexFinalStep
/**
 * 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)
 */
reindex_index(string $name) : ReindexFinalStep
/**
 * Start building a REINDEX SCHEMA statement.
 *
 * Use chainable methods: ->concurrently(), ->verbose(), ->tablespace()
 *
 * Example: reindex_schema('public')->concurrently()
 *
 * @param string $name The schema name
 */
reindex_schema(string $name) : ReindexFinalStep
/**
 * 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)
 */
reindex_table(string $name) : ReindexFinalStep

HELPER

/**
 * Create an aggregate function call (COUNT, SUM, AVG, etc.).
 *
 * @param string $name Aggregate function name
 * @param list<Expression|string> $args Function arguments
 * @param bool $distinct Use DISTINCT modifier
 */
agg(string $name, array $args, bool $distinct) : AggregateCall
/**
 * Create AVG aggregate.
 */
agg_avg(Expression|string $expr, bool $distinct) : AggregateCall
/**
 * Create COUNT(*) aggregate.
 */
agg_count(Expression|string|null $expr, bool $distinct) : AggregateCall
/**
 * Create MAX aggregate.
 */
agg_max(Expression|string $expr) : AggregateCall
/**
 * Create MIN aggregate.
 */
agg_min(Expression|string $expr) : AggregateCall
/**
 * Create SUM aggregate.
 */
agg_sum(Expression|string $expr, bool $distinct) : AggregateCall
/**
 * Create an ALL condition with a subquery or array expression.
 *
 * Example: all_(col('id'), ComparisonOperator::EQ, select(col('user_id'))->from(table('orders')))
 * Example: all_(col('value'), ComparisonOperator::GT, col('thresholds'))
 */
all_(Expression|string $left, ComparisonOperator $operator, Expression|SelectFinalStep $arrayOrSubquery) : All
/**
 * Create an ANALYZE builder.
 *
 * Example: analyze()->table('users')
 * Produces: ANALYZE users
 */
analyze() : AnalyzeFinalStep
/**
 * Combine conditions with AND.
 *
 * @param Condition ...$conditions Conditions to combine
 */
and_(Condition $conditions) : AndCondition
/**
 * Create an ANY condition with a subquery or array expression.
 *
 * Example: any_(col('id'), ComparisonOperator::EQ, select(col('user_id'))->from(table('orders')))
 * Example: any_(col('attnum', 'a'), ComparisonOperator::EQ, col('conkey', 'con'))
 */
any_(Expression|string $left, ComparisonOperator $operator, Expression|SelectFinalStep $arrayOrSubquery) : Any
/**
 * Create an array is contained by condition (<@).
 *
 * Example: array_contained_by(col('tags'), array_expr([literal('sale'), literal('featured'), literal('new')]))
 * Produces: tags <@ ARRAY['sale', 'featured', 'new']
 */
array_contained_by(Expression|string $left, Expression|string $right) : OperatorCondition
/**
 * Create an array contains condition (@>).
 *
 * Example: array_contains(col('tags'), array_expr([literal('sale')]))
 * Produces: tags @> ARRAY['sale']
 */
array_contains(Expression|string $left, Expression|string $right) : OperatorCondition
/**
 * Create an array expression.
 *
 * @param list<Expression|string> $elements Array elements
 */
array_expr(array $elements) : ArrayExpression
/**
 * Create an array overlap condition (&&).
 *
 * Example: array_overlap(col('tags'), array_expr([literal('sale'), literal('featured')]))
 * Produces: tags && ARRAY['sale', 'featured']
 */
array_overlap(Expression|string $left, Expression|string $right) : OperatorCondition
/**
 * Create an ORDER BY item with ASC direction.
 */
asc(Expression|string $expr, NullsPosition $nulls) : OrderBy
/**
 * Create a BEGIN transaction builder.
 *
 * Example: begin()->isolationLevel(IsolationLevel::SERIALIZABLE)->readOnly()
 * Produces: BEGIN ISOLATION LEVEL SERIALIZABLE READ ONLY
 */
begin() : BeginOptionsStep
/**
 * Create a BETWEEN condition.
 */
between(Expression|string $expr, Expression|string $low, Expression|string $high, bool $not) : Between
/**
 * Create a binary expression (left op right).
 */
binary_expr(Expression|string $left, string $operator, Expression|string $right) : BinaryExpression
/**
 * Create an optimized bulk INSERT query for high-performance multi-row inserts.
 *
 * Unlike insert() which uses immutable builder patterns (O(n²) for n rows),
 * this function generates SQL directly using string operations (O(n) complexity).
 *
 * @param string $table Table name
 * @param list<string> $columns Column names
 * @param int $rowCount Number of rows to insert
 */
bulk_insert(string $table, array $columns, int $rowCount) : BulkInsert
/**
 * 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
 */
call(string $procedure) : CallFinalStep
/**
 * Create a CASE expression.
 *
 * @param non-empty-list<WhenClause> $whenClauses WHEN clauses
 * @param null|Expression|string $elseResult ELSE result (optional)
 * @param null|Expression|string $operand CASE operand for simple CASE (optional)
 */
case_when(array $whenClauses, Expression|string|null $elseResult, Expression|string|null $operand) : CaseExpression
/**
 * Create a type cast expression.
 *
 * @param Expression|string $expr Expression to cast
 * @param ColumnType $dataType Target data type (use column_type_* functions)
 */
cast(Expression|string $expr, ColumnType $dataType) : TypeCast
/**
 * @param list<Schema> $schemas
 */
catalog(array $schemas) : Catalog
/**
 * @param null|ExecutionOrderStrategy<\Flow\PostgreSql\Schema\Table> $tableOrderStrategy
 */
catalog_comparator(?RenameStrategy $renameStrategy, ?ViewDependencyResolver $viewDependencyResolver, ?ExecutionOrderStrategy $tableOrderStrategy) : CatalogComparator
/**
 * @param ?list<string> $schemaNames
 * @param list<string> $excludeTables
 */
client_catalog_provider(Client $client, ?array $schemaNames, array $excludeTables) : CatalogProvider
/**
 * Close a cursor.
 *
 * Example: close_cursor('my_cursor')
 * Produces: CLOSE my_cursor
 *
 * Example: close_cursor() - closes all cursors
 * Produces: CLOSE ALL
 *
 * @param null|string $cursorName Cursor to close, or null to close all
 */
close_cursor(?string $cursorName) : CloseCursorFinalStep
/**
 * Create a CLUSTER builder.
 *
 * Example: cluster()->table('users')->using('idx_users_pkey')
 * Produces: CLUSTER users USING idx_users_pkey
 */
cluster() : ClusterFinalStep
/**
 * Create a COALESCE expression.
 *
 * @param Expression|string ...$expressions Expressions to coalesce
 */
coalesce(Expression|string $expressions) : Coalesce
/**
 * 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
 */
col(string $column, ?string $table, ?string $schema) : Column
/**
 * Create a column definition for CREATE TABLE.
 *
 * @param string $name Column name
 * @param ColumnType $type Column data type
 */
column(string $name, ColumnType $type) : ColumnDefinition
/**
 * Create an array data type from an element type.
 */
column_type_array(ColumnType $elementType) : ColumnType
/**
 * Create a char data type with length constraint.
 */
column_type_char(int $length) : ColumnType
/**
 * Create a custom data type.
 *
 * @param string $typeName Type name
 * @param null|string $schema Optional schema name
 */
column_type_custom(string $typeName, ?string $schema) : ColumnType
/**
 * Create a decimal data type with optional precision and scale.
 */
column_type_decimal(?int $precision, ?int $scale) : ColumnType
/**
 * Parse a PostgreSQL type string into a ColumnType.
 *
 * Handles all PostgreSQL type syntax including precision, arrays, and schema-qualified types.
 *
 * @param string $typeName PostgreSQL type string (e.g., 'integer', 'character varying(255)', 'text[]')
 */
column_type_from_string(string $typeName) : ColumnType
/**
 * Create a numeric data type with optional precision and scale.
 */
column_type_numeric(?int $precision, ?int $scale) : ColumnType
/**
 * Create a time data type with optional precision.
 */
column_type_time(?int $precision) : ColumnType
/**
 * Create a timestamp with time zone data type with optional precision.
 */
column_type_timestamptz(?int $precision) : ColumnType
/**
 * 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)
 */
comment(CommentTarget $target, string $name) : CommentFinalStep
/**
 * Create a COMMIT transaction builder.
 *
 * Example: commit()->andChain()
 * Produces: COMMIT AND CHAIN
 */
commit() : CommitOptionsStep
/**
 * Create a COMMIT PREPARED builder.
 *
 * Example: commit_prepared('my_transaction')
 * Produces: COMMIT PREPARED 'my_transaction'
 */
commit_prepared(string $transactionId) : PreparedTransactionFinalStep
/**
 * Concatenate expressions with the || operator.
 *
 * Example: concat(col('schema'), literal('.'), col('table'))
 * Produces: schema || '.' || table
 *
 * @param Expression|string ...$expressions At least 2 expressions to concatenate
 */
concat(Expression|string $expressions) : BinaryExpression
/**
 * Create a condition builder for fluent condition composition.
 *
 * This builder allows incremental condition building with a fluent API:
 *
 * ```php
 * $builder = conditions();
 *
 * if ($hasFilter) {
 *     $builder = $builder->and(eq(col('status'), literal('active')));
 * }
 *
 * if (!$builder->isEmpty()) {
 *     $query = select()->from(table('users'))->where($builder);
 * }
 * ```
 */
conditions() : ConditionBuilder
/**
 * Create a conflict target for ON CONFLICT (columns).
 *
 * @param list<string> $columns Columns that define uniqueness
 */
conflict_columns(array $columns) : ConflictTarget
/**
 * Create a conflict target for ON CONFLICT ON CONSTRAINT.
 */
conflict_constraint(string $name) : ConflictTarget
/**
 * @template T of object
 *
 * @param class-string<T> $class
 *
 * @return ConstructorMapper<T>
 */
constructor_mapper(string $class) : ConstructorMapper
/**
 * 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')
 */
copy() : CopyFactory
/**
 * Create a CTE (Common Table Expression).
 *
 * @param string $name CTE name
 * @param SelectFinalStep $query CTE query
 * @param array<string> $columnNames Column aliases (optional)
 * @param CTEMaterialization $materialization Materialization hint
 */
cte(string $name, SelectFinalStep $query, array $columnNames, CTEMaterialization $materialization, bool $recursive) : CTE
/**
 * SQL standard CURRENT_DATE function.
 *
 * Returns the current date (at the start of the transaction).
 * Useful as a column default value or in SELECT queries.
 *
 * Example: column('birth_date', column_type_date())->default(current_date())
 * Example: select()->select(current_date()->as('today'))
 */
current_date() : SQLValueFunctionExpression
/**
 * SQL standard CURRENT_TIME function.
 *
 * Returns the current time (at the start of the transaction).
 * Useful as a column default value or in SELECT queries.
 *
 * Example: column('start_time', column_type_time())->default(current_time())
 * Example: select()->select(current_time()->as('now_time'))
 */
current_time() : SQLValueFunctionExpression
/**
 * SQL standard CURRENT_TIMESTAMP function.
 *
 * Returns the current date and time (at the start of the transaction).
 * Useful as a column default value or in SELECT queries.
 *
 * Example: column('created_at', column_type_timestamp())->default(current_timestamp())
 * Example: select()->select(current_timestamp()->as('now'))
 */
current_timestamp() : SQLValueFunctionExpression
/**
 * Declare a server-side cursor for a query.
 *
 * Cursors must be declared within a transaction and provide memory-efficient
 * iteration over large result sets via FETCH commands.
 *
 * Example with query builder:
 *   declare_cursor('my_cursor', select(star())->from(table('users')))->noScroll()
 *   Produces: DECLARE my_cursor NO SCROLL CURSOR FOR SELECT * FROM users
 *
 * Example with raw SQL:
 *   declare_cursor('my_cursor', 'SELECT * FROM users WHERE active = true')->withHold()
 *   Produces: DECLARE my_cursor NO SCROLL CURSOR WITH HOLD FOR SELECT * FROM users WHERE active = true
 *
 * @param string $cursorName Unique cursor name
 * @param SelectFinalStep|Sql|string $query Query to iterate over
 */
declare_cursor(string $cursorName, SelectFinalStep|Sql|string $query) : DeclareCursorOptionsStep
/**
 * Create a new DELETE query builder.
 */
delete() : DeleteFromStep
/**
 * Create a derived table (subquery in FROM clause).
 */
derived(SelectFinalStep $query, string $alias) : DerivedTable
/**
 * Create an ORDER BY item with DESC direction.
 */
desc(Expression|string $expr, NullsPosition $nulls) : OrderBy
/**
 * Create a DISCARD builder.
 *
 * Example: discard(DiscardType::ALL)
 * Produces: DISCARD ALL
 *
 * @param DiscardType $type Type of resources to discard (ALL, PLANS, SEQUENCES, TEMP)
 */
discard(DiscardType $type) : DiscardFinalStep
/**
 * Create an IS DISTINCT FROM condition.
 */
distinct_from(Expression|string $left, Expression|string $right, bool $not) : IsDistinctFrom
/**
 * 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
 */
do_block(string $code) : DoFinalStep
/**
 * 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
 */
drop_owned(string $roles) : DropOwnedFinalStep
/**
 * Create an equality comparison (column = value).
 */
eq(Expression|string $left, Expression|string $right) : Comparison
/**
 * Create an EXISTS condition.
 */
exists(SelectFinalStep $subquery) : Exists
/**
 * 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
 */
explain(SelectFinalStep|InsertBuilder|UpdateBuilder|DeleteBuilder $query) : ExplainFinalStep
/**
 * Fetch rows from a cursor.
 *
 * Example: fetch('my_cursor')->forward(100)
 * Produces: FETCH FORWARD 100 my_cursor
 *
 * Example: fetch('my_cursor')->all()
 * Produces: FETCH ALL my_cursor
 *
 * @param string $cursorName Cursor to fetch from
 */
fetch(string $cursorName) : FetchCursorBuilder
/**
 * Create a FOREIGN KEY constraint.
 *
 * @param list<string> $columns Local columns
 * @param string $referenceTable Referenced table
 * @param list<string> $referenceColumns Referenced columns (defaults to same as $columns if empty)
 */
foreign_key(array $columns, string $referenceTable, array $referenceColumns) : ForeignKeyConstraint
/**
 * Create a FOR SHARE locking clause.
 *
 * @param list<string> $tables Tables to lock (empty for all)
 */
for_share(array $tables) : LockingClause
/**
 * Create a FOR UPDATE locking clause.
 *
 * @param list<string> $tables Tables to lock (empty for all)
 */
for_update(array $tables) : LockingClause
/**
 * Create a frame bound for N FOLLOWING.
 */
frame_following(Expression|string $offset) : FrameBound
/**
 * Create a frame bound for N PRECEDING.
 */
frame_preceding(Expression|string $offset) : FrameBound
/**
 * Create a function call expression.
 *
 * @param string $name Function name (can include schema like "pg_catalog.now")
 * @param list<Expression|string> $args Function arguments
 */
func(string $name, array $args) : FunctionCall
/**
 * Creates a new function argument for use in function/procedure definitions.
 *
 * Example: func_arg(column_type_integer())
 * Example: func_arg(column_type_text())->named('username')
 * Example: func_arg(column_type_integer())->named('count')->default('0')
 * Example: func_arg(column_type_text())->out()
 *
 * @param ColumnType $type The PostgreSQL data type for the argument
 *
 * @return FunctionArgument Builder for function argument options
 */
func_arg(ColumnType $type) : FunctionArgument
/**
 * Create a greater-than-or-equal comparison (column >= value).
 */
ge(Expression|string $left, Expression|string $right) : Comparison
/**
 * 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
 */
grant(TablePrivilege|string $privileges) : GrantOnStep
/**
 * 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
 */
grant_role(string $roles) : GrantRoleToStep
/**
 * Create a GREATEST expression.
 *
 * @param Expression|string ...$expressions Expressions to compare
 */
greatest(Expression|string $expressions) : Greatest
/**
 * Create a greater-than comparison (column > value).
 */
gt(Expression|string $left, Expression|string $right) : Comparison
/**
 * Create a new INSERT query builder.
 */
insert() : InsertIntoStep
/**
 * Create an IN condition.
 *
 * @param Expression|string $expr Expression to check
 * @param list<Expression> $values List of values (must be non-empty)
 *
 * @throws \InvalidArgumentException when values array is empty
 */
in_(Expression|string $expr, array $values) : In
/**
 * Create an IS NULL condition.
 */
is_null(Expression|string $expr, bool $not) : IsNull
/**
 * Wrap an expression as a boolean condition for use in WHERE/HAVING/JOIN ON.
 *
 * Example: is_true(col('is_active')) — uses a boolean column in WHERE clause.
 */
is_true(Expression|string $expr) : BooleanCondition
/**
 * 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}'
 */
json_contained_by(Expression|string $left, Expression|string $right) : OperatorCondition
/**
 * Create a JSONB contains condition (@>).
 *
 * Example: json_contains(col('metadata'), literal_json('{"category": "electronics"}'))
 * Produces: metadata @> '{"category": "electronics"}'
 */
json_contains(Expression|string $left, Expression|string $right) : OperatorCondition
/**
 * Create a JSONB key exists condition (?).
 *
 * Example: json_exists(col('metadata'), literal_string('category'))
 * Produces: metadata ? 'category'
 */
json_exists(Expression|string $expr, Expression|string $key) : OperatorCondition
/**
 * Create a JSONB all keys exist condition (?&).
 *
 * Example: json_exists_all(col('metadata'), array_expr([literal('category'), literal('name')]))
 * Produces: metadata ?& array['category', 'name']
 */
json_exists_all(Expression|string $expr, Expression|string $keys) : OperatorCondition
/**
 * Create a JSONB any key exists condition (?|).
 *
 * Example: json_exists_any(col('metadata'), array_expr([literal('category'), literal('name')]))
 * Produces: metadata ?| array['category', 'name']
 */
json_exists_any(Expression|string $expr, Expression|string $keys) : OperatorCondition
/**
 * Create a JSON field access expression (->).
 * Returns JSON.
 *
 * Example: json_get(col('metadata'), literal_string('category'))
 * Produces: metadata -> 'category'
 */
json_get(Expression|string $expr, Expression|string $key) : BinaryExpression
/**
 * Create a JSON field access expression (->>).
 * Returns text.
 *
 * Example: json_get_text(col('metadata'), literal_string('name'))
 * Produces: metadata ->> 'name'
 */
json_get_text(Expression|string $expr, Expression|string $key) : BinaryExpression
/**
 * Create a JSON path access expression (#>).
 * Returns JSON.
 *
 * Example: json_path(col('metadata'), literal_string('{category,name}'))
 * Produces: metadata #> '{category,name}'
 */
json_path(Expression|string $expr, Expression|string $path) : BinaryExpression
/**
 * Create a JSON path access expression (#>>).
 * Returns text.
 *
 * Example: json_path_text(col('metadata'), literal_string('{category,name}'))
 * Produces: metadata #>> '{category,name}'
 */
json_path_text(Expression|string $expr, Expression|string $path) : BinaryExpression
/**
 * Create a LATERAL subquery.
 *
 * @param TableReference $reference The subquery or table function reference
 */
lateral(TableReference $reference) : Lateral
/**
 * Create a less-than-or-equal comparison (column <= value).
 */
le(Expression|string $left, Expression|string $right) : Comparison
/**
 * Create a LEAST expression.
 *
 * @param Expression|string ...$expressions Expressions to compare
 */
least(Expression|string $expressions) : Least
/**
 * Create a LIKE condition.
 */
like(Expression|string $expr, Expression|string $pattern, bool $caseInsensitive, bool $negated) : Like
/**
 * Create a LISTEN statement to subscribe the current session to a notification channel.
 *
 * Usage:
 *   listen('my_channel')->toSql()  // LISTEN my_channel
 */
listen(string $channel) : ListenFinalStep
/**
 * 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
 */
literal(string|int|float|bool|null $value) : Literal
/**
 * Create a locking clause (FOR UPDATE, FOR SHARE, etc.).
 *
 * @param LockStrength $strength Lock strength
 * @param list<string> $tables Tables to lock (empty for all)
 * @param LockWaitPolicy $waitPolicy Wait policy
 */
lock_for(LockStrength $strength, array $tables, LockWaitPolicy $waitPolicy) : LockingClause
/**
 * Create a LOCK TABLE builder.
 *
 * Example: lock_table('users', 'orders')->accessExclusive()
 * Produces: LOCK TABLE users, orders IN ACCESS EXCLUSIVE MODE
 */
lock_table(string $tables) : LockFinalStep
/**
 * Create a less-than comparison (column < value).
 */
lt(Expression|string $left, Expression|string $right) : Comparison
/**
 * Create a new MERGE query builder.
 *
 * @param string $table Target table name
 * @param null|string $alias Optional table alias
 */
merge(string $table, ?string $alias) : MergeUsingStep
/**
 * Create a not-equal comparison (column != value).
 */
ne(Expression|string $left, Expression|string $right) : Comparison
/**
 * Create a NOTIFY statement to send a notification on a channel, optionally with a payload.
 *
 * Usage:
 *   notify('my_channel')->toSql()                           // NOTIFY my_channel
 *   notify('my_channel')->withPayload('hello')->toSql()     // NOTIFY my_channel, 'hello'
 */
notify(string $channel) : NotifyFinalStep
/**
 * Negate a condition or expression with NOT.
 *
 * Accepts both Condition and Expression — NOT always produces a boolean result.
 * Can be used in WHERE clauses and SELECT lists (via ->as('alias')).
 */
not_(Expression|string $expression) : NotCondition
/**
 * Create a NOT LIKE condition.
 *
 * Example: not_like(col('name'), literal('pg_%'))
 * Produces: name NOT LIKE 'pg_%'
 */
not_like(Expression|string $expr, Expression|string $pattern, bool $caseInsensitive) : Like
/**
 * Create a POSIX regex not match condition (!~*).
 * Case-insensitive.
 *
 * Example: not_regex_imatch(col('email'), literal_string('.*@spam\\.com'))
 *
 * Produces: email !~* '.*@spam\.com'
 */
not_regex_imatch(Expression|string $expr, Expression|string $pattern) : OperatorCondition
/**
 * Create a POSIX regex not match condition (!~).
 * Case-sensitive.
 *
 * Example: not_regex_match(col('email'), literal_string('.*@spam\\.com'))
 *
 * Produces: email !~ '.*@spam\.com'
 */
not_regex_match(Expression|string $expr, Expression|string $pattern) : OperatorCondition
/**
 * Create a NULLIF expression.
 */
nullif(Expression|string $expr1, Expression|string $expr2) : NullIf
/**
 * Create an ON CONFLICT DO NOTHING clause.
 */
on_conflict_nothing(?ConflictTarget $target) : OnConflictClause
/**
 * Create an ON CONFLICT DO UPDATE clause.
 *
 * @param ConflictTarget $target Conflict target (columns or constraint)
 * @param array<string, Expression|string> $updates Column updates
 */
on_conflict_update(ConflictTarget $target, array $updates) : OnConflictClause
/**
 * Create an ORDER BY item.
 */
order_by(Expression|string $expr, SortDirection $direction, NullsPosition $nulls) : OrderBy
/**
 * Combine conditions with OR.
 *
 * @param Condition ...$conditions Conditions to combine
 */
or_(Condition $conditions) : OrCondition
/**
 * Create a positional parameter ($1, $2, etc.).
 */
param(int $position) : Parameter
/**
 * @return list<Parameter>
 */
parameters(int $count, int $startAt) : array
/**
 * Create a SelectFinalStep from a raw SQL SELECT string.
 */
parsed_select(string $sql) : ParsedSelect
/**
 * Create a PostgreSQL client using ext-pgsql.
 *
 * The client connects immediately and is ready to execute queries.
 *
 * @param Client\ConnectionParameters $params Connection parameters
 * @param null|ValueConverters $valueConverters Custom type converters (optional)
 * @param null|Context $context Base mapper Context — the Client enriches it with sql/parameters/self per query before handing it to RowMapper::map()
 *
 * @throws ConnectionException If connection fails
 */
pgsql_client(ConnectionParameters $params, ?ValueConverters $valueConverters, ?Context $context) : Client
/**
 * Create connection parameters from a connection string.
 *
 * Accepts libpq-style connection strings:
 * - Key-value format: "host=localhost port=5432 dbname=mydb user=myuser password=secret"
 * - URI format: "postgresql://user:password@localhost:5432/dbname"
 *
 * @example
 * $params = pgsql_connection('host=localhost dbname=mydb');
 * $params = pgsql_connection('postgresql://user:pass@localhost/mydb');
 */
pgsql_connection(string $connectionString) : ConnectionParameters
/**
 * Create connection parameters from a DSN string.
 *
 * Parses standard PostgreSQL DSN format commonly used in environment variables
 * (e.g., DATABASE_URL). Supports postgres://, postgresql://, and pgsql:// schemes.
 *
 * @param string $dsn DSN string in format: postgres://user:password@host:port/database?options
 *
 * @throws Client\DsnParserException If the DSN cannot be parsed
 *
 * @example
 * $params = pgsql_connection_dsn('postgres://myuser:secret@localhost:5432/mydb');
 * $params = pgsql_connection_dsn('postgresql://user:[email protected]/app?sslmode=require');
 * $params = pgsql_connection_dsn('pgsql://user:pass@localhost/mydb'); // Symfony/Doctrine format
 * $params = pgsql_connection_dsn(getenv('DATABASE_URL'));
 */
pgsql_connection_dsn(string $dsn) : ConnectionParameters
/**
 * Create connection parameters from individual values.
 *
 * Allows specifying connection parameters individually for better type safety
 * and IDE support.
 *
 * @param string $database Database name (required)
 * @param string $host Hostname (default: localhost)
 * @param int $port Port number (default: 5432)
 * @param null|string $user Username (optional)
 * @param null|string $password Password (optional)
 * @param array<string, string> $options Additional libpq options
 *
 * @example
 * $params = pgsql_connection_params(
 *     database: 'mydb',
 *     host: 'localhost',
 *     user: 'myuser',
 *     password: 'secret',
 * );
 */
pgsql_connection_params(string $database, string $host, int $port, ?string $user, ?string $password, array $options) : ConnectionParameters
/**
 * Create a RowMapper Context seeded with user-supplied key/value data and an optional Catalog.
 *
 * The Context is later enriched with a Query (sql + parameters) and the executing Client by the
 * PostgreSQL Client before being handed to RowMapper::map().
 *
 * @param array<string, mixed> $data User-supplied key/value pairs
 */
postgresql_context(array $data, ?Catalog $catalog) : Context
/**
 * Create telemetry configuration for PostgreSQL client.
 *
 * Bundles telemetry instance, clock, and options needed to instrument a PostgreSQL client.
 *
 * @param Telemetry $telemetry The telemetry instance
 * @param ClockInterface $clock Clock for timestamps
 * @param null|PostgreSqlTelemetryOptions $options Telemetry options (default: all enabled)
 *
 * @example
 * $config = postgresql_telemetry_config(
 *     telemetry(resource(['service.name' => 'my-app'])),
 *     new SystemClock(),
 * );
 */
postgresql_telemetry_config(Telemetry $telemetry, ClockInterface $clock, ?PostgreSqlTelemetryOptions $options) : PostgreSqlTelemetryConfig
/**
 * Create telemetry options for PostgreSQL client instrumentation.
 *
 * Controls which telemetry signals (traces, metrics, logs) are enabled
 * and how query information is captured.
 *
 * @param bool $traceQueries Create spans for query execution (default: true)
 * @param bool $traceTransactions Create spans for transactions (default: true)
 * @param bool $collectMetrics Collect duration and row count metrics (default: true)
 * @param bool $logQueries Log executed queries (default: false)
 * @param null|int $maxQueryLength Maximum query text length in telemetry (default: 1000, null = unlimited)
 * @param bool $includeParameters Include query parameters in telemetry (default: false, security consideration)
 *
 * @example
 * // Default options (traces and metrics enabled)
 * $options = postgresql_telemetry_options();
 *
 * // Enable query logging
 * $options = postgresql_telemetry_options(logQueries: true);
 *
 * // Disable all but metrics
 * $options = postgresql_telemetry_options(
 *     traceQueries: false,
 *     traceTransactions: false,
 *     collectMetrics: true,
 * );
 */
postgresql_telemetry_options(bool $traceQueries, bool $traceTransactions, bool $collectMetrics, bool $logQueries, ?int $maxQueryLength, bool $includeParameters, ?int $maxParameters, ?int $maxParameterLength) : PostgreSqlTelemetryOptions
/**
 * Create a PREPARE TRANSACTION builder.
 *
 * Example: prepare_transaction('my_transaction')
 * Produces: PREPARE TRANSACTION 'my_transaction'
 */
prepare_transaction(string $transactionId) : PreparedTransactionFinalStep
/**
 * Create a PRIMARY KEY constraint.
 *
 * @param string ...$columns Columns that form the primary key
 */
primary_key(string $columns) : PrimaryKeyConstraint
/**
 * 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
 */
reassign_owned(string $roles) : ReassignOwnedToStep
/**
 * Create a POSIX regex match condition (~*).
 * Case-insensitive.
 *
 * Example: regex_imatch(col('email'), literal_string('.*@gmail\\.com'))
 *
 * Produces: email ~* '.*@gmail\.com'
 */
regex_imatch(Expression|string $expr, Expression|string $pattern) : OperatorCondition
/**
 * Create a POSIX regex match condition (~).
 * Case-sensitive.
 *
 * Example: regex_match(col('email'), literal_string('.*@gmail\\.com'))
 *
 * Produces: email ~ '.*@gmail\.com'
 */
regex_match(Expression|string $expr, Expression|string $pattern) : OperatorCondition
/**
 * Release a SAVEPOINT.
 *
 * Example: release_savepoint('my_savepoint')
 * Produces: RELEASE my_savepoint
 */
release_savepoint(string $name) : SavepointFinalStep
/**
 * Create a RESET ROLE builder.
 *
 * Example: reset_role()
 * Produces: RESET ROLE
 *
 * @return ResetRoleFinalStep Builder for reset role
 */
reset_role() : ResetRoleFinalStep
/**
 * Create a RETURNING clause.
 *
 * @param Expression|string ...$expressions Expressions to return
 */
returning(Expression|string $expressions) : ReturningClause
/**
 * 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
 */
revoke(TablePrivilege|string $privileges) : RevokeOnStep
/**
 * 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
 */
revoke_role(string $roles) : RevokeRoleFromStep
/**
 * Create a ROLLBACK transaction builder.
 *
 * Example: rollback()->toSavepoint('my_savepoint')
 * Produces: ROLLBACK TO SAVEPOINT my_savepoint
 */
rollback() : RollbackOptionsStep
/**
 * Create a ROLLBACK PREPARED builder.
 *
 * Example: rollback_prepared('my_transaction')
 * Produces: ROLLBACK PREPARED 'my_transaction'
 */
rollback_prepared(string $transactionId) : PreparedTransactionFinalStep
/**
 * Create a row expression.
 *
 * @param list<Expression|string> $elements Row elements
 */
row_expr(array $elements) : RowExpression
/**
 * Create a SAVEPOINT.
 *
 * Example: savepoint('my_savepoint')
 * Produces: SAVEPOINT my_savepoint
 */
savepoint(string $name) : SavepointFinalStep
/**
 * @param list<SchemaTable> $tables
 * @param list<SchemaSequence> $sequences
 * @param list<SchemaView> $views
 * @param list<SchemaMaterializedView> $materializedViews
 * @param list<SchemaFunction> $functions
 * @param list<SchemaProcedure> $procedures
 * @param list<SchemaDomain> $domains
 * @param list<SchemaExtension> $extensions
 */
schema(string $name, array $tables, array $sequences, array $views, array $materializedViews, array $functions, array $procedures, array $domains, array $extensions) : Schema
schema_check(string $expression, ?string $name, bool $noInherit) : CheckConstraint
schema_column(string $name, ColumnType $type, bool $nullable, Expression|string|int|float|bool|null $default, bool $isIdentity, ?IdentityGeneration $identityGeneration, bool $isGenerated, ?string $generationExpression, ?int $ordinalPosition) : Column
schema_column_char(string $name, int $length, bool $nullable, Expression|string|int|float|bool|null $default) : Column
schema_column_cidr(string $name, bool $nullable, Expression|string|int|float|bool|null $default) : Column
schema_column_date(string $name, bool $nullable, Expression|string|int|float|bool|null $default) : Column
schema_column_inet(string $name, bool $nullable, Expression|string|int|float|bool|null $default) : Column
schema_column_json(string $name, bool $nullable, Expression|string|int|float|bool|null $default) : Column
schema_column_numeric(string $name, ?int $precision, ?int $scale, bool $nullable, Expression|string|int|float|bool|null $default) : Column
schema_column_real(string $name, bool $nullable, Expression|string|int|float|bool|null $default) : Column
schema_column_text(string $name, bool $nullable, Expression|string|int|float|bool|null $default) : Column
schema_column_time(string $name, ?int $precision, bool $nullable, Expression|string|int|float|bool|null $default) : Column
schema_column_timestamp(string $name, ?int $precision, bool $nullable, Expression|string|int|float|bool|null $default) : Column
schema_column_uuid(string $name, bool $nullable, Expression|string|int|float|bool|null $default) : Column
schema_column_varchar(string $name, int $length, bool $nullable, Expression|string|int|float|bool|null $default) : Column
/**
 * @param list<SchemaCheckConstraint> $checkConstraints
 */
schema_domain(string $name, ColumnType $baseType, bool $nullable, Expression|string|int|float|bool|null $default, array $checkConstraints) : Domain
/**
 * @param non-empty-list<string> $columns
 * @param non-empty-list<string> $referenceColumns
 */
schema_foreign_key(array $columns, string $referenceTable, array $referenceColumns, ?string $name, string $referenceSchema, ReferentialAction $onUpdate, ReferentialAction $onDelete, bool $deferrable, bool $initiallyDeferred) : ForeignKey
/**
 * @param list<string> $argumentTypes
 */
schema_function(string $name, string $returnType, array $argumentTypes, string $language, ?string $definition, bool $isStrict, ?FunctionVolatility $volatility) : Func
/**
 * @param non-empty-list<string> $columns
 */
schema_index(string $name, array $columns, bool $unique, IndexMethod $method, bool $primary, ?string $predicate) : Index
/**
 * @param list<SchemaIndex> $indexes
 */
schema_materialized_view(string $name, string $definition, array $indexes) : MaterializedView
/**
 * @param non-empty-list<string> $columns
 */
schema_primary_key(array $columns, ?string $name) : PrimaryKey
/**
 * @param list<string> $argumentTypes
 */
schema_procedure(string $name, array $argumentTypes, string $language, ?string $definition) : Procedure
schema_sequence(string $name, string $dataType, string|int $startValue, string|int $minValue, string|int|null $maxValue, string|int $incrementBy, bool $cycle, string|int $cacheValue, ?string $ownedByTable, ?string $ownedByColumn) : Sequence
/**
 * @param non-empty-list<SchemaColumn> $columns
 * @param list<SchemaIndex> $indexes
 * @param list<SchemaForeignKey> $foreignKeys
 * @param list<SchemaUniqueConstraint> $uniqueConstraints
 * @param list<SchemaCheckConstraint> $checkConstraints
 * @param list<SchemaExcludeConstraint> $excludeConstraints
 * @param list<SchemaTrigger> $triggers
 * @param list<string> $partitionColumns
 * @param list<string> $inherits
 */
schema_table(string $name, array $columns, ?PrimaryKey $primaryKey, array $indexes, array $foreignKeys, array $uniqueConstraints, array $checkConstraints, array $excludeConstraints, array $triggers, string $schema, bool $unlogged, ?PartitionStrategy $partitionStrategy, array $partitionColumns, array $inherits, ?string $tablespace) : Table
/**
 * @param non-empty-list<TriggerEvent> $events
 */
schema_trigger(string $name, string $tableName, TriggerTiming $timing, array $events, string $functionName, bool $forEachRow, ?string $whenCondition) : Trigger
/**
 * @param non-empty-list<string> $columns
 */
schema_unique(array $columns, ?string $name, bool $nullsNotDistinct) : UniqueConstraint
/**
 * Create a new SELECT query builder.
 *
 * @param Expression|string ...$expressions Columns to select. If empty, returns SelectSelectStep.
 */
select(Expression|string $expressions) : SelectBuilder
/**
 * 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
 */
set_role(string $role) : SetRoleFinalStep
/**
 * Create a SET SESSION CHARACTERISTICS AS TRANSACTION builder.
 *
 * Example: set_session_transaction()->isolationLevel(IsolationLevel::SERIALIZABLE)
 * Produces: SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE
 */
set_session_transaction() : SetTransactionOptionsStep
/**
 * Create a SET TRANSACTION builder.
 *
 * Example: set_transaction()->isolationLevel(IsolationLevel::SERIALIZABLE)->readOnly()
 * Produces: SET TRANSACTION ISOLATION LEVEL SERIALIZABLE, READ ONLY
 */
set_transaction() : SetTransactionOptionsStep
/**
 * Create a SIMILAR TO condition.
 */
similar_to(Expression|string $expr, Expression|string $pattern) : SimilarTo
/**
 * Create a plan analyzer for analyzing EXPLAIN plans.
 *
 * @param Plan $plan The execution plan to analyze
 *
 * @return PlanAnalyzer The analyzer for extracting insights
 */
sql_analyze(Plan $plan) : PlanAnalyzer
/**
 * 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
 */
sql_deparse(ParsedQuery $query, ?DeparseOptions $options) : string
/**
 * Create an ExplainConfig for customizing EXPLAIN options.
 *
 * @param bool $analyze Whether to actually execute the query (ANALYZE)
 * @param bool $verbose Include verbose output
 * @param bool $costs Include cost estimates (default true)
 * @param bool $buffers Include buffer usage statistics (requires analyze)
 * @param bool $timing Include timing information (requires analyze)
 * @param ExplainFormat $format Output format (JSON recommended for parsing)
 */
sql_explain_config(bool $analyze, bool $verbose, bool $costs, bool $buffers, bool $timing, ExplainFormat $format) : ExplainConfig
/**
 * Create an ExplainModifier for transforming queries into EXPLAIN queries.
 */
sql_explain_modifier(ExplainConfig $config) : ExplainModifier
/**
 * Parse EXPLAIN JSON output into a Plan object.
 *
 * @param string $jsonOutput The JSON output from EXPLAIN (FORMAT JSON)
 *
 * @return Plan The parsed execution plan
 */
sql_explain_parse(string $jsonOutput) : Plan
/**
 * Returns a fingerprint of the given SQL query.
 * Literal values are normalized so they won't affect the fingerprint.
 */
sql_fingerprint(string $sql) : ?string
/**
 * 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
 */
sql_format(string $sql, ?DeparseOptions $options) : string
/**
 * 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)
 */
sql_keyset_column(string $column, SortOrder $order) : KeysetColumn
/**
 * 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.
 */
sql_normalize(string $sql) : ?string
/**
 * Normalize utility SQL statements (DDL like CREATE, ALTER, DROP).
 * This handles DDL statements differently from pg_normalize() which is optimized for DML.
 */
sql_normalize_utility(string $sql) : ?string
/**
 * Get the maximum nesting depth of a SQL query.
 *
 * Example:
 * - "SELECT * FROM t" => 1
 * - "SELECT * FROM (SELECT * FROM t)" => 2
 * - "SELECT * FROM (SELECT * FROM (SELECT * FROM t))" => 3
 */
sql_query_depth(string $sql) : int
/**
 * Extract ORDER BY clauses from a parsed SQL query.
 */
sql_query_order_by(ParsedQuery $query) : OrderBy
/**
 * Split string with multiple SQL statements into array of individual statements.
 *
 * @return array<string>
 */
sql_split(string $sql) : array
/**
 * Generate a summary of parsed queries in protobuf format.
 * Useful for query monitoring and logging without full AST overhead.
 */
sql_summary(string $sql, int $options, int $truncateLimit) : string
/**
 * 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
 */
sql_to_count_query(string $sql) : string
/**
 * Transform a SQL query into an EXPLAIN query.
 *
 * Returns the modified SQL with EXPLAIN wrapped around it.
 * Defaults to EXPLAIN ANALYZE with JSON format for easy parsing.
 *
 * @param string $sql The SQL query to explain
 * @param null|ExplainConfig $config EXPLAIN configuration (defaults to forAnalysis())
 *
 * @return string The EXPLAIN query
 */
sql_to_explain(string $sql, ?ExplainConfig $config) : string
/**
 * Transform a SQL query into a keyset (cursor-based) paginated query.
 *
 * More efficient than OFFSET for large datasets - uses indexed WHERE conditions.
 * Automatically detects existing query parameters and appends keyset placeholders at the end.
 *
 * @param string $sql The SQL query to paginate (must have ORDER BY)
 * @param int $limit Maximum number of rows to return
 * @param list<KeysetColumn> $columns Columns for keyset pagination (must match ORDER BY)
 * @param null|list<null|bool|float|int|string> $cursor Values from last row of previous page (null for first page)
 *
 * @return string The paginated SQL query
 */
sql_to_keyset_query(string $sql, int $limit, array $columns, ?array $cursor) : string
/**
 * Transform a SQL query to limit results to a specific number of rows.
 *
 * @param string $sql The SQL query to limit
 * @param int $limit Maximum number of rows to return
 *
 * @return string The limited SQL query
 */
sql_to_limited_query(string $sql, int $limit) : string
/**
 * 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
 */
sql_to_paginated_query(string $sql, int $limit, int $offset) : string
/**
 * Create a SELECT * expression.
 */
star(?string $table) : Star
/**
 * Create a row mapper backed by a public static factory method.
 *
 * The factory method must accept a single array<string, mixed> $row and return
 * an instance of the target class. If your factory needs access to the mapping
 * Context (sql/parameters/client/catalog/user-data), implement RowMapper directly.
 *
 * @template T of object
 *
 * @param class-string<T> $class
 * @param non-empty-string $method
 *
 * @return StaticFactoryMapper<T>
 */
static_factory_mapper(string $class, string $method) : StaticFactoryMapper
/**
 * Create a subquery expression.
 */
sub_select(SelectFinalStep $query) : Subquery
/**
 * 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)
 */
table(string $name, ?string $schema) : Table
/**
 * Create a table function reference.
 *
 * @param FunctionCall $function The table-valued function
 * @param bool $withOrdinality Whether to add WITH ORDINALITY
 */
table_func(FunctionCall $function, bool $withOrdinality) : TableFunction
/**
 * Create a full-text search match condition (@@).
 *
 * Example: text_search_match(col('document'), func('to_tsquery', [literal('english'), literal('hello & world')]))
 * Produces: document @@ to_tsquery('english', 'hello & world')
 */
text_search_match(Expression|string $document, Expression|string $query) : OperatorCondition
/**
 * Wrap a PostgreSQL client with telemetry instrumentation.
 *
 * Returns a decorator that adds spans, metrics, and logs to all
 * query and transaction operations following OpenTelemetry conventions.
 *
 * @param Client\Client $client The PostgreSQL client to instrument
 * @param PostgreSqlTelemetryConfig $telemetryConfig Telemetry configuration
 *
 * @example
 * $client = pgsql_client(pgsql_connection('host=localhost dbname=mydb'));
 *
 * $traceableClient = traceable_postgresql_client(
 *     $client,
 *     postgresql_telemetry_config(
 *         telemetry(resource(['service.name' => 'my-app'])),
 *         new SystemClock(),
 *         postgresql_telemetry_options(
 *             traceQueries: true,
 *             traceTransactions: true,
 *             collectMetrics: true,
 *             logQueries: true,
 *             maxQueryLength: 500,
 *         ),
 *     ),
 * );
 *
 * // All operations now traced
 * $traceableClient->transaction(function (Client $client) {
 *     $user = $client->fetchSingle('SELECT * FROM users WHERE id = $1', [123]);
 *     $client->execute('UPDATE users SET last_login = NOW() WHERE id = $1', [123]);
 * });
 */
traceable_postgresql_client(Client $client, PostgreSqlTelemetryConfig $telemetryConfig) : TraceableClient
/**
 * Create a SET TRANSACTION SNAPSHOT builder.
 *
 * Example: transaction_snapshot('00000003-0000001A-1')
 * Produces: SET TRANSACTION SNAPSHOT '00000003-0000001A-1'
 */
transaction_snapshot(string $snapshotId) : SetTransactionFinalStep
/**
 * Create a TRUNCATE TABLE builder.
 *
 * @param string ...$tables Table names to truncate
 */
truncate_table(string $tables) : TruncateFinalStep
/**
 * Wrap a value with explicit PostgreSQL type information for parameter binding.
 *
 * Use when auto-detection isn't sufficient or when you need to specify
 * the exact PostgreSQL type (since one PHP type can map to multiple PostgreSQL types):
 * - int could be INT2, INT4, or INT8
 * - string could be TEXT, VARCHAR, or CHAR
 * - array must always use typed() since auto-detection cannot determine element type
 * - DateTimeInterface could be TIMESTAMP or TIMESTAMPTZ
 * - Json could be JSON or JSONB
 *
 * @param mixed $value The value to bind
 * @param ValueType $targetType The PostgreSQL type to convert the value to
 *
 * @example
 * $client->fetch(
 *     'SELECT * FROM users WHERE id = $1 AND tags = $2',
 *     [
 *         typed('550e8400-e29b-41d4-a716-446655440000', ValueType::UUID),
 *         typed(['tag1', 'tag2'], ValueType::TEXT_ARRAY),
 *     ]
 * );
 */
typed(?mixed $value, ValueType $targetType) : TypedValue
/**
 * Creates a type attribute for composite types.
 *
 * Example: type_attr('name', column_type_text())
 * Produces: name text
 *
 * Example: type_attr('description', column_type_text())->collate('en_US')
 * Produces: description text COLLATE "en_US"
 *
 * @param string $name The attribute name
 * @param ColumnType $type The attribute type
 *
 * @return TypeAttribute Type attribute value object
 */
type_attr(string $name, ColumnType $type) : TypeAttribute
/**
 * @template TType
 * @template TOut
 *
 * @param FlowType<TType> $type
 * @param null|RowMapper<TOut> $next
 *
 * @return ($next is null ? TypeMapper<TType, TType> : TypeMapper<TType, TOut>)
 */
type_mapper(Type $type, ?RowMapper $next) : TypeMapper
/**
 * Create a UNIQUE constraint.
 *
 * @param string ...$columns Columns that must be unique together
 */
unique_constraint(string $columns) : UniqueConstraint
/**
 * Create an UNLISTEN statement to unsubscribe the current session from a notification channel.
 *
 * Usage:
 *   unlisten('my_channel')->toSql()  // UNLISTEN my_channel
 */
unlisten(string $channel) : UnlistenFinalStep
/**
 * Create a new UPDATE query builder.
 */
update() : UpdateTableStep
/**
 * Create a VACUUM builder.
 *
 * Example: vacuum()->table('users')
 * Produces: VACUUM users
 */
vacuum() : VacuumFinalStep
/**
 * Create a VALUES clause as a table reference.
 *
 * Usage:
 *   select()->from(
 *       values_table(
 *           row_expr([literal(1), literal('Alice')]),
 *           row_expr([literal(2), literal('Bob')])
 *       )->as('t', ['id', 'name'])
 *   )
 *
 * Generates: SELECT * FROM (VALUES (1, 'Alice'), (2, 'Bob')) AS t(id, name)
 */
values_table(RowExpression $rows) : ValuesTable
/**
 * Create a WHEN clause for CASE expression.
 */
when(Expression|string $condition, Expression|string $result) : WhenClause
/**
 * Create a window definition for WINDOW clause.
 *
 * @param string $name Window name
 * @param list<Expression|string> $partitionBy PARTITION BY expressions
 * @param list<OrderBy> $orderBy ORDER BY items
 * @param null|WindowFrame $frame Window frame specification
 */
window_def(string $name, array $partitionBy, array $orderBy, ?WindowFrame $frame) : WindowDefinition
/**
 * Create a window frame specification.
 */
window_frame(FrameMode $mode, FrameBound $start, ?FrameBound $end, FrameExclusion $exclusion) : WindowFrame
/**
 * Create a window function.
 *
 * @param string $name Function name
 * @param list<Expression|string> $args Function arguments
 * @param list<Expression|string> $partitionBy PARTITION BY expressions
 * @param list<OrderBy> $orderBy ORDER BY items
 */
window_func(string $name, array $args, array $partitionBy, array $orderBy) : WindowFunction
/**
 * 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'))
 */
with(CTE $ctes) : WithBuilder
Contributors

Built in the open.

Join us on GitHub
scroll back to top