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 = ; 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-Eretr( 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 introduced by regex substitution - WTF !!! $str =~ s/^\s+//; # or breaks QueryLog and all queries go to Apache error log return $str; =cut } 1;