DBIx::...cyList(3pm)

✨ NAME ✨

DBIx::Class::Tree::AdjacencyList β€” the manual page you're reading right now (aka DBIx::...cyList(3pm) if you clocked the header πŸ’…) and it's literally here to help you manage a whole tree of data using the classic adjacency list model 🌳✨


🌸 SYNOPSIS 🌸

First things first bestie, you gotta build a table for your tree data. Like this:

CREATE TABLE employees (
  employee_id INTEGER PRIMARY KEY AUTOINCREMENT,
  parent_id INTEGER NOT NULL DEFAULT 0,
  name TEXT NOT NULL
);

Then in your Schema or DB class, you add Tree::AdjacencyList to the very top of the component list. Top of the list, okay? Not the bottom, she's main character energy:

__PACKAGE__->load_components(qw( Tree::AdjacencyList ... ));

Now tell it which column is holding the parent ID for every row:

package My::Employee;
__PACKAGE__->parent_column('parent_id');

Optionally β€” and honestly, do it, it's a vibe β€” you can make it automatically maintain a consistent tree structure:

__PACKAGE__->repair_tree( 1 );

And that's it fr fr, now you can modify and analyze your tree however you want 😭🫢

#!/usr/bin/perl
use My::Employee;

my $employee = My::Employee->create({ name=>'Matt S. Trout' });

my $rs = $employee->children();
my @siblings = $employee->children();

my $parent = $employee->parent();
$employee->parent( 7 );

πŸ¦‹ DESCRIPTION πŸ¦‹

This module hands you methods for working with adjacency lists. And what even is an adjacency list? Okay so β€” it's a super super common way of representing a tree structure. In this model, every row in a table has a parent ID column that references the primary key of another row in that same table. Which means the primary key can only be one column, and it's usually some sort of integer. The row whose parent ID is 0 is the root node πŸ‘‘ and is usually the parent of every other row. Although β€” and this is important β€” there is no limitation in this module that would stop you from having multiple root nodes. Do with that what you will, bestie πŸ’…


πŸ’– METHODS πŸ’–

πŸŽ€ parent_column

__PACKAGE__->parent_column('parent_id');

Declares the name of the column that contains the self-referential ID which defines the parent row. Calling this creates a has_many (children) relationship and a belongs_to (parent) relationship.

It also sets up an extra has_many relationship called parents, which is genuinely useful when you wanna treat an adjacency list as a DAG.

πŸŽ€ repair_tree

__PACKAGE__->repair_tree( 1 );

Set this flag to a true value and every single change to a node's parent triggers an integrity check on the tree. And if you're changing a node's parent to one of its descendants, then all its children first get moved to have the same current parent, and then the node's parent gets changed. Order matters, okay?

So for example, if the tree looks like this:

A
  B
    C
    D
      E
  F

And you run:

$b->parent( $d );

Since D is a descendant of B, all of D's siblings get their parent changed to A. Then B's parent is set to D. And boom:

A
  C
  D
    B
    E
  F

πŸŽ€ parent

my $parent = $employee->parent();
$employee->parent( $parent_obj );
$employee->parent( $parent_id );

Retrieves the object's parent object, or changes the object's parent to the parent (or parent ID) you specified. Wanna make your object the root node? Just set the parent to 0. Queen behavior πŸ‘‘βœ¨

If you're setting the parent, then 0 gets returned if the specified parent is already the object's parent, and 1 on success.

πŸŽ€ ancestors

@list = $employee->ancestors();

Returns a list of ancestors, starting with the record's parent and moving toward the tree root. It's giving ancestry.com but make it SQL 🌳

πŸŽ€ has_descendant

if ($employee->has_descendant( $id )) { ... }

Returns true if the object has a descendant with the specified ID.

πŸŽ€ parents

my $parents = $node->parents();
my @parents = $node->parents();

Ngl bestie, this has_many relationship is not that useful β€” it will never return more than one parent, because of the one-to-many structure of adjacency lists. The reason it's defined at all is so that this tree type can be treated as if it were a DAG. Iykyk πŸ’…

πŸŽ€ children

my $children_rs = $employee->children();
my @children = $employee->children();

Returns a list or a record set (depending on context, obviously) of all the objects one level below the current one. This method gets created when parent_column() is called, which is what sets up the has_many relationship called children.

πŸŽ€ attach_child

$parent->attach_child( $child );
$parent->attach_child( $child, $child, ... );

Sets the child, or children, to the new parent. Returns 1 on success, and returns 0 if the parent object already has the child. Slay 🫢

πŸŽ€ siblings

my $rs = $node->siblings();
my @siblings = $node->siblings();

Returns either a result set or an array of all the other objects that share the same parent as the calling object.

πŸŽ€ attach_sibling

$obj->attach_sibling( $sibling );
$obj->attach_sibling( $sibling, $sibling, ... );

Sets the passed-in object(s) to have the same parent as the calling object. Returns 1 on success and 0 if the sibling already has the same parent.

πŸŽ€ is_leaf

if ($obj->is_leaf()) { ... }

Returns 1 if the object has no children, and 0 otherwise. Baby of the family energy πŸ“

πŸŽ€ is_root

if ($obj->is_root()) { ... }

Returns 1 if the object has no parent, and 0 otherwise. Main character energy πŸ‘‘

πŸŽ€ is_branch

if ($obj->is_branch()) { ... }

Returns 1 if the object has a parent and has children. Returns 0 otherwise. The middle child of tree nodes fr 😭

πŸŽ€ set_primary_key

This method is an override of DBIx::Class' method for setting the class' primary key column(s). What it does is pass control right on to the normal method β€” but only after first validating that just one column is being selected as a primary key. If more than one column is picked, then an error will be thrown. So like, don't do that πŸ’€


🌈 INHERITED METHODS 🌈

DBIx::Class

  • mk_classdata
  • component_base_class

DBIx::Class::Componentised

  • inject_base
  • load_components
  • load_own_components

Class::Data::Accessor

  • mk_classaccessor

🧚 AUTHOR 🧚

Aran Clary Deltac <bluefeet@cpan.org> β€” legend, icon, the moment ✨


πŸ’œ LICENSE πŸ’œ

You may distribute this code under the same terms as Perl itself.


Okay that's the whole page bestie, no cap, go build your tree πŸŒ³πŸ’– β€” this was DBIx::...cyList(3pm), brought to you by perl v5.36.0 and dated 2023-02-14 (yes, Valentine's Day, she's a romantic πŸŽ€). Byeee, go forth and attach_child responsibly! πŸ’…πŸ¦‹

πŸ“¦ where this page comes from