File Coverage

blib/lib/OPTIMADE/Filter/Comparison.pm
Criterion Covered Total %
statement 92 95 96.8
branch 30 40 75.0
condition 5 6 83.3
subroutine 14 14 100.0
pod 0 10 0.0
total 141 165 85.4


line stmt bran cond sub pod time code
1             package OPTIMADE::Filter::Comparison;
2              
3 6     6   133352 use strict;
  6         14  
  6         297  
4 6     6   33 use warnings;
  6         11  
  6         433  
5              
6 6     6   654 use parent 'OPTIMADE::Filter::Modifiable';
  6         343  
  6         44  
7 6     6   389 use Scalar::Util qw(blessed);
  6         10  
  6         10273  
8              
9             our $VERSION = '0.11.0'; # VERSION
10              
11             sub new {
12 261     261 0 394301 my( $class, $operator ) = @_;
13 261         1613 return bless { operands => [], operator => $operator }, $class;
14             }
15              
16             sub push_operand
17             {
18 259     259 0 556 my( $self, $operand ) = @_;
19 259 50       420 die 'attempt to insert more than two operands' if @{$self->{operands}} >= 2;
  259         882  
20 259         440 push @{$self->{operands}}, $operand;
  259         864  
21             }
22              
23             sub unshift_operand
24             {
25 185     185 0 408 my( $self, $operand ) = @_;
26 185 50       338 die 'attempt to insert more than two operands' if @{$self->{operands}} >= 2;
  185         555  
27 185         361 unshift @{$self->{operands}}, $operand;
  185         638  
28             }
29              
30             sub operator
31             {
32 345     345 0 691 my( $self, $operator ) = @_;
33 345         725 my $previous_operator = $self->{operator};
34 345 50       821 $self->{operator} = $operator if defined $operator;
35 345         1158 return $previous_operator;
36             }
37              
38             sub left
39             {
40 73     73 0 177 my( $self, $operand ) = @_;
41 73         153 my $previous_operand = $self->{operands}[0];
42 73 100       189 $self->{operands}[0] = $operand if defined $operand;
43 73         243 return $previous_operand;
44             }
45              
46             sub right
47             {
48 9     9 0 271 my( $self, $operand ) = @_;
49 9         26 my $previous_operand = $self->{operands}[1];
50 9 100       32 $self->{operands}[1] = $operand if defined $operand;
51 9         38 return $previous_operand;
52             }
53              
54             sub to_filter
55             {
56 184     184 0 25590 my( $self ) = @_;
57 184         610 $self->validate;
58              
59 184         391 my $operator = $self->{operator};
60 184         291 my @operands;
61 184         275 for my $i (0..$#{$self->{operands}}) {
  184         570  
62 368         764 my $arg = $self->{operands}[$i];
63 368 100 66     1617 if( blessed $arg && $arg->can( 'to_filter' ) ) {
64 216         583 $arg = $arg->to_filter;
65             } else {
66 152         354 $arg =~ s/\\/\\\\/g;
67 152         314 $arg =~ s/"/\\"/g;
68 152         313 $arg = "\"$arg\"";
69             }
70 368         930 push @operands, $arg;
71             }
72              
73 184         794 return "($operands[0] $operator $operands[1])";
74             }
75              
76             sub to_SQL
77             {
78 93     93 0 396 my( $self, $options ) = @_;
79 93         271 $self->validate;
80              
81 93 50       264 $options = {} unless $options;
82             my( $delim, $placeholder ) = (
83             $options->{delim},
84             $options->{placeholder},
85 93         257 );
86 93 50       312 $delim = "'" unless $delim;
87              
88 93         182 my $operator = $self->{operator};
89 93         181 my @operands = @{$self->{operands}};
  93         280  
90              
91             # Handle STARTS/ENDS WITH
92 93 100       416 if( $operator eq 'CONTAINS' ) {
    100          
    100          
93 3         8 $operator = 'LIKE';
94 3 50       18 $operands[1] = '%' . $operands[1] . '%' if !blessed $operands[1];
95             } elsif( $operator =~ /^STARTS( WITH)?$/ ) {
96 4         12 $operator = 'LIKE';
97 4 100       21 $operands[1] = $operands[1] . '%' if !blessed $operands[1];
98             } elsif( $operator =~ /^ENDS( WITH)?$/ ) {
99 1         4 $operator = 'LIKE';
100 1 50       10 $operands[1] = '%' . $operands[1] if !blessed $operands[1];
101             }
102              
103 93         169 my @values;
104             my @operands_now;
105 93         205 for my $arg (@operands) {
106 184         374 my $sql = $arg;
107 184 100 100     889 if( blessed $arg && $arg->can( 'to_SQL' ) ) {
108 107         356 ( $sql, my $values ) = $arg->to_SQL( $options );
109 97 50       587 if( $arg->isa( OPTIMADE::Filter::Comparison:: ) ) {
110 0         0 $sql = "($sql)";
111             }
112 97         225 push @values, @$values;
113             } else {
114 77         196 push @values, $arg;
115 77 100       182 if( $placeholder ) {
116 16         33 $sql = $placeholder;
117             } else {
118 61         155 $sql =~ s/"/""/g;
119 61         136 $sql = "\"$sql\"";
120             }
121             }
122 174         417 push @operands_now, $sql;
123             }
124 83         283 @operands = @operands_now;
125              
126 83 100       174 if( wantarray ) {
127 69         422 return ( "$operands[0] $operator $operands[1]", \@values );
128             } else {
129 14         94 return "$operands[0] $operator $operands[1]";
130             }
131             }
132              
133             sub modify
134             {
135 5     5 0 3696 my $self = shift;
136 5         9 my $code = shift;
137              
138 10         54 $self->{operands} = [ map { OPTIMADE::Filter::Modifiable::modify( $_, $code, @_ ) }
139 5         8 @{$self->{operands}} ];
  5         11  
140 5         104 return $code->( $self, @_ );
141             }
142              
143             sub validate
144             {
145 277     277 0 506 my $self = shift;
146              
147 277 50       464 if( @{$self->{operands}} != 2 ) {
  277         839  
148             die 'number of operands for OPTIMADE::Filter::Comparison must be 2, ' .
149 0         0 'got ' . @{$self->{operands}};
  0         0  
150             }
151 277 50       741 die 'operator undefined for OPTIMADE::Filter::Comparison'
152             if !$self->operator;
153             }
154              
155             1;