NAME
DBIO::Cake - DDL-like DSL for defining DBIO result classes
VERSION
version 0.900000
SYNOPSIS
package MyApp::Schema::Result::Artist;
use DBIO::Cake;
table 'artists';
col id => integer auto_inc;
col name => varchar(100);
col bio => text null;
col active => boolean default(1);
col created_at => timestamp;
col updated_at => timestamp on_update;
primary_key 'id';
unique artist_name => ['name'];
has_many cds => 'MyApp::Schema::Result::CD', 'artist_id';
1;
PostgreSQL-specific example:
package MyApp::Schema::Result::User;
use DBIO::Cake -inflate_json;
table 'users';
col id => uuid;
col name => varchar(100);
col role => enum(qw( admin moderator user guest )), null;
col metadata => jsonb \"{}";
col embedding => vector(1536);
col tags => array(text), null;
col tsv => tsvector null;
col created_at => timestamp;
col updated_at => timestamp on_update;
col deleted_at => timestamp null;
primary_key 'id';
idx user_tags => ['tags'], using => 'gin';
1;
DESCRIPTION
DBIO::Cake is the most concise way to define DBIO result classes. It keeps the same underlying schema metadata as vanilla DBIO::Core, but replaces verbose hashref-heavy declarations with a DDL-like DSL.
Use Cake when you want result classes to read like schema definitions without changing how the rest of DBIO behaves.
When you use DBIO::Cake, it automatically:
Enables
strictandwarningsSets the calling class to inherit from DBIO::Core
Exports all DSL functions into the calling package
Cleans up exported symbols after the scope ends (via namespace::clean)
COMMA-FREE SYNTAX
Cake supports a DDL-like comma-free syntax. All type functions and modifiers pass @_ through, so Perl chains them via nested function calls:
col id => integer auto_inc; # parsed as: integer(auto_inc())
col bio => text null; # parsed as: text(null())
col active => boolean default(1); # parsed as: boolean(default(1))
When you need a comma: after a number or closing parenthesis, Perl needs a comma before the next bareword:
col name => varchar(100), null; # comma after (100)
col name => varchar 100, null; # comma after 100
This matches DBIx::Class::ResultDDL conventions.
IMPORT OPTIONS
use DBIO::Cake; # defaults
use DBIO::Cake -inflate_datetime; # load InflateColumn::DateTime
use DBIO::Cake -inflate_json; # auto-inflate json/jsonb columns
use DBIO::Cake -retrieve_defaults; # set retrieve_on_insert for columns with defaults
use DBIO::Cake -no_autoclean; # don't clean up symbols
Multiple options can be combined:
use DBIO::Cake -inflate_datetime, -inflate_json;
SMART DEFAULTS
Cake automatically sets sensible defaults based on column type and nullability.
Timestamp columns
The behavior depends on nullability and the on_update modifier:
col created_at => timestamp; # NOT NULL -> set_on_create
col updated_at => timestamp on_update; # NOT NULL -> set_on_create + set_on_update
col deleted_at => timestamp null; # nullable -> no auto-set
col last_login => timestamp null, on_update; # nullable -> only set_on_update
The logic: NOT NULL timestamp columns must have a value on create, so set_on_create is implied. Nullable columns don't need a value on create, so only explicit on_update is applied.
This integrates with the DBIO::Timestamp component built into DBIO core.
UUID columns
NOT NULL uuid columns automatically get retrieve_on_insert so the database-generated default (e.g. PostgreSQL's gen_random_uuid()) is retrieved after INSERT:
col id => uuid;
# -> retrieve_on_insert => 1
Scalar references as defaults
A scalar reference anywhere in a col declaration is treated as a default_value. This is a shorthand for default(\...):
col id => uuid \"gen_random_uuid()";
col active => boolean \1;
col created => timestamp \"now()";
# equivalent to:
col id => uuid default(\"gen_random_uuid()");
For literal SQL defaults, use a reference to a string. For Perl-side defaults, use default($value) without a reference.
COLUMN TYPES
All type functions return flat key-value lists and pass through @_, enabling the comma-free syntax.
Integer types
integer, tinyint, smallint, bigint
col id => integer auto_inc;
col count => bigint;
Serial types (auto-increment shortcuts)
serial, bigserial, smallserial
col id => serial; # integer + auto_inc in one
Numeric types
numeric($precision, $scale), decimal($precision, $scale)
col price => numeric(10, 2);
Floating point types
real (alias: float4), double (alias: float8), float($bits)
String types
char($size), varchar($size)
col code => char(3);
col name => varchar(100), null;
Text types
text, tinytext, mediumtext, longtext
col bio => text null;
Binary types
blob, tinyblob, mediumblob, longblob, bytea
Boolean
boolean (alias: bool)
col active => boolean default(1);
Date/Time types
date, datetime, timestamp, time, timetz, timestamptz, interval
col created_at => timestamp; # auto set_on_create
col updated_at => timestamp on_update; # auto set_on_create + set_on_update
col deleted_at => timestamp null; # no auto-set
col birthday => date null;
Enum
enum(@values)
col role => enum(qw( admin moderator user guest ));
UUID
uuid
col id => uuid; # auto retrieve_on_insert
JSON
json, jsonb
col metadata => jsonb null;
With -inflate_json, json/jsonb columns are automatically serialized.
Array (PostgreSQL)
array($type)
col tags => array(text), null;
Vector / AI (pgvector)
vector($dims), halfvec($dims), sparsevec($dims)
col embedding => vector(1536);
Full-text search (PostgreSQL)
tsvector, tsquery
Network types (PostgreSQL)
inet, cidr, macaddr, macaddr8
Geometric types (PostgreSQL)
point, line, lseg, box, path, polygon, circle
Range types (PostgreSQL)
int4range, int8range, numrange, tsrange, tstzrange, daterange
Other
money, xml, hstore, bit($size), varbit($size)
COLUMN MODIFIERS
All modifiers return flat key-value lists and pass through @_.
null
Marks the column as nullable.
col bio => text null;
auto_inc
Marks the column as auto-increment.
col id => integer auto_inc;
fk
Marks the column as a foreign key.
col author_id => integer fk;
unsigned
Marks the column as unsigned (MySQL).
col count => integer unsigned;
default($value)
Sets the default value.
col active => boolean default(1);
col created => timestamp default(\"now()");
on_create
Explicitly set set_on_create. Normally not needed -- NOT NULL timestamp columns get this automatically.
on_update
Set set_on_update -- the column value is refreshed on every row update.
col updated_at => timestamp on_update;
TABLE AND CONSTRAINT FUNCTIONS
table
table 'my_table';
Sets the table name for this result class.
primary_key
primary_key 'id';
primary_key 'artist_id', 'cd_id';
Sets the primary key column(s).
unique
unique \@cols;
unique $name => \@cols;
Adds a unique constraint.
RELATIONSHIP FUNCTIONS
belongs_to author => 'MyApp::Schema::Result::Author', 'author_id';
has_one isbn => 'MyApp::Schema::Result::ISBN', 'book_id';
has_many books => 'MyApp::Schema::Result::Book', 'author_id';
might_have bio => 'MyApp::Schema::Result::Bio', 'author_id';
many_to_many roles => 'actor_roles', 'role';
rel_one
Like belongs_to but forces join_type => 'left'.
rel_many
Alias for has_many.
CASCADE HELPERS
ddl_cascade
Returns on_delete => 'CASCADE', on_update => 'CASCADE' for use in relationship attribute hashes.
dbic_cascade
Returns cascade_delete => 1, cascade_copy => 1.
VIEW SUPPORT
view
view 'my_view', 'SELECT * FROM artists WHERE active = 1';
Declares a view-based result source.
TIMESTAMP HELPERS
Shortcut functions for the most common timestamp column patterns.
col_created
col_created; # creates 'created_at' column
col_created 'born_at'; # custom column name
Equivalent to col created_at => timestamp.
col_updated
col_updated; # creates 'updated_at' column
col_updated 'modified_at'; # custom column name
Equivalent to col updated_at => timestamp on_update.
cols_updated_created
cols_updated_created; # creates both created_at + updated_at
Creates both timestamp columns in one call. The most common pattern -- just add this one line and you're done.
INDEX SUPPORT
idx
idx name_idx => ['name'];
idx composite_idx => ['last_name', 'first_name'], type => 'unique';
idx tags_idx => ['tags'], using => 'gin';
idx draft_only => ['key'],
type => 'unique',
pg => { where => 'version IS NULL' };
Declares an index. Cake installs two hooks on the Result class so that idx works transparently in both deployment pipelines:
sqlt_deploy_hook— DEPRECATED hook for legacy deployment. Theoptionskey passes producer-specific options through.pg_indexes— used by DBIO::PostgreSQL::DDL when the schema loads thePostgreSQLcomponent. Thepgkey carries PostgreSQL-specific options (where,using,with,expression) and is passed through to the native PG DDL emitter.
If the class already defines pg_indexes by hand, those definitions are preserved and Cake-declared indexes are merged on top.
PostgreSQL partial indexes
idx agent_published => ['key', 'version'],
type => 'unique',
pg => { where => 'version IS NOT NULL' };
idx agent_draft => ['key'],
type => 'unique',
pg => { where => 'version IS NULL' };
SEE ALSO
DBIO::Core, DBIO::Candy, DBIO::ResultSource, DBIx::Class::ResultDDL (inspiration for Cake's syntax)
AUTHOR
DBIO & DBIx::Class Authors
COPYRIGHT AND LICENSE
Copyright (C) 2026 DBIO Authors Portions Copyright (C) 2005-2025 DBIx::Class Authors Based on DBIx::Class, heavily modified.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.