File Coverage

lib/UR/DataSource/RDBMS/Operator/In.pm
Criterion Covered Total %
statement 38 39 97.4
branch 12 14 85.7
condition 4 6 66.6
subroutine 7 7 100.0
pod 0 1 0.0
total 61 67 91.0


line stmt bran cond sub pod time code
1 19     19   11799 use strict;
  19         30  
  19         616  
2 19     19   83 use warnings;
  19         33  
  19         986  
3              
4             package UR::DataSource::RDBMS::Operator::In;
5              
6             # This allows the size of an autogenerated IN-clause to be adjusted.
7             # The limit for Oracle is 1000, and a bug requires that, in some cases
8             # we drop to 250.
9 19     19   72 use constant IN_CLAUSE_SIZE_LIMIT => 250;
  19         25  
  19         3054  
10              
11             our @CARP_NOT = qw( UR::DataSource::RDBMS );
12              
13 66     66   180 sub _negation_clause { '' }
14              
15             sub generate_sql_for {
16 91     91 0 183 my($class, $expr_sql, $val, $escape) = @_;
17              
18 91 50       274 unless (ref($val) eq 'ARRAY') {
19 0         0 $val = [$val];
20             }
21              
22 91 100       247 unless (@$val) {
23             # an empty list was passed-in.
24             # since "in ()", like "where 1=0", is self-contradictory,
25             # there is no data to return, and no SQL required
26 12         2976 Carp::carp("Null in-clause");
27 12         50 return;
28             }
29              
30 19     19   76 my @list = do { no warnings 'uninitialized';
  19         46  
  19         4711  
  79         109  
31 79         364 sort @$val; };
32 79         217 my $has_null = _list_contains_null(\@list);
33 79   66     344 my $wrap = ($has_null or @$val > IN_CLAUSE_SIZE_LIMIT ? 1 : 0);
34 79         111 my $cnt = 0;
35 79         115 my $sql = '';
36 79 100       183 $sql .= "\n(\n " if $wrap;
37 79         358 while (my @set = splice(@list,0,IN_CLAUSE_SIZE_LIMIT))
38             {
39 79 50       175 $sql .= "\n or " if $cnt++;
40             $sql .= $expr_sql
41             . $class->_negation_clause
42 79         252 . " in (" . join(",",map { UR::Util::sql_quote($_) } @set) . ")";
  190         363  
43             }
44 79 100       183 if ($has_null) {
45 10         30 $sql .= "\n or $expr_sql is "
46             . $class->_negation_clause
47             . ' null';
48             }
49 79 100       156 $sql .= "\n)\n" if $wrap;
50              
51 79         253 return ($sql);
52             }
53              
54             sub _list_contains_null {
55 79     79   107 my $list = shift;
56              
57 79         174 foreach my $elt ( @$list ) {
58 186 100 66     663 if (! defined($elt)
59             or
60             length($elt) == 0
61             ) {
62 10         19 return 1;
63             }
64             }
65 69         127 return '';
66             }
67              
68             1;