NAME
DBIx::QuickORM::Manual::Relations - A guide to relations: defining links (foreign keys) and following them between rows, plus joins.
DESCRIPTION
A link in DBIx::QuickORM describes a directional relationship between two tables: a set of local columns on one table that reference a set of other columns on another table. This is what most ORMs call a "relationship" or "foreign key". Once a link is defined you can follow it from a row to its related rows, insert related rows, find a row's siblings, and build joins.
This guide covers the runtime side of relations: following links between rows and building joins. For defining links as part of a schema, see DBIx::QuickORM::Manual::Schema and the link DSL reference in DBIx::QuickORM.
DEFINING A LINK (BRIEF)
Links are defined in the schema DSL with link. They can be declared inside a column (the column is then the local column), or at the schema level naming both sides:
table author => sub {
column author_id => ...;
column name => ...;
};
table book => sub {
column book_id => ...;
column author_id => sub {
# This column is the local side; the link points at author.author_id
link author => [author => ['author_id']];
};
};
# Or declared at the schema level, naming both sides:
link(
{table => 'author', columns => ['author_id'], alias => 'books'},
{table => 'book', columns => ['author_id'], alias => 'author'},
);
The full link syntax (column-level form, two-node form, aliases, and the hashref form) is documented under the link DSL function in DBIx::QuickORM; composing it into a schema is covered in DBIx::QuickORM::Manual::Schema. The compiled result is a DBIx::QuickORM::Link object carrying the local table and columns, the other table and columns, whether the link is unique on the other side, and any aliases naming it.
UNIQUE VS NON-UNIQUE LINKS
A link is either unique or not, depending on whether the other side can match at most one row:
- Unique link
-
The other columns are (covered by) a unique constraint or primary key, so following the link reaches at most one row. Example: a
bookhas oneauthor. Useobtainto get that single row. - Non-unique link
-
Following the link can reach many rows. Example: an
authorhas manybooks. Usefollowto get a handle over all of them.
When a link is built against a schema its unique flag is inferred automatically from the unique constraints on the other table, so you usually do not need to set it yourself. obtain croaks if you call it on a non-unique link.
RESOLVING A LINK
The relation methods all accept a link specification rather than only a fully-built DBIx::QuickORM::Link object. A spec may be:
An existing DBIx::QuickORM::Link object (used as-is).
A bare string: a fuzzy lookup matched against aliases, then table names, then column keys (first hit wins).
Keyword pairs that force a specific dimension instead of the fuzzy match:
alias => $name,table => $name, ortable => $name, columns => \@cols.A hashref describing a new link, which is parsed into one.
Resolution is provided by DBIx::QuickORM::Role::Linked via resolve_link, which the source uses internally before each traversal. If a spec is ambiguous (for example, two links to the same table and no alias to disambiguate) it croaks and lists the candidates.
FOLLOWING LINKS BETWEEN ROWS
The row-level relation methods live in DBIx::QuickORM::Role::Row. In each case $link is any spec accepted by resolve_link.
follow
my $handle = $row->follow($link);
Returns a DBIx::QuickORM::Handle for the rows reached by following $link from this row. Because it returns a handle you can refine and iterate it like any other query:
my $author = $orm->connection->handle('author')->one(author_id => 1);
# Every book by this author:
for my $book ($author->follow('books')->all) {
print $book->field('title'), "\n";
}
# Refine before fetching:
my $recent = $author->follow('books')
->order_by({'-desc' => 'published'})
->limit(5);
See DBIx::QuickORM::Manual::Querying for everything a handle can do.
obtain
my $related = $row->obtain($link);
Like follow, but for a unique link: it returns the single related row (equivalent to $row->follow($link)->one). Croaks if the link is not unique.
my $book = $orm->connection->handle('book')->one(book_id => 10);
my $author = $book->obtain('author');
print $author->field('name'), "\n";
siblings
my $handle = $row->siblings($link_or_fields);
Returns a handle for rows that share the same values on the given link's local columns - this row's "siblings". You may pass a link spec (its local columns are used) or an explicit arrayref of field names. The result includes the original row.
# Other books by the same author (and this book too):
my $book = $orm->connection->handle('book')->one(book_id => 10);
my @same_author = $book->siblings([qw/author_id/])->all;
insert_related
$row->insert_related($link, \%row_data);
Insert a new related row across $link, automatically filling the linking columns from this row. You provide the rest of the data; do not include the linked columns yourself (it croaks if you do).
my $author = $orm->connection->handle('author')->one(author_id => 1);
$author->insert_related('books', {
title => 'New Book',
published => '2026-01-01',
# author_id is filled in automatically from $author
});
AUTOROW LINK ACCESSORS
When you enable autorow (see DBIx::QuickORM and DBIx::QuickORM::Manual::Schema), the generated row classes get named accessor methods for each link, so you rarely need to pass a link spec by hand:
A unique link generates a singular accessor that calls
obtainand returns the one related row.A non-unique link generates a plural accessor that calls
followand returns a handle.
my $author = $book->author; # unique link -> obtain, single row
my @books = $author->books->all; # non-unique link -> follow, a handle
The accessor names are derived automatically; you can control them with autoname link_accessor => sub { ... } as described in DBIx::QuickORM.
JOINS
Following links one row at a time issues a query per step. When you want a single query spanning multiple tables, build a join from a handle. The join methods on DBIx::QuickORM::Handle each take a link spec and return a new handle whose source is a DBIx::QuickORM::Join:
$h->join(@args)$h->left_join(@args)$h->right_join(@args)$h->inner_join(@args)$h->full_join(@args)$h->cross_join(@args)
The directional variants are shortcuts that set the join type; a single argument is taken as the link, otherwise pass key/value pairs (link, as, from, ...).
my $h = $orm->connection->handle('book');
# Books joined to their authors:
my $joined = $h->left_join('author');
for my $jrow ($joined->all) {
# ...
}
Fetching from a join yields DBIx::QuickORM::Join::Row objects. A join row holds the per-table pieces of each fetched record (the flat result is split back out per component table by the join), so you can reach the individual rows that made up the joined record. Each joined table is given a short alias; the first/primary table is the anchor and additional tables are added by the join methods. You can chain joins to span more than two tables, and use the "alias:link" form (or the from parameter) to control which already joined table a new link attaches to.
Joins have no primary key and are not directly cachable; they are a read-time construct for fetching related data efficiently. For details on the join source itself see DBIx::QuickORM::Join.
SEE ALSO
- DBIx::QuickORM::Manual
-
The documentation hub.
- DBIx::QuickORM::Manual::QuickStart
-
A fast end-to-end introduction, including following relations.
- DBIx::QuickORM::Manual::Schema
-
Defining links as part of a schema.
- DBIx::QuickORM::Manual::Querying
-
Working with the handles returned by
follow,siblings, and the join methods. - DBIx::QuickORM::Link
-
The link object: local/other tables and columns,
unique,key, and aliases. - DBIx::QuickORM
-
The
linkDSL reference andautorowlink accessors.
SOURCE
The source code repository for DBIx-QuickORM can be found at https://github.com/exodist/DBIx-QuickORM/.
MAINTAINERS
AUTHORS
COPYRIGHT
Copyright Chad Granum <exodist7@gmail.com>.
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.