| DBIx::Tree - Perl module for generating a tree from a self-referential table |
DBIx::Tree - Perl module for generating a tree from a self-referential table
use DBIx::Tree;
# have DBIx::Tree build the necessary SQL from table & column names:
my $tree = new DBIx::Tree(connection => $dbh,
table => $table,
method => sub { disp_tree(@_) },
columns => [$id_col, $label_col, $parent_col],
start_id => $start_id);
$tree->traverse;
# alternatively, use your own custom SQL statement
my $sql = <<EOSQL; SELECT nodes.id, labels.label, nodes.parent_id FROM nodes INNER JOIN labels ON nodes.id = labels.node_id WHERE labels.type = 'preferred label' ORDER BY label ASC
EOSQL
my $tree = new DBIx::Tree(connection => $dbh,
sql => $sql,
method => sub { disp_tree(@_) },
columns => ['id', 'label', 'parent_id'],
start_id => $start_id);
$tree->traverse;
# or use an already prepared DBI statement handle:
my $sth = $dbh->prepare($sql);
my $tree = new DBIx::Tree(connection => $dbh,
sth => $sth,
method => sub { disp_tree(@_) },
columns => ['id', 'label', 'parent_id'],
start_id => $start_id);
$tree->traverse;
When you've got one of those nasty self-referential tables that you want to bust out into a tree, this is the module to check out. Assuming there are no horribly broken nodes in your tree and (heaven forbid) any circular references, this module will turn something like:
food food_id parent_id
================== ======= =========
Food 001 NULL
Beans and Nuts 002 001
Beans 003 002
Nuts 004 002
Black Beans 005 003
Pecans 006 004
Kidney Beans 007 003
Red Kidney Beans 008 007
Black Kidney Beans 009 007
Dairy 010 001
Beverages 011 010
Whole Milk 012 011
Skim Milk 013 011
Cheeses 014 010
Cheddar 015 014
Stilton 016 014
Swiss 017 014
Gouda 018 014
Muenster 019 014
Coffee Milk 020 011
into:
Food (001)
Dairy (010)
Beverages (011)
Coffee Milk (020)
Whole Milk (012)
Skim Milk (013)
Cheeses (014)
Cheddar (015)
Stilton (016)
Swiss (017)
Gouda (018)
Muenster (019)
Beans and Nuts (002)
Beans (003)
Black Beans (005)
Kidney Beans (007)
Red Kidney Beans (008)
Black Kidney Beans (009)
Nuts (004)
Pecans (006)
There are examples in the examples directory - one plain text example, and two Tk examples.
my $tree = new DBIx::Tree(connection => $dbh,
table => $table,
sql => $sql,
sth => $sth,
method => sub { disp_tree(@_) },
columns => [$id_col, $label_col, $parent_col],
start_id => $start_id,
threshold => $threshold,
match_data => $match_data,
limit => $limit
recursive => 1 || 0);
item: the name of the item
level (0-n): the nesting level of the item.
id: the unique id of the item.
parent_id: an array ref containing the geneology of parent id's
for the current item
parent_name: an array ref containing the geneology of parent name's
for the current item
If the 'threshold' parameter has been set (either via the new()
constructor or in the call to traverse()), the callback will only
occur if the tree item is 'threshold' or more levels deep in the
hierarchy.
item: the name of the item
level (0-n): the nesting level of the item.
id: the unique id of the item.
parent_id: an array ref containing the geneology of parent id's
for the current item
parent_name: an array ref containing the geneology of parent name's
for the current item
If the 'threshold' parameter has been set (either via the new()
constructor or in the call to traverse()), the callback will only
occur if the tree item is 'threshold' or more levels deep in the
hierarchy.
id_col: The name of the column containing the unique id.
label_col: The name of the column containing the textual data
of the row, like a name.
parent_col: The name of the column containing the id of the
row's parent.
Optional additional columns; note that these will only be used in queries built by DBIx::Tree from 'table' specifications - i.e. they will not be used with 'sth'- or 'sql'-type query parameters (presumably you can provide this functionality yourself when using one of those query types).
order_col: The name of a column to use for ordering the results;
defaults to the column name specified by label_col.
This column name does not need to exist in the result
set, but should exist in the table being queried.
order_dir: An SQL directive specifying the directionality of the
ordering; for most databases this is either 'ASC' or
'DESC'. The default is an empty string, which leaves
the decision to the database (in most cases, this will
be ascending)
traverse(%args)new() constructor.
Graceful handling of circular references. Better docs. Rewrite the algorithm. Separate data acquisition from data formatting.
Brian Jepson, bjepson@ids.net
This module was inspired by the Expanding Hierarchies example that I stumbled across in the Microsoft SQL Server Database Developer's Companion section of the Microsoft SQL Server Programmer's Toolkit.
Jan Mach <machj@ders.cz> contributed substantial performance improvements, ordering handling for tree output, and other bug fixes.
Aaron Mackey <amackey@virginia.edu> has continued active development on the module based on Brian Jepson's version 0.91 release.
perl(1). DBI(3). Tk(3).
| DBIx::Tree - Perl module for generating a tree from a self-referential table |