File Coverage

blib/lib/OPTiMaDe/Filter/Comparison.pm
Criterion Covered Total %
statement 79 89 88.7
branch 26 38 68.4
condition 4 6 66.6
subroutine 11 13 84.6
pod 0 10 0.0
total 120 156 76.9


line stmt bran cond sub pod time code
1             package OPTiMaDe::Filter::Comparison;
2              
3 5     5   33 use strict;
  5         11  
  5         147  
4 5     5   25 use warnings;
  5         8  
  5         135  
5 5     5   2028 use Scalar::Util qw(blessed);
  5         11  
  5         5380  
6              
7             sub new {
8 156     156 0 358 my( $class, $operator ) = @_;
9 156         577 return bless { operands => [], operator => $operator }, $class;
10             }
11              
12             sub push_operand
13             {
14 159     159 0 320 my( $self, $operand ) = @_;
15 159 50       224 die 'attempt to insert more than two operands' if @{$self->{operands}} >= 2;
  159         428  
16 159         242 push @{$self->{operands}}, $operand;
  159         419  
17             }
18              
19             sub unshift_operand
20             {
21 153     153 0 282 my( $self, $operand ) = @_;
22 153 50       244 die 'attempt to insert more than two operands' if @{$self->{operands}} >= 2;
  153         349  
23 153         232 unshift @{$self->{operands}}, $operand;
  153         361  
24             }
25              
26             sub operator
27             {
28 222     222 0 447 my( $self, $operator ) = @_;
29 222         358 my $previous_operator = $self->{operator};
30 222 50       395 $self->{operator} = $operator if defined $operator;
31 222         554 return $previous_operator;
32             }
33              
34             sub left
35             {
36 0     0 0 0 my( $self, $operand ) = @_;
37 0         0 my $previous_operand = $self->{operands}[0];
38 0 0       0 $self->{operands}[0] = $operand if defined $operand;
39 0         0 return $previous_operand;
40             }
41              
42             sub right
43             {
44 0     0 0 0 my( $self, $operand ) = @_;
45 0         0 my $previous_operand = $self->{operands}[1];
46 0 0       0 $self->{operands}[1] = $operand if defined $operand;
47 0         0 return $previous_operand;
48             }
49              
50             sub to_filter
51             {
52 148     148 0 11710 my( $self ) = @_;
53 148         372 $self->validate;
54              
55 148         277 my $operator = $self->{operator};
56 148         200 my @operands;
57 148         213 for my $i (0..$#{$self->{operands}}) {
  148         345  
58 296         513 my $arg = $self->{operands}[$i];
59 296 100 66     1557 if( blessed $arg && $arg->can( 'to_filter' ) ) {
60 160         413 $arg = $arg->to_filter;
61             } else {
62 136         290 $arg =~ s/\\/\\\\/g;
63 136         216 $arg =~ s/"/\\"/g;
64 136         251 $arg = "\"$arg\"";
65             }
66 296         694 push @operands, $arg;
67             }
68              
69 148         570 return "($operands[0] $operator $operands[1])";
70             }
71              
72             sub to_SQL
73             {
74 74     74 0 247 my( $self, $options ) = @_;
75 74         204 $self->validate;
76              
77 74 100       180 $options = {} unless $options;
78             my( $delim, $placeholder ) = (
79             $options->{delim},
80             $options->{placeholder},
81 74         154 );
82 74 50       151 $delim = "'" unless $delim;
83              
84 74         118 my $operator = $self->{operator};
85 74         107 my @operands = @{$self->{operands}};
  74         181  
86              
87             # Handle STARTS/ENDS WITH
88 74 100       255 if( $operator eq 'CONTAINS' ) {
    100          
    100          
89 3         11 $operator = 'LIKE';
90 3 50       15 $operands[1] = '%' . $operands[1] . '%' if !blessed $operands[1];
91             } elsif( $operator =~ /^STARTS( WITH)?$/ ) {
92 4         9 $operator = 'LIKE';
93 4 100       18 $operands[1] = $operands[1] . '%' if !blessed $operands[1];
94             } elsif( $operator =~ /^ENDS( WITH)?$/ ) {
95 1         3 $operator = 'LIKE';
96 1 50       8 $operands[1] = '%' . $operands[1] if !blessed $operands[1];
97             }
98              
99 74         114 my @values;
100             my @operands_now;
101 74         134 for my $arg (@operands) {
102 148 100 66     592 if( blessed $arg && $arg->can( 'to_SQL' ) ) {
103 80         227 ( $arg, my $values ) = $arg->to_SQL( $options );
104 80         170 push @values, @$values;
105             } else {
106 68         138 push @values, $arg;
107 68 100       124 if( $placeholder ) {
108 15         21 $arg = $placeholder;
109             } else {
110 53         113 $arg =~ s/"/""/g;
111 53         109 $arg = "\"$arg\"";
112             }
113             }
114 148         323 push @operands_now, $arg;
115             }
116 74         187 @operands = @operands_now;
117              
118 74 100       143 if( wantarray ) {
119 60         307 return ( "($operands[0] $operator $operands[1])", \@values );
120             } else {
121 14         88 return "($operands[0] $operator $operands[1])";
122             }
123             }
124              
125             sub modify
126             {
127 3     3 0 7 my $self = shift;
128 3         4 my $code = shift;
129              
130 6         42 $self->{operands} = [ map { OPTiMaDe::Filter::modify( $_, $code, @_ ) }
131 3         4 @{$self->{operands}} ];
  3         8  
132 3         25 return $code->( $self, @_ );
133             }
134              
135             sub validate
136             {
137 222     222 0 347 my $self = shift;
138              
139 222 50       329 if( @{$self->{operands}} != 2 ) {
  222         522  
140             die 'number of operands for OPTiMaDe::Filter::Comparison must be 2, ' .
141 0         0 'got ' . @{$self->{operands}};
  0         0  
142             }
143 222 50       491 die 'operator undefined for OPTiMaDe::Filter::Comparison'
144             if !$self->operator;
145             }
146              
147             1;