File Coverage

blib/lib/ObjectDB/Util.pm
Criterion Covered Total %
statement 69 94 73.4
branch 31 44 70.4
condition 7 9 77.7
subroutine 9 11 81.8
pod 0 6 0.0
total 116 164 70.7


line stmt bran cond sub pod time code
1             package ObjectDB::Util;
2              
3 7     7   108381 use strict;
  7         27  
  7         161  
4 7     7   26 use warnings;
  7         11  
  7         177  
5              
6 7     7   29 use base 'Exporter';
  7         10  
  7         1761  
7              
8             our $VERSION = '3.26';
9             our @EXPORT_OK = qw(load_class execute to_array merge_rows filter_columns);
10              
11             require Carp;
12             require Storable;
13              
14             sub load_class {
15 5     5 0 10 my ($class) = @_;
16              
17 5 50       9 Carp::croak('class name is required') unless $class;
18              
19 5 50       37 Carp::croak("Invalid class name '$class'")
20             unless $class =~ m/^[[:lower:]\d:]+$/smxi;
21              
22 5         10 my $path = $class;
23 5         18 $path =~ s{::}{/}smxg;
24 5         8 $path .= '.pm';
25              
26 5 100 66     28 return 1 if exists $INC{$path} && defined $INC{$path};
27              
28             {
29 7     7   44 no strict 'refs';
  7         11  
  7         633  
  2         4  
30              
31 2         3 for (keys %{"$class\::"}) {
  2         17  
32 0 0       0 return 1 if defined &{$_};
  0         0  
33             }
34             }
35              
36             eval {
37 2         949 require $path;
38              
39 2         11 1;
40 2 50       3 } or do {
41 0         0 my $e = $@;
42              
43 0         0 delete $INC{$path};
44              
45             {
46 7     7   40 no strict 'refs';
  7         9  
  7         4722  
  0         0  
47 0         0 %{"$class\::"} = ();
  0         0  
48             }
49              
50 0         0 Carp::croak($e);
51             };
52             }
53              
54             sub execute {
55 0     0 0 0 my ($dbh, $stmt) = @_;
56              
57 0         0 my $sql = $stmt->to_sql;
58 0         0 my @bind = $stmt->to_bind;
59              
60 0         0 my $sth = $dbh->prepare($sql);
61 0         0 my $rv = $sth->execute(@bind);
62              
63 0 0       0 return wantarray ? ($rv, $sth) : $rv;
64             }
65              
66             sub force_arrayrefs {
67 0     0 0 0 my ($data, $defaults) = @_;
68              
69 0         0 my $clone = Storable::dclone($data);
70              
71 0         0 foreach my $key (keys %$defaults) {
72 0 0       0 if (!exists $clone->{$key}) {
    0          
73 0         0 $clone->{$key} = [ @{ $defaults->{$key} } ];
  0         0  
74             }
75             elsif (!ref $clone->{$key}) {
76 0         0 $clone->{$key} = [ $clone->{$key} ];
77             }
78              
79 0         0 push @{ $clone->{$key} }, @{ $defaults->{$key} };
  0         0  
  0         0  
80              
81             }
82              
83 0         0 return $clone;
84             }
85              
86             sub to_array {
87 7     7 0 926 my ($data) = @_;
88              
89 7 100       19 return () unless defined $data;
90              
91 6 100       24 return @$data if ref $data eq 'ARRAY';
92              
93 1         5 return ($data);
94             }
95              
96             sub merge_rows {
97 14     14 0 20084 my $rows = shift;
98              
99 14         18 my $merged = [];
100              
101 14         17 my %order;
102 14         27 NEXT_MERGE: while (@$rows) {
103 30         50 my $row = shift @$rows;
104              
105 30         38 my $row_sign = '';
106 30         69 foreach my $key (sort keys %$row) {
107 42         50 my $value = $row->{$key};
108 42 100 66     100 $value = \'join' if ref $value eq 'HASH' || ref $value eq 'ARRAY';
109              
110 42 100       59 $value = \undef unless defined $value;
111 42         74 $row_sign .= "$key=$value";
112             }
113              
114 30 100       53 if (!exists $order{$row_sign}) {
115 23         38 $order{$row_sign} = $row;
116              
117 23         33 push @$merged, $row;
118 23         44 next NEXT_MERGE;
119             }
120              
121 7         8 my $prev = $order{$row_sign};
122              
123 7         36 foreach my $key (keys %$row) {
124             next
125             unless ref $prev->{$key} eq 'HASH'
126 12 100 100     44 || ref $prev->{$key} eq 'ARRAY';
127              
128             my $prev_row =
129             ref $prev->{$key} eq 'ARRAY'
130             ? $prev->{$key}->[-1]
131 5 100       11 : $prev->{$key};
132              
133 5         13 my $merged_rows = merge_rows([ $prev_row, $row->{$key} ]);
134 5 100       13 if (@$merged_rows > 1) {
135             my $prev_rows =
136             ref $prev->{$key} eq 'ARRAY'
137             ? $prev->{$key}
138 4 100       10 : [ $prev->{$key} ];
139 4         5 pop @$prev_rows;
140 4         10 $prev->{$key} = [ @$prev_rows, @$merged_rows ];
141             }
142             }
143             }
144              
145 14         31 return $merged;
146             }
147              
148             sub filter_columns {
149 4     4 0 2160 my ($meta_columns, $params) = @_;
150              
151 4         7 my @columns;
152 4 100       7 if ($params->{columns}) {
153 1 50       5 push @columns, to_array($params->{columns}) if $params->{columns};
154             }
155             else {
156 3         6 push @columns, @$meta_columns;
157             }
158              
159 4 100       10 push @columns, to_array($params->{'+columns'}) if $params->{'+columns'};
160 4 100       8 if ($params->{'-columns'}) {
161 1         3 my $minus_columns = { map { $_ => 1 } to_array($params->{'-columns'}) };
  1         3  
162              
163 1 50       3 @columns = grep { !exists $minus_columns->{ ref($_) ? $_->{'-col'} : $_ } } @columns;
  2         7  
164             }
165              
166 4         23 return \@columns;
167             }
168              
169             1;