flow php

Table Query Builder

The Table Query Builder provides a fluent, type-safe interface for constructing PostgreSQL DDL statements: CREATE TABLE, ALTER TABLE, DROP TABLE, TRUNCATE, and CREATE TABLE AS.

CREATE TABLE

Basic Table Creation

<?php

use function Flow\PostgreSql\DSL\{create, column, sql_type_serial, sql_type_varchar};

$query = create()->table('users')
    ->column(column('id', sql_type_serial())->primaryKey())
    ->column(column('name', sql_type_varchar(100))->notNull());

echo $query->toSQL();
// CREATE TABLE users (id serial PRIMARY KEY, name varchar(100) NOT NULL)

Table with Schema

<?php

use function Flow\PostgreSql\DSL\{create, column, sql_type_serial};

$query = create()->table('users', 'public')
    ->column(column('id', sql_type_serial())->primaryKey());

echo $query->toSQL();
// CREATE TABLE public.users (id serial PRIMARY KEY)

IF NOT EXISTS

<?php

use function Flow\PostgreSql\DSL\{create, column, sql_type_serial};

$query = create()->table('users')
    ->ifNotExists()
    ->column(column('id', sql_type_serial())->primaryKey());

echo $query->toSQL();
// CREATE TABLE IF NOT EXISTS users (id serial PRIMARY KEY)

Column Definitions

Columns support various constraints and options:

<?php

use function Flow\PostgreSql\DSL\{create, column, sql_type_integer, sql_type_varchar, sql_type_boolean, sql_type_timestamp};

$query = create()->table('users')
    ->column(column('id', sql_type_integer())->identity('ALWAYS'))
    ->column(column('email', sql_type_varchar(255))->notNull()->unique())
    ->column(column('active', sql_type_boolean())->default(true))
    ->column(column('created_at', sql_type_timestamp())->defaultRaw('CURRENT_TIMESTAMP'));

echo $query->toSQL();
// CREATE TABLE users (
//   id int GENERATED ALWAYS AS IDENTITY,
//   email varchar(255) NOT NULL UNIQUE,
//   active boolean DEFAULT true,
//   created_at timestamp DEFAULT CURRENT_TIMESTAMP
// )

Column with Foreign Key Reference

<?php

use function Flow\PostgreSql\DSL\{create, column, sql_type_serial, sql_type_integer};

$query = create()->table('orders')
    ->column(column('id', sql_type_serial())->primaryKey())
    ->column(column('user_id', sql_type_integer())->notNull()->references('users', 'id'));

echo $query->toSQL();
// CREATE TABLE orders (id serial PRIMARY KEY, user_id int NOT NULL REFERENCES users(id))

Generated Columns

<?php

use function Flow\PostgreSql\DSL\{create, column, sql_type_varchar, sql_type_text};

$query = create()->table('users')
    ->column(column('first_name', sql_type_varchar(50)))
    ->column(column('last_name', sql_type_varchar(50)))
    ->column(column('full_name', sql_type_text())->generatedAs("first_name || ' ' || last_name"));

echo $query->toSQL();
// CREATE TABLE users (first_name varchar(50), last_name varchar(50), full_name pg_catalog.text GENERATED ALWAYS AS (first_name || ' ' || last_name) STORED)

Table-Level Constraints

Primary Key

<?php

use function Flow\PostgreSql\DSL\{create, column, sql_type_integer, primary_key};

$query = create()->table('order_items')
    ->column(column('order_id', sql_type_integer())->notNull())
    ->column(column('product_id', sql_type_integer())->notNull())
    ->constraint(primary_key('order_id', 'product_id'));

echo $query->toSQL();
// CREATE TABLE order_items (order_id int NOT NULL, product_id int NOT NULL, PRIMARY KEY (order_id, product_id))

Unique Constraint

<?php

use function Flow\PostgreSql\DSL\{create, column, sql_type_serial, sql_type_varchar, unique_constraint};

$query = create()->table('users')
    ->column(column('id', sql_type_serial())->primaryKey())
    ->column(column('email', sql_type_varchar(255))->notNull())
    ->constraint(unique_constraint('email'));

echo $query->toSQL();
// CREATE TABLE users (id serial PRIMARY KEY, email varchar(255) NOT NULL, UNIQUE (email))

Check Constraint

<?php

use function Flow\PostgreSql\DSL\{create, column, sql_type_serial, sql_type_integer, check_constraint};

$query = create()->table('products')
    ->column(column('id', sql_type_serial())->primaryKey())
    ->column(column('price', sql_type_integer()))
    ->constraint(check_constraint('price > 0')->name('positive_price'));

echo $query->toSQL();
// CREATE TABLE products (id serial PRIMARY KEY, price int, CONSTRAINT positive_price CHECK (price > 0))

Foreign Key Constraint

<?php

use function Flow\PostgreSql\DSL\{create, column, sql_type_serial, sql_type_integer, foreign_key, ref_action_cascade, ref_action_restrict};

$query = create()->table('orders')
    ->column(column('id', sql_type_serial())->primaryKey())
    ->column(column('user_id', sql_type_integer())->notNull())
    ->constraint(
        foreign_key(['user_id'], 'users', ['id'])
            ->onDelete(ref_action_cascade())
            ->onUpdate(ref_action_restrict())
    );

echo $query->toSQL();
// CREATE TABLE orders (id serial PRIMARY KEY, user_id int NOT NULL, FOREIGN KEY (user_id) REFERENCES ONLY users (id) ON UPDATE RESTRICT ON DELETE CASCADE)

Temporary Tables

<?php

use function Flow\PostgreSql\DSL\{create, column, sql_type_integer};

$query = create()->table('temp_results')
    ->temporary()
    ->column(column('id', sql_type_integer()));

echo $query->toSQL();
// CREATE TEMPORARY TABLE temp_results (id int) ON COMMIT DROP

Unlogged Tables

<?php

use function Flow\PostgreSql\DSL\{create, column, sql_type_integer};

$query = create()->table('cache_data')
    ->unlogged()
    ->column(column('id', sql_type_integer()));

echo $query->toSQL();
// CREATE UNLOGGED TABLE cache_data (id int)

Table Inheritance

<?php

use function Flow\PostgreSql\DSL\{create, column, sql_type_varchar};

$query = create()->table('employees')
    ->column(column('department', sql_type_varchar(100)))
    ->inherits('persons');

echo $query->toSQL();
// CREATE TABLE employees (department varchar(100)) INHERITS (persons)

Partitioned Tables

<?php

use function Flow\PostgreSql\DSL\{create, column, sql_type_integer, sql_type_timestamp};

// Range partitioning
$query = create()->table('logs')
    ->column(column('id', sql_type_integer()))
    ->column(column('created_at', sql_type_timestamp()))
    ->partitionByRange('created_at');

echo $query->toSQL();
// CREATE TABLE logs (id int, created_at timestamp) PARTITION BY RANGE (created_at)

// List partitioning
$query = create()->table('sales')
    ->column(column('region', sql_type_varchar(50)))
    ->partitionByList('region');

// Hash partitioning
$query = create()->table('data')
    ->column(column('id', sql_type_integer()))
    ->partitionByHash('id');

CREATE TABLE AS

Basic CREATE TABLE AS

<?php

use function Flow\PostgreSql\DSL\{create, select, col, table};

$selectQuery = select()
    ->select(col('id'), col('name'))
    ->from(table('users'));

$query = create()->tableAs('users_backup', $selectQuery);

echo $query->toSQL();
// CREATE TABLE users_backup AS SELECT id, name FROM users

With IF NOT EXISTS

<?php

use function Flow\PostgreSql\DSL\{create, select, col, table};

$selectQuery = select()
    ->select(col('id'), col('name'))
    ->from(table('users'));

$query = create()->tableAs('users_backup', $selectQuery)
    ->ifNotExists();

echo $query->toSQL();
// CREATE TABLE IF NOT EXISTS users_backup AS SELECT id, name FROM users

With Column Names

<?php

use function Flow\PostgreSql\DSL\{create, select, col, table};

$selectQuery = select()
    ->select(col('id'), col('name'))
    ->from(table('users'));

$query = create()->tableAs('users_backup', $selectQuery)
    ->columnNames('user_id', 'user_name');

echo $query->toSQL();
// CREATE TABLE users_backup(user_id, user_name) AS SELECT id, name FROM users

Structure Only (No Data)

<?php

use function Flow\PostgreSql\DSL\{create, select, col, table};

$selectQuery = select()
    ->select(col('id'), col('name'))
    ->from(table('users'));

$query = create()->tableAs('users_backup', $selectQuery)
    ->withNoData();

echo $query->toSQL();
// CREATE TABLE users_backup AS SELECT id, name FROM users WITH NO DATA

ALTER TABLE

Add Column

<?php

use function Flow\PostgreSql\DSL\{alter, column, sql_type_varchar};

$query = alter()->table('users')
    ->addColumn(column('email', sql_type_varchar(255))->notNull());

echo $query->toSQL();
// ALTER TABLE users ADD COLUMN email varchar(255) NOT NULL

Drop Column

<?php

use function Flow\PostgreSql\DSL\alter;

$query = alter()->table('users')
    ->dropColumn('temp_column');

echo $query->toSQL();
// ALTER TABLE users DROP temp_column

// With CASCADE
$query = alter()->table('users')
    ->dropColumn('temp_column', cascade: true);

echo $query->toSQL();
// ALTER TABLE users DROP temp_column CASCADE

Alter Column Type

<?php

use function Flow\PostgreSql\DSL\{alter, sql_type_text};

$query = alter()->table('users')
    ->alterColumnType('name', sql_type_text());

echo $query->toSQL();
// ALTER TABLE users ALTER COLUMN name TYPE pg_catalog.text

Set/Drop NOT NULL

<?php

use function Flow\PostgreSql\DSL\alter;

// Set NOT NULL
$query = alter()->table('users')
    ->alterColumnSetNotNull('email');

echo $query->toSQL();
// ALTER TABLE users ALTER COLUMN email SET NOT NULL

// Drop NOT NULL
$query = alter()->table('users')
    ->alterColumnDropNotNull('email');

echo $query->toSQL();
// ALTER TABLE users ALTER COLUMN email DROP NOT NULL

Set/Drop Default

<?php

use function Flow\PostgreSql\DSL\alter;

// Set default
$query = alter()->table('users')
    ->alterColumnSetDefault('status', "'active'");

echo $query->toSQL();
// ALTER TABLE users ALTER COLUMN status SET DEFAULT 'active'

// Drop default
$query = alter()->table('users')
    ->alterColumnDropDefault('status');

echo $query->toSQL();
// ALTER TABLE users ALTER COLUMN status DROP DEFAULT

Add Constraint

<?php

use function Flow\PostgreSql\DSL\{alter, unique_constraint};

$query = alter()->table('users')
    ->addConstraint(unique_constraint('email')->name('users_email_unique'));

echo $query->toSQL();
// ALTER TABLE users ADD CONSTRAINT users_email_unique UNIQUE (email)

Drop Constraint

<?php

use function Flow\PostgreSql\DSL\alter;

$query = alter()->table('users')
    ->dropConstraint('users_email_unique');

echo $query->toSQL();
// ALTER TABLE users DROP CONSTRAINT users_email_unique

Multiple Operations

<?php

use function Flow\PostgreSql\DSL\{alter, column, sql_type_varchar};

$query = alter()->table('users')
    ->addColumn(column('phone', sql_type_varchar(20)))
    ->dropColumn('fax')
    ->alterColumnSetNotNull('email');

echo $query->toSQL();
// ALTER TABLE users ADD COLUMN phone varchar(20), DROP fax, ALTER COLUMN email SET NOT NULL

IF EXISTS

<?php

use function Flow\PostgreSql\DSL\{alter, column, sql_type_varchar};

$query = alter()->table('users')
    ->ifExists()
    ->addColumn(column('email', sql_type_varchar(255)));

echo $query->toSQL();
// ALTER TABLE IF EXISTS users ADD COLUMN email varchar(255)

Rename Column

<?php

use function Flow\PostgreSql\DSL\alter;

$query = alter()->table('users')
    ->renameColumn('old_name', 'new_name');

echo $query->toSQL();
// ALTER TABLE users RENAME COLUMN old_name TO new_name

Rename Constraint

<?php

use function Flow\PostgreSql\DSL\alter;

$query = alter()->table('users')
    ->renameConstraint('old_constraint', 'new_constraint');

echo $query->toSQL();
// ALTER TABLE users RENAME CONSTRAINT old_constraint TO new_constraint

Rename Table

<?php

use function Flow\PostgreSql\DSL\alter;

$query = alter()->table('users')
    ->renameTo('users_archive');

echo $query->toSQL();
// ALTER TABLE users RENAME TO users_archive

Set Schema

<?php

use function Flow\PostgreSql\DSL\alter;

$query = alter()->table('users')
    ->setSchema('archive');

echo $query->toSQL();
// ALTER TABLE users SET SCHEMA archive

DROP TABLE

Simple Drop

<?php

use function Flow\PostgreSql\DSL\drop;

$query = drop()->table('users');

echo $query->toSQL();
// DROP TABLE users

IF EXISTS

<?php

use function Flow\PostgreSql\DSL\drop;

$query = drop()->table('users')
    ->ifExists();

echo $query->toSQL();
// DROP TABLE IF EXISTS users

CASCADE

<?php

use function Flow\PostgreSql\DSL\drop;

$query = drop()->table('users')
    ->cascade();

echo $query->toSQL();
// DROP TABLE users CASCADE

Multiple Tables

<?php

use function Flow\PostgreSql\DSL\drop;

$query = drop()->table('users', 'orders', 'products');

echo $query->toSQL();
// DROP TABLE users, orders, products

TRUNCATE

Simple Truncate

<?php

use function Flow\PostgreSql\DSL\truncate_table;

$query = truncate_table('users');

echo $query->toSQL();
// TRUNCATE users

Multiple Tables

<?php

use function Flow\PostgreSql\DSL\truncate_table;

$query = truncate_table('users', 'orders', 'products');

echo $query->toSQL();
// TRUNCATE users, orders, products

Restart Identity

<?php

use function Flow\PostgreSql\DSL\truncate_table;

$query = truncate_table('users')
    ->restartIdentity();

echo $query->toSQL();
// TRUNCATE users RESTART IDENTITY

CASCADE

<?php

use function Flow\PostgreSql\DSL\truncate_table;

$query = truncate_table('users')
    ->cascade();

echo $query->toSQL();
// TRUNCATE users CASCADE

Data Types

The following SQL type functions are available:

Numeric Types

Function PostgreSQL Type
sql_type_integer() int
sql_type_bigint() bigint
sql_type_smallint() smallint
sql_type_serial() serial
sql_type_bigserial() bigserial
sql_type_numeric($precision, $scale) numeric(p,s)
sql_type_decimal($precision, $scale) decimal(p,s)
sql_type_real() real
sql_type_double() double precision

String Types

Function PostgreSQL Type
sql_type_text() text
sql_type_varchar($length) varchar(n)
sql_type_char($length) char(n)

Date/Time Types

Function PostgreSQL Type
sql_type_date() date
sql_type_time($precision) time
sql_type_timestamp($precision) timestamp
sql_type_timestamptz($precision) timestamptz
sql_type_interval() interval

Other Types

Function PostgreSQL Type
sql_type_boolean() boolean
sql_type_uuid() uuid
sql_type_json() json
sql_type_jsonb() jsonb
sql_type_bytea() bytea
sql_type_inet() inet
sql_type_cidr() cidr
sql_type_macaddr() macaddr
sql_type_array($elementType) type[]

Referential Actions

The following referential action functions are available for foreign key constraints:

Function Action
ref_action_cascade() CASCADE
ref_action_restrict() RESTRICT
ref_action_no_action() NO ACTION
ref_action_set_null() SET NULL
ref_action_set_default() SET DEFAULT

For a complete list of DSL functions, see the DSL reference.


Contributors

Join us on GitHub external resource
scroll back to top