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-2020 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   103 use strict;
  16         29  
  16         474  
14 16     16   75 use warnings FATAL => "all";
  16         28  
  16         530  
15 16     16   192 use vars qw(@ISA $VERSION);
  16         25  
  16         624  
16              
17 16     16   90 use SQL::Statement::Term ();
  16         27  
  16         1288  
18             @ISA = qw(SQL::Statement::Term);
19              
20             $VERSION = '1.414';
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 does not 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   717 my $self = $_[0];
55              
56 332         1064 undef $self->{PARAMS};
57              
58 332         955 $self->SUPER::DESTROY();
59             }
60              
61             package SQL::Statement::Function::UserFunc;
62              
63 16     16   93 use vars qw(@ISA);
  16         28  
  16         659  
64              
65 16     16   104 use Carp ();
  16         28  
  16         343  
66 16     16   73 use Params::Util qw(_INSTANCE);
  16         27  
  16         768  
67              
68 16     16   8582 use SQL::Statement::Functions;
  16         46  
  16         5975  
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   643 my ( $class, $owner, $name, $subnm, $params ) = @_;
116              
117 271         727 my $self = $class->SUPER::new($owner);
118              
119 271         1676 my ( $pkg, $sub ) = $subnm =~ m/^(.*::)([^:]+$)/;
120 271 100       719 if ( !$sub )
121             {
122 2         4 $sub = $subnm;
123 2         5 $pkg = 'main';
124             }
125 271         1173 $pkg =~ s/::$//g;
126 271 50       621 $pkg = 'main' unless ($pkg);
127              
128 271         545 $self->{SUB} = $sub;
129 271         483 $self->{PKG} = $pkg;
130 271         515 $self->{NAME} = $name;
131 271         420 $self->{PARAMS} = $params;
132              
133 271 50       1623 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         982 return $self;
148             }
149              
150             sub value($)
151             {
152 240     240   381 my $self = $_[0];
153 240         364 my $eval = $_[1];
154 240         397 my $pkg = $self->{PKG};
155 240         371 my $sub = $self->{SUB};
156 240         351 my @params = map { $_->value($eval); } @{ $self->{PARAMS} };
  341         1354  
  240         494  
157 240         2263 return $pkg->$sub( $self->{OWNER}, @params ); # FIXME is $pkg just a string?
158             }
159              
160             package SQL::Statement::Function::NumericEval;
161              
162 16     16   125 use vars qw(@ISA);
  16         28  
  16         833  
163              
164 16     16   175 use Params::Util qw(_NUMBER _INSTANCE);
  16         38  
  16         5677  
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   113 my ( $class, $owner, $expr, $params ) = @_;
209              
210 41         119 my $self = $class->SUPER::new($owner);
211              
212 41         92 $self->{EXPR} = $expr;
213 41         86 $self->{PARAMS} = $params;
214              
215 41         103 return $self;
216             }
217              
218             sub value($)
219             {
220 171     171   328 my ( $self, $eval ) = @_;
221             my @vals =
222 171 50       252 map { _INSTANCE( $_, 'SQL::Statement::Term' ) ? $_->value($eval) : $_ } @{ $self->{PARAMS} };
  395         2052  
  171         366  
223 171         359 foreach my $val (@vals)
224             {
225 395 50       1071 return $self->{OWNER}->do_err(qq~Bad numeric expression '$val'!~)
226             unless ( defined( _NUMBER($val) ) );
227             }
228 171         329 my $expr = $self->{EXPR};
229 171         1500 $expr =~ s/\?(\d+)\?/$vals[$1]/g;
230 171         748 $expr =~ s/\s//g;
231 171         626 $expr =~ s/^([\)\(+\-\*\/\%0-9]+)$/$1/; # untaint
232 171         7712 return eval $expr;
233             }
234              
235             package SQL::Statement::Function::Trim;
236              
237 16     16   136 use vars qw(@ISA);
  16         42  
  16         769  
238              
239 16     16   6182 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 are not 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   29 my ( $class, $owner, $spec, $char, $params ) = @_;
303 10   100     34 $spec ||= 'BOTH';
304 10   100     36 $char ||= ' ';
305              
306 10         40 my $self = $class->SUPER::new($owner);
307              
308 10         19 $self->{PARAMS} = $params;
309 1     1   2 $self->{TRIMFN} = sub { my $s = $_[0]; $s =~ s/^$char*//g; return $s; }
  1         23  
  1         3  
310 10 100       54 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       27 if ( $spec =~ m/TRAILING/ );
313 2     2   5 $self->{TRIMFN} = sub { my $s = $_[0]; $s =~ s/^$char*//g; $s =~ s/$char*$//g; return $s; }
  2         43  
  2         26  
  2         8  
314 10 100       48 if ( $spec =~ m/BOTH/ );
315              
316 10         26 return $self;
317             }
318              
319             sub value($)
320             {
321 3     3   55 my $val = $_[0]->{PARAMS}->[0]->value( $_[1] );
322 3         8 $val = &{ $_[0]->{TRIMFN} }($val);
  3         9  
323 3         11 return $val;
324             }
325              
326             package SQL::Statement::Function::SubString;
327              
328 16     16   115 use vars qw(@ISA);
  16         35  
  16         4029  
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 are not 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   10 my ( $class, $owner, $start, $length, $params ) = @_;
397              
398 3         22 my $self = $class->SUPER::new($owner);
399              
400 3         8 $self->{START} = $start;
401 3         7 $self->{LENGTH} = $length;
402 3         5 $self->{PARAMS} = $params;
403              
404 3         9 return $self;
405             }
406              
407             sub value($)
408             {
409 5     5   17 my $val = $_[0]->{PARAMS}->[0]->value( $_[1] );
410 5         17 my $start = $_[0]->{START}->value( $_[1] ) - 1;
411             my $length =
412 5 50       17 defined( $_[0]->{LENGTH} ) ? $_[0]->{LENGTH}->value( $_[1] ) : length($val) - $start;
413 5         16 return substr( $val, $start, $length );
414             }
415              
416             package SQL::Statement::Function::StrConcat;
417              
418 16     16   117 use vars qw(@ISA);
  16         46  
  16         3163  
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   26 my ( $class, $owner, $params ) = @_;
461              
462 7         48 my $self = $class->SUPER::new($owner);
463              
464 7         19 $self->{PARAMS} = $params;
465              
466 7         24 return $self;
467             }
468              
469             sub value($)
470             {
471 4009     4009   5723 my $rc = '';
472 4009         5117 foreach my $val ( @{ $_[0]->{PARAMS} } )
  4009         7743  
473             {
474 3         11 my $catval = $val->value( $_[1] );
475 3 50       673 $rc .= defined($catval) ? $catval : '';
476             }
477 4009         11767 return $rc;
478             }
479              
480             =head1 AUTHOR AND COPYRIGHT
481              
482             Copyright (c) 2009-2020 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;