http://qs321.pair.com?node_id=185917
Category: Text Processing
Author/Contact Info DamnDirtyApe <douggorley@shaw.ca>
Description: I wrote this module because I wanted a super-simple way to separate my SQL queries from my application code.
package INI::Library ;

=head1 NAME

INI::Library - A module for managing simple libraries
stored in INI-like files.

=head1 SYNOPSIS

  use INI::Library ;
    
  my $sql = new INI::Library { lib => 'sql.lib' } ;

  ## Ask for a library entry by name...
  my $query = $sql->retr( 'some_sql_query' ) ;

  ## Add or update an entry...
  $sql->set( 'yet_another_query', <<'END' ) ;
  SELECT foo
  FROM   bar
  WHERE  zoot = 1
  END

  ## Remove an entry from the library...
  $sql->drop( 'one_more_query' ) ;

  ## List the entries in the library...
  print join( ' : ', $sql->elements ), "\n" ;

  ## Dump the contents of the library to a string...
  my $lib_str = $sql->ini_out ;

  ## Write the INI library to disk...
  $sql->write ;

=head1 LIBRARY FILE FORMAT

The format for the library files looks a little like an INI file (henc
+e
the name.)  However, unlike an INI file, it does not handle key=value 
+pairs
which are divided into sections.  Library entry names are on a line by
themselves, enclosed in square brackets.  Whatever occurs until the
next title tag is the value of the library entry.  Blank lines, pound
signs (#) and C++ style comments (//) are all discarded.

A sample library file might look like this:

  ## A sample library file

  [get_survey_questions]
  select   question_no,
           question_text
  from     question
  where    survey_id = ?
  order by question_no

  [get_survey_info]
  select title,
         date_format( open_date, '%Y%m%d' ) as open_date, 
         date_format( close_date, '%Y%m%d' ) as close_date, 
         template_file
  from   survey
  where  survey_id = ?


=cut

use strict ;
use warnings ;

=head1 OBJECT METHODS

=over 4

=item PACKAGE-E<gt>new( HASHREF )

Create a new library handle.  Currently, the only argument supported i
+n
the hashref is C<lib>, which refers to the file containing the INI
library.

=cut

sub new
{
    my $proto = shift ;
    my $options = shift ;
    my $self = {
                 'options'  => $options,
                 'contents' => undef
               } ;
    {
        my $curr_name = '' ;
        open INI, $self->{'options'}->{'lib'}
          or die "Cannot open $self->{'options'}->{'lib'}: $!" ;
        while ( <INI> )
        {
            next if m{^\s*$} ;
            next if m{^\s*#} ;
            next if m{^\s*//} ;
            if ( m{^\[([^\]]+)\]} )
            {
                $curr_name = $1 ;
                next ;
            }
            if ( $curr_name )
            {
                $self->{'contents'}->{$curr_name} .= $_ ;
            }
        }
    }
    bless $self, $proto ;
    return $self ;
}

=item $OBJ-E<gt>retr( NAME )

Returns the library entry referenced by NAME.

=cut 

sub retr
{
    my ( $self, $entity_name ) = @_ ;
    return $self->{'contents'}->{$entity_name} ;
}

=item $OBJ-E<gt>set( NAME, VALUE )

Sets the library entry NAME to VALUE.  This is used both to create new
library entries and to update existing ones.

=cut

sub set
{
    my ( $self, $entity_name, $entity ) = @_ ;
    $self->{'contents'}->{$entity_name} = $entity ;
    return $self ;
}

=item $OBJ-E<gt>drop( NAME )

Drops entry NAME form the library.

=cut

sub drop
{
    my ( $self, $entity_name ) = @_ ;
    delete $self->{'contents'}->{$entity_name} ;
    return $self ;
}

=item $OBJ-E<gt>elements

Returns a list of all entry names in the library.

=cut 

sub elements
{
    my $self = shift ;
    return sort keys %{$self->{'contents'}} ;
}

=item $OBJ-E<gt>ini_out

Returns a string containing the library contents in the same
INI format that the module reads from.

=cut 

sub ini_out
{
    my $self   = shift ;
    my $output = '' ;
    foreach ( sort keys %{$self->{'contents'}} )
    {
        $output .= sprintf "[%s]\n%s\n", $_, $self->{'contents'}->{$_}
+ ;
    }
    return $output ;
}

=item $OBJ-E<gt>write

Writes the library to the file named in C<lib>.

=cut

sub write
{
    my $self = shift ;
    open OUT, ">$self->{'options'}->{'lib'}"
      or die "Cannot open $self->{'options'}->{'lib'}: $!" ;
    print OUT $self->ini_out ;
    close OUT ;
}

=back

=head1 AUTHOR

Doug Gorley E<lt>douggorley@shaw.caE<gt>

=cut

1 ;

__END__
Replies are listed 'Best First'.
Re: INI::Library
by simon.proctor (Vicar) on Jul 29, 2002 at 11:24 UTC
    Hi,

    I was thinking about your package name and was wondering whether you would consider Library::INI or Library::Config::Ini. Because then you have the kind of namespace you could add to if need be (as your project grows for example). You could also call it Config::Ini and pair it up with Config::IniFiles (where that uses name=value pairs) though I personally wouldn't :P. Nice snippet though :)
Re: INI::Library
by gav^ (Curate) on Jul 29, 2002 at 17:46 UTC
    I quite like your idea, it's nice and lightweight. One suggestion might be to change the name to be in the SQL:: namespace so it is easier to find.

    Other other interesting modules that try to solve this problem (not embedding SQL in your perl scripts) include SQL::Catalog, SQL::Snippet, DBIx::Librarian, and Ima::DBI.

    gav^