File Coverage

blib/lib/OPTIMADE/Filter/Comparison.pm
Criterion Covered Total %
statement 92 95 96.8
branch 29 40 72.5
condition 5 6 83.3
subroutine 14 14 100.0
pod 0 10 0.0
total 140 165 84.8


line stmt bran cond sub pod time code
1             package OPTIMADE::Filter::Comparison;
2              
3 6     6   45905 use strict;
  6         17  
  6         224  
4 6     6   36 use warnings;
  6         9  
  6         215  
5              
6 6     6   406 use parent 'OPTIMADE::Filter::Modifiable';
  6         269  
  6         26  
7              
8 6     6   362 use Scalar::Util qw(blessed);
  6         12  
  6         6610  
9              
10             sub new {
11 173     173 0 487 my( $class, $operator ) = @_;
12 173         715 return bless { operands => [], operator => $operator }, $class;
13             }
14              
15             sub push_operand
16             {
17 175     175 0 350 my( $self, $operand ) = @_;
18 175 50       250 die 'attempt to insert more than two operands' if @{$self->{operands}} >= 2;
  175         454  
19 175         268 push @{$self->{operands}}, $operand;
  175         455  
20             }
21              
22             sub unshift_operand
23             {
24 169     169 0 307 my( $self, $operand ) = @_;
25 169 50       228 die 'attempt to insert more than two operands' if @{$self->{operands}} >= 2;
  169         444  
26 169         263 unshift @{$self->{operands}}, $operand;
  169         414  
27             }
28              
29             sub operator
30             {
31 247     247 0 449 my( $self, $operator ) = @_;
32 247         399 my $previous_operator = $self->{operator};
33 247 50       451 $self->{operator} = $operator if defined $operator;
34 247         616 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         2 return $previous_operand;
43             }
44              
45             sub right
46             {
47 5     5 0 126 my( $self, $operand ) = @_;
48 5         6 my $previous_operand = $self->{operands}[1];
49 5 100       11 $self->{operands}[1] = $operand if defined $operand;
50 5         15 return $previous_operand;
51             }
52              
53             sub to_filter
54             {
55 164     164 0 11321 my( $self ) = @_;
56 164         398 $self->validate;
57              
58 164         355 my $operator = $self->{operator};
59 164         224 my @operands;
60 164         245 for my $i (0..$#{$self->{operands}}) {
  164         375  
61 328         560 my $arg = $self->{operands}[$i];
62 328 100 66     1336 if( blessed $arg && $arg->can( 'to_filter' ) ) {
63 176         445 $arg = $arg->to_filter;
64             } else {
65 152         310 $arg =~ s/\\/\\\\/g;
66 152         227 $arg =~ s/"/\\"/g;
67 152         284 $arg = "\"$arg\"";
68             }
69 328         759 push @operands, $arg;
70             }
71              
72 164         638 return "($operands[0] $operator $operands[1])";
73             }
74              
75             sub to_SQL
76             {
77 83     83 0 321 my( $self, $options ) = @_;
78 83         197 $self->validate;
79              
80 83 50       197 $options = {} unless $options;
81             my( $delim, $placeholder ) = (
82             $options->{delim},
83             $options->{placeholder},
84 83         175 );
85 83 50       202 $delim = "'" unless $delim;
86              
87 83         124 my $operator = $self->{operator};
88 83         132 my @operands = @{$self->{operands}};
  83         184  
89              
90             # Handle STARTS/ENDS WITH
91 83 100       286 if( $operator eq 'CONTAINS' ) {
    100          
    100          
92 3         7 $operator = 'LIKE';
93 3 50       18 $operands[1] = '%' . $operands[1] . '%' if !blessed $operands[1];
94             } elsif( $operator =~ /^STARTS( WITH)?$/ ) {
95 4         7 $operator = 'LIKE';
96 4 100       19 $operands[1] = $operands[1] . '%' if !blessed $operands[1];
97             } elsif( $operator =~ /^ENDS( WITH)?$/ ) {
98 1         4 $operator = 'LIKE';
99 1 50       7 $operands[1] = '%' . $operands[1] if !blessed $operands[1];
100             }
101              
102 83         134 my @values;
103             my @operands_now;
104 83         153 for my $arg (@operands) {
105 166         282 my $sql = $arg;
106 166 100 100     652 if( blessed $arg && $arg->can( 'to_SQL' ) ) {
107 89         233 ( $sql, my $values ) = $arg->to_SQL( $options );
108 89 50       387 if( $arg->isa( OPTIMADE::Filter::Comparison:: ) ) {
109 0         0 $sql = "($sql)";
110             }
111 89         187 push @values, @$values;
112             } else {
113 77         149 push @values, $arg;
114 77 100       162 if( $placeholder ) {
115 16         27 $sql = $placeholder;
116             } else {
117 61         122 $sql =~ s/"/""/g;
118 61         118 $sql = "\"$sql\"";
119             }
120             }
121 166         409 push @operands_now, $sql;
122             }
123 83         207 @operands = @operands_now;
124              
125 83 100       147 if( wantarray ) {
126 69         340 return ( "$operands[0] $operator $operands[1]", \@values );
127             } else {
128 14         79 return "$operands[0] $operator $operands[1]";
129             }
130             }
131              
132             sub modify
133             {
134 5     5 0 1890 my $self = shift;
135 5         9 my $code = shift;
136              
137 10         57 $self->{operands} = [ map { OPTIMADE::Filter::Modifiable::modify( $_, $code, @_ ) }
138 5         9 @{$self->{operands}} ];
  5         11  
139 5         60 return $code->( $self, @_ );
140             }
141              
142             sub validate
143             {
144 247     247 0 392 my $self = shift;
145              
146 247 50       354 if( @{$self->{operands}} != 2 ) {
  247         575  
147             die 'number of operands for OPTIMADE::Filter::Comparison must be 2, ' .
148 0         0 'got ' . @{$self->{operands}};
  0         0  
149             }
150 247 50       515 die 'operator undefined for OPTIMADE::Filter::Comparison'
151             if !$self->operator;
152             }
153              
154             1;