File Coverage

blib/lib/Math/DifferenceSet/Planar/Data.pm
Criterion Covered Total %
statement 100 100 100.0
branch 36 40 90.0
condition 8 9 88.8
subroutine 31 31 100.0
pod 14 14 100.0
total 189 194 97.4


line stmt bran cond sub pod time code
1             package Math::DifferenceSet::Planar::Data;
2              
3 6     6   67251 use strict;
  6         23  
  6         150  
4 6     6   32 use warnings;
  6         11  
  6         205  
5 6     6   30 use Carp qw(croak);
  6         8  
  6         255  
6 6     6   30 use File::Spec;
  6         11  
  6         141  
7 6     6   2112 use File::Share qw(dist_dir);
  6         163409  
  6         380  
8 6     6   3013 use DBD::SQLite::Constants qw(SQLITE_OPEN_READONLY);
  6         165813  
  6         828  
9 6     6   3021 use Math::DifferenceSet::Planar::Schema;
  6         23  
  6         257  
10              
11             # Math::DifferenceSet::Planar::Data=ARRAY(...)
12              
13             # .......... index .......... # .......... value ..........
14 6     6   43 use constant _F_DATA => 0; # difference set result set object
  6         13  
  6         438  
15 6     6   30 use constant _F_SPACES => 1; # PDS space result set object or undef
  6         36  
  6         309  
16 6     6   39 use constant _F_PATH => 2; # database path name
  6         11  
  6         273  
17 6     6   33 use constant _NFIELDS => 3;
  6         9  
  6         7296  
18              
19             our $VERSION = '0.017';
20             our @CARP_NOT = qw(Math::DifferenceSet::Planar);
21              
22             our $DATABASE_DIR = dist_dir('Math-DifferenceSet-Planar');
23              
24             # ----- private subroutines -----
25              
26             sub _iterate {
27 16     16   52 my ($domain, $min, $max, @columns) = @_;
28 16         35 my @sel = ();
29 16         36 my $dir = 'ASC';
30 16 100 100     111 if (defined($min) && defined($max) && $min > $max) {
      100        
31 3         15 ($min, $max, $dir) = ($max, $min, 'DESC');
32             }
33 16 100       52 push @sel, '>=' => $min if defined $min;
34 16 100       50 push @sel, '<=' => $max if defined $max;
35 16 100       177 my $results = $domain->search(
    100          
36             @sel? { order_ => { @sel } }: undef,
37             {
38             @columns? ( columns => \@columns ): (),
39             order_by => "order_ $dir",
40             }
41             );
42 16     86   5583 return sub { $results->next };
  86         27130  
43             }
44              
45             # ----- private accessor methods -----
46              
47 79     79   437 sub _data { $_[0]->[_F_DATA] }
48 37     37   92 sub _spaces { $_[0]->[_F_SPACES] }
49 1     1   6 sub _path { $_[0]->[_F_PATH] }
50              
51             # ----- class methods -----
52              
53             sub list_databases {
54 7 50   7 1 380 opendir my $dh, $DATABASE_DIR or return ();
55             my @files =
56             map {
57 11 100       55 my $is_standard = /^pds[_\W]/i? 1: 0;
58 11         290 my $path = File::Spec->rel2abs($_, $DATABASE_DIR);
59 11 50       276 (-f $path)? [$_, $is_standard, -s _]: ()
60             }
61 7         246 grep { /\.db\z/i } readdir $dh;
  36         123  
62 7         103 closedir $dh;
63             return
64 11         61 map { $_->[0] }
65             sort {
66 7 50 66     44 $b->[1] <=> $a->[1] || $b->[2] <=> $a->[2] ||
  6         35  
67             $a->[0] cmp $b->[0]
68             }
69             @files;
70             }
71              
72             sub new {
73 11     11 1 690 my $class = shift;
74 11 100       64 my ($filename) = @_? @_: $class->list_databases
    50          
75             or croak "bad database: empty share directory: $DATABASE_DIR";
76 11         247 my $path = File::Spec->rel2abs($filename, $DATABASE_DIR);
77 11 100       647 -e $path or croak "bad database: file does not exist: $path";
78 9         216 my $schema =
79             Math::DifferenceSet::Planar::Schema->connect(
80             "dbi:SQLite:$path", q[], q[],
81             { sqlite_open_flags => SQLITE_OPEN_READONLY },
82             );
83 9         347759 my $data = $schema->resultset('DifferenceSet');
84 9         4820 my $count = eval { $data->search->count };
  9         52  
85 9 100       233571 croak "bad database: query failed: $@" if !defined $count;
86 8         218 my $spaces = $schema->resultset('DifferenceSetSpace');
87 8 100       3164 undef $spaces if !eval { $spaces->search->count };
  8         77  
88 8         31214 return bless [$data, $spaces, $path], $class;
89             }
90              
91             # ----- object methods -----
92              
93             sub get {
94 45     45 1 5602 my ($this, $order, @columns) = @_;
95 45 100       130 return $this->_data->search(
96             { order_ => $order },
97             @columns ? { columns => \@columns } : ()
98             )->single;
99             }
100              
101             sub get_space {
102 16     16 1 1142 my ($this, $order) = @_;
103 16         69 my $spaces = $this->_spaces;
104 16 100       48 return undef if !defined $spaces;
105 15         74 return $spaces->search({ order_ => $order })->single;
106             }
107              
108             sub iterate {
109 6     6 1 16 my ($this, $min, $max) = @_;
110 6         17 return _iterate($this->_data, $min, $max);
111             }
112              
113             sub iterate_properties {
114 5     5 1 5476 my ($this, $min, $max) = @_;
115 5         22 my @columns = qw(order_ base exponent modulus n_planes);
116 5         22 return _iterate($this->_data, $min, $max, @columns);
117             }
118              
119             sub iterate_spaces {
120 6     6 1 1772 my ($this, $min, $max) = @_;
121 6         22 my $spaces = $this->_spaces;
122 6 100   1   24 return sub {} if !defined $spaces;
123 5         19 return _iterate($spaces, $min, $max);
124             }
125              
126 4     4 1 3335 sub min_order { $_[0]->_data->get_column('order_')->min }
127 14     14 1 13024 sub max_order { $_[0]->_data->get_column('order_')->max }
128 5     5 1 11962 sub count { $_[0]->_data->search->count }
129 1     1 1 4587 sub path { $_[0]->_path }
130              
131             sub sp_min_order {
132 3     3 1 4660 my ($this) = @_;
133 3         13 my $spaces = $this->_spaces;
134 3 100       15 return undef if !defined $spaces;
135 2         12 return $spaces->get_column('order_')->min;
136             }
137              
138             sub sp_max_order {
139 9     9 1 4191 my ($this) = @_;
140 9         28 my $spaces = $this->_spaces;
141 9 100       33 return 0 if !defined $spaces;
142 8         65 return $spaces->get_column('order_')->max;
143             }
144              
145             sub sp_count {
146 3     3 1 5815 my ($this) = @_;
147 3         13 my $spaces = $this->_spaces;
148 3 100       16 return 0 if !defined $spaces;
149 2         11 return $spaces->search->count;
150             }
151              
152             1;
153              
154             __END__