File Coverage

blib/lib/OPTIMADE/Filter/Comparison.pm
Criterion Covered Total %
statement 90 92 97.8
branch 29 38 76.3
condition 5 6 83.3
subroutine 14 14 100.0
pod 0 10 0.0
total 138 160 86.2


line stmt bran cond sub pod time code
1             package OPTIMADE::Filter::Comparison;
2              
3 6     6   55193 use strict;
  6         17  
  6         180  
4 6     6   31 use warnings;
  6         11  
  6         182  
5              
6 6     6   465 use parent 'OPTIMADE::Filter::Modifiable';
  6         326  
  6         28  
7              
8 6     6   351 use Scalar::Util qw(blessed);
  6         11  
  6         6641  
9              
10             sub new {
11 157     157 0 442 my( $class, $operator ) = @_;
12 157         630 return bless { operands => [], operator => $operator }, $class;
13             }
14              
15             sub push_operand
16             {
17 159     159 0 302 my( $self, $operand ) = @_;
18 159 50       216 die 'attempt to insert more than two operands' if @{$self->{operands}} >= 2;
  159         418  
19 159         240 push @{$self->{operands}}, $operand;
  159         462  
20             }
21              
22             sub unshift_operand
23             {
24 153     153 0 271 my( $self, $operand ) = @_;
25 153 50       200 die 'attempt to insert more than two operands' if @{$self->{operands}} >= 2;
  153         350  
26 153         213 unshift @{$self->{operands}}, $operand;
  153         355  
27             }
28              
29             sub operator
30             {
31 223     223 0 406 my( $self, $operator ) = @_;
32 223         378 my $previous_operator = $self->{operator};
33 223 50       411 $self->{operator} = $operator if defined $operator;
34 223         547 return $previous_operator;
35             }
36              
37             sub left
38             {
39 1     1 0 3 my( $self, $operand ) = @_;
40 1         8 my $previous_operand = $self->{operands}[0];
41 1 50       4 $self->{operands}[0] = $operand if defined $operand;
42 1         3 return $previous_operand;
43             }
44              
45             sub right
46             {
47 5     5 0 125 my( $self, $operand ) = @_;
48 5         13 my $previous_operand = $self->{operands}[1];
49 5 100       12 $self->{operands}[1] = $operand if defined $operand;
50 5         20 return $previous_operand;
51             }
52              
53             sub to_filter
54             {
55 148     148 0 11691 my( $self ) = @_;
56 148         346 $self->validate;
57              
58 148         270 my $operator = $self->{operator};
59 148         204 my @operands;
60 148         191 for my $i (0..$#{$self->{operands}}) {
  148         357  
61 296         576 my $arg = $self->{operands}[$i];
62 296 100 66     1220 if( blessed $arg && $arg->can( 'to_filter' ) ) {
63 160         404 $arg = $arg->to_filter;
64             } else {
65 136         272 $arg =~ s/\\/\\\\/g;
66 136         197 $arg =~ s/"/\\"/g;
67 136         261 $arg = "\"$arg\"";
68             }
69 296         679 push @operands, $arg;
70             }
71              
72 148         535 return "($operands[0] $operator $operands[1])";
73             }
74              
75             sub to_SQL
76             {
77 75     75 0 238 my( $self, $options ) = @_;
78 75         175 $self->validate;
79              
80 75 100       161 $options = {} unless $options;
81             my( $delim, $placeholder ) = (
82             $options->{delim},
83             $options->{placeholder},
84 75         181 );
85 75 50       144 $delim = "'" unless $delim;
86              
87 75         124 my $operator = $self->{operator};
88 75         109 my @operands = @{$self->{operands}};
  75         164  
89              
90             # Handle STARTS/ENDS WITH
91 75 100       253 if( $operator eq 'CONTAINS' ) {
    100          
    100          
92 3         7 $operator = 'LIKE';
93 3 50       15 $operands[1] = '%' . $operands[1] . '%' if !blessed $operands[1];
94             } elsif( $operator =~ /^STARTS( WITH)?$/ ) {
95 4         9 $operator = 'LIKE';
96 4 100       18 $operands[1] = $operands[1] . '%' if !blessed $operands[1];
97             } elsif( $operator =~ /^ENDS( WITH)?$/ ) {
98 1         4 $operator = 'LIKE';
99 1 50       6 $operands[1] = '%' . $operands[1] if !blessed $operands[1];
100             }
101              
102 75         125 my @values;
103             my @operands_now;
104 75         130 for my $arg (@operands) {
105 150 100 100     561 if( blessed $arg && $arg->can( 'to_SQL' ) ) {
106 81         205 ( $arg, my $values ) = $arg->to_SQL( $options );
107 81         170 push @values, @$values;
108             } else {
109 69         141 push @values, $arg;
110 69 100       119 if( $placeholder ) {
111 16         25 $arg = $placeholder;
112             } else {
113 53         110 $arg =~ s/"/""/g;
114 53         107 $arg = "\"$arg\"";
115             }
116             }
117 150         321 push @operands_now, $arg;
118             }
119 75         181 @operands = @operands_now;
120              
121 75 100       134 if( wantarray ) {
122 61         284 return ( "($operands[0] $operator $operands[1])", \@values );
123             } else {
124 14         74 return "($operands[0] $operator $operands[1])";
125             }
126             }
127              
128             sub modify
129             {
130 5     5 0 2134 my $self = shift;
131 5         12 my $code = shift;
132              
133 10         68 $self->{operands} = [ map { OPTIMADE::Filter::Modifiable::modify( $_, $code, @_ ) }
134 5         10 @{$self->{operands}} ];
  5         11  
135 5         62 return $code->( $self, @_ );
136             }
137              
138             sub validate
139             {
140 223     223 0 370 my $self = shift;
141              
142 223 50       298 if( @{$self->{operands}} != 2 ) {
  223         529  
143             die 'number of operands for OPTIMADE::Filter::Comparison must be 2, ' .
144 0         0 'got ' . @{$self->{operands}};
  0         0  
145             }
146 223 50       409 die 'operator undefined for OPTIMADE::Filter::Comparison'
147             if !$self->operator;
148             }
149              
150             1;