File Coverage

lib/Metadata/DB/Analizer.pm
Criterion Covered Total %
statement 18 18 100.0
branch n/a
condition n/a
subroutine 6 6 100.0
pod n/a
total 24 24 100.0


line stmt bran cond sub pod time code
1             package Metadata::DB::Analizer;
2 2     2   40590 use strict;
  2         5  
  2         78  
3 2     2   13 use Carp;
  2         3  
  2         220  
4 2     2   12 use warnings;
  2         14  
  2         70  
5 2     2   2015 use LEOCHARRE::DEBUG;
  2         12213  
  2         14  
6 2     2   329 use vars qw($VERSION);
  2         4  
  2         96  
7 2     2   12 use base 'Metadata::DB::Base';
  2         3  
  2         4667  
8             use LEOCHARRE::Class::Accessors
9             multi => ['search_attributes_selected','_attributes'],
10             single => ['attribute_option_list_limit'];
11              
12             no warnings 'redefine';
13             $VERSION = sprintf "%d.%02d", q$Revision: 1.3 $ =~ /(\d+)/g;
14              
15              
16              
17             # LIST ALL ATTS AVAILABLE
18             *get_attributes = \&_attributes;
19             sub _attributes {
20             my $self = shift;
21             unless( $self->_attributes_count ){
22             debug('_attributes_count returned none.. ');
23             my $atts = $self->_distinct_attributes_arrayref;
24             ref $atts eq 'ARRAY' or die('not array ref');
25             debug("got atts scalar: [".scalar @$atts."]");
26             for(@$atts){
27             $self->_attributes_add($_);
28             }
29            
30             }
31             return $self->_attributes_arrayref;
32             }
33              
34             sub _distinct_attributes_arrayref {
35             my $self = shift;
36            
37             my $keys = $self->dbh->selectcol(
38             sprintf
39             "SELECT DISTINCT %s FROM %s",
40             $self->table_metadata_column_name_key,
41             $self->table_metadata_name,
42             );
43             debug("keys @$keys\n");
44             return $keys;
45             }
46              
47              
48              
49              
50              
51              
52             # get ratio of attributes, how many 'age', 'name', and 'color' etc atts are there
53              
54             sub get_attributes_ratios {
55             my $self = shift;
56              
57             my $at = $self->get_attributes_counts;
58            
59             $at->{all} or croak('no atts in table ?');
60              
61             my $attr ={};
62              
63             for my $att ( keys %$at){
64              
65             # total entries
66             $attr->{$att} =
67             int (($at->{$att} * 100) / $at->{all} );
68            
69             }
70              
71             delete $attr->{all};
72             return $attr;
73             }
74              
75             sub get_attributes_by_ratio {
76             my $self = shift;
77              
78             my $_att = $self->get_attributes_ratios;
79              
80             my @atts = sort { $_att->{$b} <=> $_att->{$a} } keys %$_att;
81             return \@atts;
82             }
83              
84              
85             sub get_attributes_counts {
86             my $self = shift;
87              
88             my $attr ={};
89             my $_atts = $self->get_attributes;
90              
91             my $total=0;
92            
93             for my $att (@$_atts){
94              
95             # total entries
96             $attr->{$att} = $self->attribute_all_unique_values_count($att);
97             $total+= $attr->{$att};
98             }
99              
100             # actaully we can just add all the vals, can get diff numb.. but.. whatever- not urgent.
101             $attr->{ all } = $total; #$self->dbh->rows_count($self->table_metadata_name);
102              
103             return $attr;
104             }
105              
106              
107             sub get_records_count {
108             my $self = shift;
109              
110             my $idname = $self->table_metadata_column_name_id;
111             my $tablename = $self->table_metadata_name;
112             my $q = $self->dbh->prepare("SELECT count(DISTINCT $idname) FROM $tablename");
113             $q->execute;
114              
115             my $count;
116             $q->bind_columns(\$count);
117             $q->fetch;
118             $count ||=0;
119             return $count;
120             }
121              
122             # end analysis
123              
124              
125              
126              
127              
128              
129              
130              
131              
132              
133              
134              
135             sub search_attributes_selected {
136             my $self = shift;
137            
138             unless( $self->search_attributes_selected_count ){
139             debug("no search attributes list has been selected, we will chose all");
140             my @params = sort @{ $self->get_attributes };
141             debug("params are [@params]\n");
142             for (@params){
143             $self->search_attributes_selected_add($_);
144             }
145             }
146              
147             # weed out ones that have one option only? maybe not since the alternative is none..
148             # because one option for an att, the alternative is still valid.
149            
150              
151             return $self->search_attributes_selected_arrayref;
152             }
153              
154              
155              
156              
157             # start single att methods
158             # INTERFACE
159              
160             # for each of the attributes, how many variations are there?
161             # if there are less then x, then make it a drop down box
162              
163             # this is not meant to be used online, only offline, as a regeneration of query interface
164              
165              
166             # if they are more then x choices, then return false
167             # what we used this for is making a drop down
168             sub attribute_option_list {
169             my( $self, $attribute, $_limit ) = @_;
170             defined $attribute or croak('missing dbh or attribute name');
171            
172             # this is safe because it returns what we wet, if we set, otherwise returns anyway
173             my $limit = $self->attribute_option_list_limit( $attribute, $_limit );
174            
175            
176             # order it
177             my $list = $self->attribute_all_unique_values($attribute,$limit)
178             or return;
179              
180             my $sorted = _sort($list);
181            
182             # unshift into list a value for 'none' ?
183            
184            
185             return $sorted;
186             }
187              
188             sub attribute_option_list_limit {
189             my($self, $att, $limit ) = @_;
190              
191             $self->{_attlimit} ||={};
192             $self->{_attlimit_default} ||= 100;
193            
194             if( defined $att and defined $limit){
195             debug("att $att, limit $limit");
196             $self->{_attlimit}->{$att} = $limit;
197             return $limit;
198             }
199              
200             elsif ( defined $att and ( ! defined $limit ) ){
201            
202             if( $att=~/^\d+$/ ){ # then this is to set default limit globally
203             debug("setting default limit to $att");
204             $self->{_attlimit_default} = $att;
205             return $self->{_attlimit_default};
206             }
207            
208             else { # we are requesting the limit value for this att
209            
210            
211             my $specific_limit = $self->{_attlimit}->{$att};
212             unless( $specific_limit ){
213             debug("att $att did not have explicit limit, returning default");
214             return $self->{_attlimit_default};
215             }
216            
217             debug("att $att had specific limit set to $specific_limit");
218             return $specific_limit;
219             }
220              
221             }
222              
223             # no args, just return the default
224             debug("returning default limit of ".$self->{_attlimit_default});
225            
226             return $self->{_attlimit_default};
227             }
228              
229              
230             sub _sort { # mostly to sort values
231             my $list = shift;
232            
233             for(@$list){
234             $_=~/^[\.\d]+$/ and next;
235            
236             # then we are string!
237             return [ sort { lc $a cmp lc $b } @$list ];
238             }
239            
240             # we are number
241             return [ sort { $a <=> $b } @$list ];
242             }
243              
244              
245             #just for heuristics!!! not accurate!
246             sub _att_uniq_vals {
247             my ($self,$att) = @_;
248             defined $att or croak('missing att');
249              
250             my $limit = 1000;
251              
252             # unique vals
253              
254             # this is for heuristics
255             my $_sql = sprintf "SELECT DISTINCT %s FROM %s WHERE %s=? LIMIT ?",
256             $self->table_metadata_column_name_value,
257             $self->table_metadata_name,
258             $self->table_metadata_column_name_key;
259              
260             my $s = $self->dbh->prepare_cached( $_sql )
261             or die( "statement [$_sql], ".$self->dbh->errstr );
262            
263             $s->execute($att,$limit) or die( $self->dbh->errstr );
264            
265             my $value;
266             $s->bind_columns(\$value);
267              
268             my @vals;
269             while($s->fetch){
270             push @vals,$value;
271             }
272             return \@vals;
273             }
274              
275              
276              
277              
278             sub attribute_all_unique_values {
279             my ($self,$attribute,$limit) = @_;
280             defined $attribute or croak('missing dbh or attribute name');
281            
282             my $_limit;
283             if(defined $limit){
284             $_limit = ' LIMIT '.($limit+1);
285             }
286             else {
287             $_limit = '';
288             }
289              
290             debug("limit = $limit\n") if $limit;
291            
292            
293              
294             # unique vals
295             my $q = sprintf "SELECT DISTINCT %s FROM %s WHERE %s='%s' $_limit",
296             $self->table_metadata_column_name_value,
297             $self->table_metadata_name,
298             $self->table_metadata_column_name_key,
299             $attribute,
300             ;
301             # debug(" query: $q \n");
302            
303             my $r = $self->dbh->selectall_arrayref($q);
304            
305             my @vals = ();
306             for(@$r){
307             push @vals, $_->[0];
308             }
309              
310             if(scalar @vals and $limit and (scalar @vals > $limit)){
311             debug("limit [$limit] exceeded, try higher limit?\n");
312             return;
313             }
314             return \@vals;
315             }
316              
317              
318             # pass it one attribute name, tells how many there are (possibilities) distinct values
319             sub attribute_all_unique_values_count { # THIS WILL BE SLOW
320             my ($self,$attribute) =@_;
321             defined $attribute or confess('missing attribute arg');
322              
323             my $vals = $self->attribute_all_unique_values($attribute);
324             my $count = scalar @$vals;
325             return $count;
326             }
327              
328             sub attribute_type_is_number {
329             my ($self,$att) = @_;
330             defined $att or croak('missing attribute name');
331              
332             my $vals = $self->_att_uniq_vals($att) or return;
333             scalar @$vals or return;
334             for (@$vals){
335             /^\d+$/ or return 0;
336             }
337             return 1;
338             }
339              
340              
341             # end single att methods
342              
343              
344              
345              
346              
347              
348             1;
349              
350             __END__