package LIMS::Local::QueryLibrary;
use strict;
use warnings;
use Data::Dumper;
# use Data::Printer;
our $VERSION = 0.0.3; # CPAN version has not been updated since 2004
=head1 NAME
SQL::Library - A module for managing simple SQL libraries
stored in INI-like files.
=head1 VERSION
This document refers to version 0.0.3 of SQL::Library.
=head1 SYNOPSIS
Modification of CPAN SQL::Library - uses its new() and retr() methods and adds
a new function in new() to ensure unique entity_name entries. Original
SQL::Library silently ignored duplicate entries eg [find_stuff] .... [find_stuff]
and appended content of duplicate entry to content of initial entry:
$self->{'contents'}->{$curr_name} .= $_; # $curr_name = entity_name of SQL query
23/10/2017:
strip c-style comments from beginning of query; appends new-line so needs to be
removed
only includes retr() & elements(), not other methods such as set(), drop(), etc
=cut
sub new
{
my $proto = shift;
my $options = shift;
my $self = {
'options' => $options,
'contents' => undef
};
my $curr_name = '';
my @lib_arr = ();
if ( ref $self->{'options'}->{'lib'} eq 'ARRAY' )
{
# Could be a filehandle or a string.
if ( @{ $self->{'options'}->{'lib'} } == 1 )
{
@lib_arr = split /(?<=\n)/, $self->{'options'}->{'lib'}->[0];
}
else
{
@lib_arr = @{ $self->{'options'}->{'lib'} };
}
}
else
{
open LIB, $self->{'options'}->{'lib'}
or die "Cannot open $self->{'options'}->{'lib'}: $!";
@lib_arr = <LIB>;
close LIB;
}
#-------------------------------------------------------------------------------
my %seen = (); # new code to check for duplicate entries - see below
#-------------------------------------------------------------------------------
foreach ( @lib_arr ) # each line of library(s) content
{
next if m{^\s*$};
next if m{^\s*#};
next if m{^\s*//};
if ( m{^\[([^\]]+)\]} ) # gets entity_name of entry eg [find_stuff]
{
$curr_name = $1; # warn Dumper $curr_name;
#-------------------------------------------------------------------------------
die 'already have entry for ' . $curr_name if $seen{$curr_name}++;
#-------------------------------------------------------------------------------
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}; # strip c-style comments:
my $str = $self->{contents}->{$entity_name};
return strip_comments($str); # ignores queries without /* c-style comments */
#-------------------------------------------------------------------------------
}
sub elements
{
my $self = shift;
return sort keys %{$self->{'contents'}};
}
# http://perldoc.perl.org/perlfaq6.html#How-do-I-use-a-regular-expression-to-strip-C-style-comments-from-a-file%3f
sub strip_comments {
my $str = shift; # my $pre = $str; p $pre;
# short one-line version to remove /* comments */ only, need to remove
# remaining new-line marker or QueryLog dumps query to error.log
my $n = $str =~ s{/\*[^*]*\*+([^/*][^*]*\*+)*/}{defined $2 ? $2 : ""}gse; # p $n;
# remove any leading white-spaces before SELECT/UPDATE, etc (breaks QueryLog)
$str =~ s/^\s+//; # p $pre if $str ne $pre;
return $str;
=begin # long version:
$str =~ s{
/\* ## Start of /* ... */ comment
[^*]*\*+ ## Non-* followed by 1-or-more *'s
(
[^/*][^*]*\*+
)* ## 0-or-more things which don't start with / but do end with *
/ ## End of /* ... */ comment
| ## OR various things which aren't comments:
(
" ## Start of " ... " string
(
\\. ## Escaped char
| ## OR
[^"\\] ## Non "\
)*
" ## End of " ... " string
| ## OR
' ## Start of ' ... ' string
(
\\. ## Escaped char
| ## OR
[^'\\] ## Non '\
)*
' ## End of ' ... ' string
| ## OR
. ## Anything other char
[^/"'\\]* ## Chars which doesn't start a comment, string or escape
)
}{defined $2 ? $2 : ""}gxse; # p $pre if $str ne $pre;
# remove leading new-line left over from /* comment */ removal:
$str =~ s/^\s+//; # or breaks QueryLog and all queries go to Apache error log
return $str;
=cut
}
1;