/**
* 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 DSL References
DSL stands for Domain Specific Language. In the case of Flow, the DSL is used to define simple functions that can be used to transform data. Most of those functions are initializing a new instance of a class under the hood since Flow is fully object-oriented. Please look at the examples below to get a better understanding of how to use the DSL functions.
SCHEMA
/**
* 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 ast_view_dependency_resolver() : AstViewDependencyResolver /**
* 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 $expr Expression to cast
* @param ColumnType $dataType Target data type (use column_type_* functions)
*/
cast(Expression|string $expr, ColumnType $dataType) : TypeCast /**
* @param null|ExecutionOrderStrategy<\Flow\PostgreSql\Schema\Table> $tableOrderStrategy
*/
catalog_comparator(?RenameStrategy $renameStrategy, ?ViewDependencyResolver $viewDependencyResolver, ?ExecutionOrderStrategy $tableOrderStrategy) : CatalogComparator chain_catalog_provider(CatalogProvider $providers) : ChainCatalogProvider /**
* Create a CHECK constraint.
*/
check_constraint(Condition $condition) : CheckConstraint /**
* @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 bigint data type (PostgreSQL int8).
*/
column_type_bigint() : ColumnType /**
* Create a bigserial data type.
*/
column_type_bigserial() : ColumnType /**
* Create a boolean data type.
*/
column_type_boolean() : ColumnType /**
* Create a bytea data type.
*/
column_type_bytea() : ColumnType /**
* Create a char data type with length constraint.
*/
column_type_char(int $length) : ColumnType /**
* Create a cidr data type.
*/
column_type_cidr() : 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 date data type.
*/
column_type_date() : ColumnType /**
* Create a decimal data type with optional precision and scale.
*/
column_type_decimal(?int $precision, ?int $scale) : ColumnType /**
* Create a double precision data type (PostgreSQL float8).
*/
column_type_double_precision() : 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 an inet data type.
*/
column_type_inet() : ColumnType /**
* Create an integer data type (PostgreSQL int4).
*/
column_type_integer() : ColumnType /**
* Create an interval data type.
*/
column_type_interval() : ColumnType /**
* Create a JSON data type.
*/
column_type_json() : ColumnType /**
* Create a JSONB data type.
*/
column_type_jsonb() : ColumnType /**
* Create a macaddr data type.
*/
column_type_macaddr() : ColumnType /**
* Create a numeric data type with optional precision and scale.
*/
column_type_numeric(?int $precision, ?int $scale) : ColumnType /**
* Create a real data type (PostgreSQL float4).
*/
column_type_real() : ColumnType /**
* Create a serial data type.
*/
column_type_serial() : ColumnType /**
* Create a smallint data type (PostgreSQL int2).
*/
column_type_smallint() : ColumnType /**
* Create a smallserial data type.
*/
column_type_smallserial() : ColumnType /**
* Create a text data type.
*/
column_type_text() : ColumnType /**
* Create a time data type with optional precision.
*/
column_type_time(?int $precision) : ColumnType /**
* Create a timestamp data type with optional precision.
*/
column_type_timestamp(?int $precision) : ColumnType /**
* Create a timestamp with time zone data type with optional precision.
*/
column_type_timestamptz(?int $precision) : ColumnType /**
* Create a UUID data type.
*/
column_type_uuid() : ColumnType /**
* Create a varchar data type with length constraint.
*/
column_type_varchar(int $length) : 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 COUNT(*) aggregate.
*/
count_all() : AggregateCall /**
* 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 foreign_key_dependency_order() : ForeignKeyDependencyOrder /**
* 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 CURRENT ROW.
*/
frame_current_row() : FrameBound /**
* 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 frame bound for UNBOUNDED FOLLOWING.
*/
frame_unbounded_following() : FrameBound /**
* Create a frame bound for UNBOUNDED PRECEDING.
*/
frame_unbounded_preceding() : 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 /**
* Get the BRIN index method.
*/
index_method_brin() : IndexMethod /**
* Get the BTREE index method.
*/
index_method_btree() : IndexMethod /**
* Get the GIN index method.
*/
index_method_gin() : IndexMethod /**
* Get the GIST index method.
*/
index_method_gist() : IndexMethod /**
* Get the HASH index method.
*/
index_method_hash() : IndexMethod /**
* Get the SPGIST index method.
*/
index_method_spgist() : IndexMethod /**
* 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
*/
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 manual_catalog_provider(Catalog $catalog) : CatalogProvider materialized_view_dependency_order() : MaterializedViewDependencyOrder /**
* 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 noop_view_dependency_resolver() : NoopViewDependencyResolver /**
* 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 /**
* @return NoExecutionOrder<mixed>
*/
no_execution_order() : NoExecutionOrder /**
* 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)
*
* @throws ConnectionException If connection fails
*/
pgsql_client(ConnectionParameters $params, ?ValueConverters $valueConverters) : 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 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 /**
* Get a CASCADE referential action.
*/
ref_action_cascade() : ReferentialAction /**
* Get a NO ACTION referential action.
*/
ref_action_no_action() : ReferentialAction /**
* Get a RESTRICT referential action.
*/
ref_action_restrict() : ReferentialAction /**
* Get a SET DEFAULT referential action.
*/
ref_action_set_default() : ReferentialAction /**
* Get a SET NULL referential action.
*/
ref_action_set_null() : ReferentialAction /**
* 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 RETURNING * clause.
*/
returning_all() : 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, ?string $default, bool $isIdentity, ?IdentityGeneration $identityGeneration, bool $isGenerated, ?string $generationExpression, ?int $ordinalPosition) : Column schema_column_bigint(string $name, bool $nullable, ?string $default) : Column schema_column_big_serial(string $name) : Column schema_column_boolean(string $name, bool $nullable, ?string $default) : Column schema_column_bytea(string $name, bool $nullable, ?string $default) : Column schema_column_char(string $name, int $length, bool $nullable, ?string $default) : Column schema_column_cidr(string $name, bool $nullable, ?string $default) : Column schema_column_date(string $name, bool $nullable, ?string $default) : Column schema_column_double_precision(string $name, bool $nullable, ?string $default) : Column schema_column_inet(string $name, bool $nullable, ?string $default) : Column schema_column_integer(string $name, bool $nullable, ?string $default) : Column schema_column_interval(string $name, bool $nullable, ?string $default) : Column schema_column_json(string $name, bool $nullable, ?string $default) : Column schema_column_jsonb(string $name, bool $nullable, ?string $default) : Column schema_column_macaddr(string $name, bool $nullable, ?string $default) : Column schema_column_numeric(string $name, ?int $precision, ?int $scale, bool $nullable, ?string $default) : Column schema_column_real(string $name, bool $nullable, ?string $default) : Column schema_column_serial(string $name) : Column schema_column_smallint(string $name, bool $nullable, ?string $default) : Column schema_column_small_serial(string $name) : Column schema_column_text(string $name, bool $nullable, ?string $default) : Column schema_column_time(string $name, ?int $precision, bool $nullable, ?string $default) : Column schema_column_timestamp(string $name, ?int $precision, bool $nullable, ?string $default) : Column schema_column_timestamp_tz(string $name, ?int $precision, bool $nullable, ?string $default) : Column schema_column_uuid(string $name, bool $nullable, ?string $default) : Column schema_column_varchar(string $name, int $length, bool $nullable, ?string $default) : Column /**
* @param list<SchemaCheckConstraint> $checkConstraints
*/
schema_domain(string $name, ColumnType $baseType, bool $nullable, ?string $default, array $checkConstraints) : Domain schema_exclude(string $definition, ?string $name) : ExcludeConstraint schema_extension(string $name, ?string $version) : Extension /**
* @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 schema_view(string $name, string $definition, bool $isUpdatable) : View /**
* 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 DeparseOptions for configuring SQL formatting.
*/
sql_deparse_options() : DeparseOptions /**
* 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 sql_parse(string $sql) : ParsedQuery sql_parser() : Parser /**
* Extract columns from a parsed SQL query.
*/
sql_query_columns(ParsedQuery $query) : Columns /**
* 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 functions from a parsed SQL query.
*/
sql_query_functions(ParsedQuery $query) : Functions /**
* Extract ORDER BY clauses from a parsed SQL query.
*/
sql_query_order_by(ParsedQuery $query) : OrderBy /**
* Extract tables from a parsed SQL query.
*/
sql_query_tables(ParsedQuery $query) : Tables /**
* 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 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->fetchOne('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 T
*
* @param FlowType<T> $type
*
* @return TypeMapper<T>
*/
type_mapper(Type $type) : 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 value_type_bigint() : ValueType value_type_bit() : ValueType value_type_bool() : ValueType value_type_boolean() : ValueType value_type_bool_array() : ValueType value_type_bpchar() : ValueType value_type_bytea() : ValueType value_type_char() : ValueType value_type_cidr() : ValueType value_type_date() : ValueType value_type_double() : ValueType value_type_float4() : ValueType value_type_float4_array() : ValueType value_type_float8() : ValueType value_type_float8_array() : ValueType value_type_inet() : ValueType value_type_int2() : ValueType value_type_int2_array() : ValueType value_type_int4() : ValueType value_type_int4_array() : ValueType value_type_int8() : ValueType value_type_int8_array() : ValueType value_type_integer() : ValueType value_type_interval() : ValueType value_type_json() : ValueType value_type_jsonb() : ValueType value_type_jsonb_array() : ValueType value_type_json_array() : ValueType value_type_macaddr() : ValueType value_type_macaddr8() : ValueType value_type_money() : ValueType value_type_numeric() : ValueType value_type_oid() : ValueType value_type_real() : ValueType value_type_smallint() : ValueType value_type_text() : ValueType value_type_text_array() : ValueType value_type_time() : ValueType value_type_timestamp() : ValueType value_type_timestamptz() : ValueType value_type_timetz() : ValueType value_type_uuid() : ValueType value_type_uuid_array() : ValueType value_type_varbit() : ValueType value_type_varchar() : ValueType value_type_varchar_array() : ValueType value_type_xml() : ValueType view_dependency_order() : ViewDependencyOrder /**
* 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