File Coverage

blib/lib/SQL/Statement/Function.pm
Criterion Covered Total %
statement 121 132 91.6
branch 14 28 50.0
condition 4 4 100.0
subroutine 27 28 96.4
pod n/a
total 166 192 86.4


line stmt bran cond sub pod time code
1             package SQL::Statement::Function;
2              
3             ######################################################################
4             #
5             # This module is copyright (c), 2009-2017 by Jens Rehsack.
6             # All rights reserved.
7             #
8             # It may be freely distributed under the same terms as Perl itself.
9             # See below for help and copyright information (search for SYNOPSIS).
10             #
11             ######################################################################
12              
13 16     16   55 use strict;
  16         21  
  16         416  
14 16     16   85 use warnings FATAL => "all";
  16         17  
  16         480  
15 16     16   55 use vars qw(@ISA $VERSION);
  16         16  
  16         559  
16              
17 16     16   61 use SQL::Statement::Term ();
  16         17  
  16         1113  
18             @ISA = qw(SQL::Statement::Term);
19              
20             $VERSION = '1.412';
21              
22             =pod
23              
24             =head1 NAME
25              
26             SQL::Statement::Function - abstract base class for all function executing terms
27              
28             =head1 SYNOPSIS
29              
30             # this class doesn't have a common constructor, because all derived classes
31             # have their special requirements
32              
33             =head1 DESCRIPTION
34              
35             SQL::Statement::Function is an abstract base class providing the interface
36             for all function executing terms.
37              
38             =head1 INHERITANCE
39              
40             SQL::Statement::Function
41             ISA SQL::Statement::Term
42              
43             =head1 METHODS
44              
45             =head2 DESTROY
46              
47             Destroys the term and undefines the weak reference to the owner as well
48             as the reference to the parameter list.
49              
50             =cut
51              
52             sub DESTROY
53             {
54 332     332   272 my $self = $_[0];
55              
56 332         688 undef $self->{PARAMS};
57              
58 332         668 $self->SUPER::DESTROY();
59             }
60              
61             package SQL::Statement::Function::UserFunc;
62              
63 16     16   56 use vars qw(@ISA);
  16         17  
  16         482  
64              
65 16     16   63 use Carp ();
  16         16  
  16         252  
66 16     16   48 use Params::Util qw(_INSTANCE);
  16         20  
  16         613  
67              
68 16     16   7111 use SQL::Statement::Functions;
  16         35  
  16         5355  
69              
70             @ISA = qw(SQL::Statement::Function);
71              
72             =pod
73              
74             =head1 NAME
75              
76             SQL::Statement::Function::UserFunc - implements executing a perl subroutine
77              
78             =head1 SYNOPSIS
79              
80             # create an user function term with an SQL::Statement object as owner,
81             # specifying the function name, the subroutine name (full qualified)
82             # and the parameters to the subroutine
83             my $term = SQL::Statement::Function::UserFunc->new( $owner, $name, $sub, \@params );
84             # access the result of that operation
85             $term->value( $eval );
86              
87             =head1 DESCRIPTION
88              
89             SQL::Statement::Function::UserFunc implements a term which returns the result
90             of the specified subroutine.
91              
92             =head1 INHERITANCE
93              
94             SQL::Statement::Function
95             ISA SQL::Statement::Term
96              
97             =head1 METHODS
98              
99             =head2 new
100              
101             Instantiates a new C instance.
102              
103             =head2 value
104              
105             Invokes the given subroutine with the values of the params and return it's
106             result:
107              
108             my @params = map { $_->value($eval); } @{ $self->{PARAMS} };
109             return $subpkg->$subname( $self->{OWNER}, @params );
110              
111             =cut
112              
113             sub new
114             {
115 271     271   335 my ( $class, $owner, $name, $subnm, $params ) = @_;
116              
117 271         601 my $self = $class->SUPER::new($owner);
118              
119 271         1278 my ( $pkg, $sub ) = $subnm =~ m/^(.*::)([^:]+$)/;
120 271 100       470 if ( !$sub )
121             {
122 2         4 $sub = $subnm;
123 2         4 $pkg = 'main';
124             }
125 271         724 $pkg =~ s/::$//g;
126 271 50       420 $pkg = 'main' unless ($pkg);
127              
128 271         322 $self->{SUB} = $sub;
129 271         269 $self->{PKG} = $pkg;
130 271         272 $self->{NAME} = $name;
131 271         275 $self->{PARAMS} = $params;
132              
133 271 50       1173 unless ( UNIVERSAL::can( $pkg, $sub ) )
134             {
135 0 0       0 unless ( 'main' eq $pkg )
136             {
137 0         0 my $mod = $pkg;
138 0         0 $mod =~ s|::|/|g;
139 0         0 $mod .= '.pm';
140 0 0       0 eval { require $mod; } unless ( defined( $INC{$mod} ) );
  0         0  
141 0 0       0 return $owner->do_err($@) if ($@);
142             }
143              
144 0 0       0 $pkg->can($sub) or return $owner->do_err( "Can't find subroutine $pkg" . "::$sub" );
145             }
146              
147 271         655 return $self;
148             }
149              
150             sub value($)
151             {
152 240     240   213 my $self = $_[0];
153 240         181 my $eval = $_[1];
154 240         268 my $pkg = $self->{PKG};
155 240         190 my $sub = $self->{SUB};
156 240         158 my @params = map { $_->value($eval); } @{ $self->{PARAMS} };
  341         1031  
  240         277  
157 240         1793 return $pkg->$sub( $self->{OWNER}, @params ); # FIXME is $pkg just a string?
158             }
159              
160             package SQL::Statement::Function::NumericEval;
161              
162 16     16   79 use vars qw(@ISA);
  16         21  
  16         705  
163              
164 16     16   70 use Params::Util qw(_NUMBER _INSTANCE);
  16         16  
  16         4468  
165              
166             @ISA = qw(SQL::Statement::Function);
167              
168             =pod
169              
170             =head1 NAME
171              
172             SQL::Statement::Function::NumericEval - implements numeric evaluation of a term
173              
174             =head1 SYNOPSIS
175              
176             # create an user function term with an SQL::Statement object as owner,
177             # specifying the expression to evaluate and the parameters to the subroutine
178             my $term = SQL::Statement::NumericEval->new( $owner, $expr, \@params );
179             # access the result of that operation
180             $term->value( $eval );
181              
182             =head1 DESCRIPTION
183              
184             SQL::Statement::Function::NumericEval implements the numeric evaluation of a
185             term. All parameters are expected to be numeric.
186              
187             =head1 INHERITANCE
188              
189             SQL::Statement::Function::NumericEval
190             ISA SQL::Statement::Function
191             ISA SQL::Statement::Term
192              
193             =head1 METHODS
194              
195             =head2 new
196              
197             Instantiates a new C instance.
198             Takes I<$owner>, I<$expr> and I<\@params> as arguments (in specified order).
199              
200             =head2 value
201              
202             Returns the result of the evaluated expression.
203              
204             =cut
205              
206             sub new
207             {
208 41     41   53 my ( $class, $owner, $expr, $params ) = @_;
209              
210 41         102 my $self = $class->SUPER::new($owner);
211              
212 41         48 $self->{EXPR} = $expr;
213 41         45 $self->{PARAMS} = $params;
214              
215 41         73 return $self;
216             }
217              
218             sub value($)
219             {
220 171     171   167 my ( $self, $eval ) = @_;
221             my @vals =
222 171 50       121 map { _INSTANCE( $_, 'SQL::Statement::Term' ) ? $_->value($eval) : $_ } @{ $self->{PARAMS} };
  395         1545  
  171         196  
223 171         218 foreach my $val (@vals)
224             {
225 395 50       758 return $self->{OWNER}->do_err(qq~Bad numeric expression '$val'!~)
226             unless ( defined( _NUMBER($val) ) );
227             }
228 171         185 my $expr = $self->{EXPR};
229 171         1209 $expr =~ s/\?(\d+)\?/$vals[$1]/g;
230 171         450 $expr =~ s/\s//g;
231 171         378 $expr =~ s/^([\)\(+\-\*\/\%0-9]+)$/$1/; # untaint
232 171         6274 return eval $expr;
233             }
234              
235             package SQL::Statement::Function::Trim;
236              
237 16     16   82 use vars qw(@ISA);
  16         26  
  16         592  
238              
239 16     16   4695 BEGIN { @ISA = qw(SQL::Statement::Function); }
240              
241             =pod
242              
243             =head1 NAME
244              
245             SQL::Statement::Function::Trim - implements the built-in trim function support
246              
247             =head1 SYNOPSIS
248              
249             # create an trim function term with an SQL::Statement object as owner,
250             # specifying the spec, char and the parameters to the subroutine
251             my $term = SQL::Statement::Trim->new( $owner, $spec, $char, \@params );
252             # access the result of that operation
253             $term->value( $eval );
254              
255             =head1 DESCRIPTION
256              
257             SQL::Statement::Function::Trim implements string trimming.
258              
259             =head1 INHERITANCE
260              
261             SQL::Statement::Function::Trim
262             ISA SQL::Statement::Function
263             ISA SQL::Statement::Term
264              
265             =head1 METHODS
266              
267             =head2 new
268              
269             Instantiates a new C instance.
270             Takes I<$owner>, I<$spec>, I<$char> and I<\@params> as arguments
271             (in specified order).
272              
273             Meaning of the parameters:
274              
275             =over 4
276              
277             =item I<$spec>
278              
279             Can be on of 'LEADING', 'TRAILING' 'BOTH'. Trims the leading chars, trailing
280             chars or at both ends, respectively.
281              
282             Defaults to 'BOTH'.
283              
284             =item I<$char>
285              
286             The character to trim - defaults to C<' '>
287              
288             =item I<\@params>
289              
290             Expected to be an array with exact 1 element (more aren't evaluated).
291              
292             =back
293              
294             =head2 value
295              
296             Returns the trimmed value of first parameter argument.
297              
298             =cut
299              
300             sub new
301             {
302 10     10   17 my ( $class, $owner, $spec, $char, $params ) = @_;
303 10   100     44 $spec ||= 'BOTH';
304 10   100     48 $char ||= ' ';
305              
306 10         34 my $self = $class->SUPER::new($owner);
307              
308 10         16 $self->{PARAMS} = $params;
309 1     1   2 $self->{TRIMFN} = sub { my $s = $_[0]; $s =~ s/^$char*//g; return $s; }
  1         14  
  1         2  
310 10 100       36 if ( $spec =~ m/LEADING/ );
311 0     0   0 $self->{TRIMFN} = sub { my $s = $_[0]; $s =~ s/$char*$//g; return $s; }
  0         0  
  0         0  
312 10 100       22 if ( $spec =~ m/TRAILING/ );
313 2     2   4 $self->{TRIMFN} = sub { my $s = $_[0]; $s =~ s/^$char*//g; $s =~ s/$char*$//g; return $s; }
  2         28  
  2         21  
  2         4  
314 10 100       43 if ( $spec =~ m/BOTH/ );
315              
316 10         27 return $self;
317             }
318              
319             sub value($)
320             {
321 3     3   9 my $val = $_[0]->{PARAMS}->[0]->value( $_[1] );
322 3         4 $val = &{ $_[0]->{TRIMFN} }($val);
  3         6  
323 3         8 return $val;
324             }
325              
326             package SQL::Statement::Function::SubString;
327              
328 16     16   75 use vars qw(@ISA);
  16         17  
  16         3060  
329              
330             @ISA = qw(SQL::Statement::Function);
331              
332             =pod
333              
334             =head1 NAME
335              
336             SQL::Statement::Function::SubString - implements the built-in sub-string function support
337              
338             =head1 SYNOPSIS
339              
340             # create an substr function term with an SQL::Statement object as owner,
341             # specifying the start and length of the sub string to extract from the
342             # first element of \@params
343             my $term = SQL::Statement::SubString->new( $owner, $start, $length, \@params );
344             # access the result of that operation
345             $term->value( $eval );
346              
347             =head1 DESCRIPTION
348              
349             SQL::Statement::Function::SubString implements a sub-string extraction term.
350              
351             =head1 INHERITANCE
352              
353             SQL::Statement::Function::SubString
354             ISA SQL::Statement::Function
355             ISA SQL::Statement::Term
356              
357             =head1 METHODS
358              
359             =head2 new
360              
361             Instantiates a new C instance.
362             Takes I<$owner>, I<$start>, I<$length> and I<\@params> as arguments
363             (in specified order).
364              
365             Meaning of the parameters:
366              
367             =over 4
368              
369             =item I<$start>
370              
371             Specifies the start position to extract the sub-string. This is expected
372             to be a L instance. The first character in a string
373             has the position 1.
374              
375             =item I<$length>
376              
377             Specifies the length of the extracted sub-string. This is expected
378             to be a L instance.
379              
380             If omitted, everything to the end of the string is returned.
381              
382             =item I<\@params>
383              
384             Expected to be an array with exact 1 element (more aren't evaluated).
385              
386             =back
387              
388             =head2 value
389              
390             Returns the extracted sub-string value from first parameter argument.
391              
392             =cut
393              
394             sub new
395             {
396 3     3   4 my ( $class, $owner, $start, $length, $params ) = @_;
397              
398 3         19 my $self = $class->SUPER::new($owner);
399              
400 3         6 $self->{START} = $start;
401 3         6 $self->{LENGTH} = $length;
402 3         4 $self->{PARAMS} = $params;
403              
404 3         8 return $self;
405             }
406              
407             sub value($)
408             {
409 5     5   12 my $val = $_[0]->{PARAMS}->[0]->value( $_[1] );
410 5         13 my $start = $_[0]->{START}->value( $_[1] ) - 1;
411             my $length =
412 5 50       14 defined( $_[0]->{LENGTH} ) ? $_[0]->{LENGTH}->value( $_[1] ) : length($val) - $start;
413 5         11 return substr( $val, $start, $length );
414             }
415              
416             package SQL::Statement::Function::StrConcat;
417              
418 16     16   77 use vars qw(@ISA);
  16         20  
  16         2989  
419              
420             @ISA = qw(SQL::Statement::Function);
421              
422             =pod
423              
424             =head1 NAME
425              
426             SQL::Statement::Function::StrConcat - implements the built-in string concatenation
427              
428             =head1 SYNOPSIS
429              
430             # create an substr function term with an SQL::Statement object as owner
431             # and \@params to concatenate
432             my $term = SQL::Statement::StrConcat->new( $owner, \@params );
433             # access the result of that operation
434             $term->value( $eval );
435              
436             =head1 DESCRIPTION
437              
438             SQL::Statement::Function::StrConcat implements a string concatenation term.
439              
440             =head1 INHERITANCE
441              
442             SQL::Statement::Function::StrConcat
443             ISA SQL::Statement::Function
444             ISA SQL::Statement::Term
445              
446             =head1 METHODS
447              
448             =head2 new
449              
450             Instantiates a new C instance.
451              
452             =head2 value
453              
454             Returns the concatenated string composed of the parameter values.
455              
456             =cut
457              
458             sub new
459             {
460 7     7   19 my ( $class, $owner, $params ) = @_;
461              
462 7         35 my $self = $class->SUPER::new($owner);
463              
464 7         14 $self->{PARAMS} = $params;
465              
466 7         18 return $self;
467             }
468              
469             sub value($)
470             {
471 4009     4009   2801 my $rc = '';
472 4009         2395 foreach my $val ( @{ $_[0]->{PARAMS} } )
  4009         4765  
473             {
474 3         8 my $catval = $val->value( $_[1] );
475 3 50       377 $rc .= defined($catval) ? $catval : '';
476             }
477 4009         8991 return $rc;
478             }
479              
480             =head1 AUTHOR AND COPYRIGHT
481              
482             Copyright (c) 2009-2017 by Jens Rehsack: rehsackATcpan.org
483              
484             All rights reserved.
485              
486             You may distribute this module under the terms of either the GNU
487             General Public License or the Artistic License, as specified in
488             the Perl README file.
489              
490             =cut
491              
492             1;