CGI::Widget::DBI::Browse - Database browsing widget


  use CGI;
  use CGI::Widget::DBI::Browse;

  my $q = CGI->new;
  my $wb = CGI::Widget::DBI::Browse->new(
    q => $q,
    # database connection info
    -dbi_connect_dsn => 'DBI:Pg:dbname=my_pg_database;host=localhost',
    -dbi_user => 'pguser',
    -dbi_pass => 'pgpass',
    # database schema info
    -sql_table => 'table1 t1 inner join table2 t2 using (key_col)',
    -sql_retrieve_columns => [ qw/ t1.description t2.extra_information/ ],
  # or if you already have a search widget, you can use the settings from it
  # my $wb = CGI::Widget::DBI::Browse->new(ws => $search_widget_obj);

  # list of category columns (how to represent data as a tree)
  $wb->{-category_columns} = [ qw/main_category sub_category1 sub_category2/ ];

  # output to browser
  print $q->header;
  print $q->start_html;

  # show current page in tree
  #  (default is a list of distinct values in the first category_column)
  print $wb->display_results();

  print $q->end_html;


Implements user-interface for browsing a database table or joined tables. Just provide a list of hierarchical categories for your data, and it allows the user to walk down the category tree to find the database records they want.

Specifically, this module simply makes successive calls to the search widget module (CGI::Widget::DBI::Search) filtering results by the category of records the user is currently viewing (node in a tree representation of your data).



Creates and initializes a new CGI::Widget::DBI::Browse object.

Possible configuration options:

Database connection options
  -dbi_connect_dsn      => DBI data source name (full connection string)
  -dbi_user             => database username
  -dbi_pass             => database password
  -dbi_host             => host to connect to database (overridden by -dbi_connect_dsn)
  -sql_database         => database to connect to (overridden by -dbi_connect_dsn)
Database retrieval options
  -sql_table            => Database table(s) to query,
  -sql_table_columns    => [ARRAY] List of all columns in sql_table,
  -sql_retrieve_columns => [ARRAY] List of columns for retrieval,

  ... Also accepts all the options that CGI::Widget::DBI::Search does;
      they are simply passed through ...
Schema description configuration
  -category_columns     => [ARRAY] List of columns to be used as "categories,"
                           or internal nodes, allowing hierarchical navigation of
                           a tree-based representation of your data
                        => {HASH} Extra columns to be retrieved for a given category
                           column.  Keys should be a subset of -category_columns, and
                           values should be an arrayref containing the extra columns
                           (or column aliases) to retrieve for that category column.
                           Typically used in conjunction with -category_column_closures.
                        => {HASH} of (CODE): Reference to a hash containing a code
                           reference for each category column which should be passed 
                           through before displaying.  Similar to the -columndata_closures
                           option of CGI::Widget::DBI::Search.
Search result display options
                        => Maximum number of database records to display
                           on a page while navigating by category (default: 100)
  -skip_to_results      => If true, skips directly to display of database records
                           while in category browsing mode
  -auto_skip_to_results => If set, skips directly to results if in category browsing mode
                           but there are no category members at the current level, or if
                           there is exactly one category member with value '' (empty string).
                           Note: this will have no effect if the search widget ('ws' object)
                           is not set to -show_total_numresults.
                        => (CODE): If set along with -auto_skip_to_results, and auto-skip
                           mode is in effect, this callback routine will be called before
                           the actual search and displaying results are executed.  Useful
                           when behavior of the widget is dependent on whether we are
                           browsing or not. (i.e. the return value of is_browsing())
Performance options
  -cache_categories     => Turn on automatic caching of categories.  Creates a table
                           called browse_widget_category_cache which stores records
                           for each internal node in the browse tree.
                           BEWARE: currently there is no cache expiration mechanism;
                           also, the the cache table is a hard-coded name, so be careful
                           if you use more than one browse widget in the same database.



Returns true if the widget is in browse mode, viewing navigable categories (branch nodes) rather than viewing actual results (leaf nodes). Returns the actual category column name currently browsing on.


Returns the previous category column in -category_columns relative to the node currently being viewed. If we are at the top-level category (root node in the browse tree), then this method returns undef.


Returns a list of all previous category columns in -category_columns relative to the current node. If we are the root node, an empty list is returned.


Displays results from CGI::Widget::DBI::Search (in grid display mode) of data values specified by -category_columns and current state of query object in object variable 'q'.


category_value_is_cached($category, $value)

Returns true if cache entries exist in the category cache table for the key/value pair $category/$value.

cache_results_for_category_value($category, $value)

Executes a category search as normal, using CGI::Widget::DBI::Search in -dry_run mode to just generate the SQL, and stores the results in category cache table.



Main rendering method of the database browse. Typically this is the only method that actually *needs* to be called from the delegating class, after configuration, since this calls all other methods as necessary.


Displays a node in the browse tree, identically to how display_results() would, only by using the cache table. Specifically, it configures the search widget by directly injecting data retrieved from the cache table and calling the search widget's display_results() method, skipping the call to its search() method. Also, if there is no cache entry for the current node in the browse tree, this calls cache_results_for_category_value() first to cache the results.

Note: this method is called automatically by display_results() if -cache_categories is true.


Appends breadcrumb navigation HTML to the -optional_header of the enclosed search widget object based on the current state of the browse widget. Also sets the 'category_title' object of this browse widget object to a string representation of the current location in the browse tree.

Note: this method is called automatically by display_results().

Emits an href link to the requested $category_col in the browse tree for the category data from $row. This is typically used as a callback from a column's -columndata_closures rendering. E.g.

  $wb->{ws}->{-columndata_closures}->{'state_or_province'} = sub {
      my ($obj, $row) = @_;
      return $obj->{b}->link_for_category_column('state_or_province', $row);

For it to work as expected, all columns listed in -category_columns must also be in the select results, i.e. present in -sql_retrieve_columns.


Adi Fairbank <>


Copyright (C) 2008-2014 Adi Fairbank


This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License along with this program. If not, see <>.


Dec 7, 2014

2 POD Errors

The following errors were encountered while parsing the POD:

Around line 73:

You forgot a '=back' before '=head2'

Around line 75:

'=item' outside of any '=over'