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   58737 use strict;
  6         20  
  6         147  
4 6     6   26 use warnings;
  6         12  
  6         159  
5 6     6   29 use Carp qw(croak);
  6         10  
  6         254  
6 6     6   35 use File::Spec;
  6         10  
  6         146  
7 6     6   2094 use File::Share qw(dist_dir);
  6         160825  
  6         347  
8 6     6   2866 use DBD::SQLite::Constants qw(SQLITE_OPEN_READONLY);
  6         163474  
  6         744  
9 6     6   2569 use Math::DifferenceSet::Planar::Schema;
  6         22  
  6         235  
10              
11             # Math::DifferenceSet::Planar::Data=ARRAY(...)
12              
13             # .......... index .......... # .......... value ..........
14 6     6   40 use constant _F_DATA => 0; # difference set result set object
  6         12  
  6         375  
15 6     6   33 use constant _F_SPACES => 1; # PDS space result set object or undef
  6         32  
  6         294  
16 6     6   33 use constant _F_PATH => 2; # database path name
  6         10  
  6         273  
17 6     6   38 use constant _NFIELDS => 3;
  6         13  
  6         7273  
18              
19             our $VERSION = '0.018';
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   31 my ($domain, $min, $max, @columns) = @_;
28 16         27 my @sel = ();
29 16         23 my $dir = 'ASC';
30 16 100 100     73 if (defined($min) && defined($max) && $min > $max) {
      100        
31 3         12 ($min, $max, $dir) = ($max, $min, 'DESC');
32             }
33 16 100       37 push @sel, '>=' => $min if defined $min;
34 16 100       34 push @sel, '<=' => $max if defined $max;
35 16 100       103 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   4187 return sub { $results->next };
  86         18796  
43             }
44              
45             # ----- private accessor methods -----
46              
47 79     79   337 sub _data { $_[0]->[_F_DATA] }
48 37     37   69 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 296 opendir my $dh, $DATABASE_DIR or return ();
55             my @files =
56             map {
57 11 100       52 my $is_standard = /^pds[_\W]/i? 1: 0;
58 11         267 my $path = File::Spec->rel2abs($_, $DATABASE_DIR);
59 11 50       271 (-f $path)? [$_, $is_standard, -s _]: ()
60             }
61 7         232 grep { /\.db\z/i } readdir $dh;
  36         127  
62 7         105 closedir $dh;
63             return
64 11         60 map { $_->[0] }
65             sort {
66 7 50 66     43 $b->[1] <=> $a->[1] || $b->[2] <=> $a->[2] ||
  6         30  
67             $a->[0] cmp $b->[0]
68             }
69             @files;
70             }
71              
72             sub new {
73 11     11 1 598 my $class = shift;
74 11 100       52 my ($filename) = @_? @_: $class->list_databases
    50          
75             or croak "bad database: empty share directory: $DATABASE_DIR";
76 11         223 my $path = File::Spec->rel2abs($filename, $DATABASE_DIR);
77 11 100       604 -e $path or croak "bad database: file does not exist: $path";
78 9         185 my $schema =
79             Math::DifferenceSet::Planar::Schema->connect(
80             "dbi:SQLite:$path", q[], q[],
81             { sqlite_open_flags => SQLITE_OPEN_READONLY },
82             );
83 9         336561 my $data = $schema->resultset('DifferenceSet');
84 9         4468 my $count = eval { $data->search->count };
  9         38  
85 9 100       225177 croak "bad database: query failed: $@" if !defined $count;
86 8         198 my $spaces = $schema->resultset('DifferenceSetSpace');
87 8 100       2587 undef $spaces if !eval { $spaces->search->count };
  8         65  
88 8         26368 return bless [$data, $spaces, $path], $class;
89             }
90              
91             # ----- object methods -----
92              
93             sub get {
94 45     45 1 4468 my ($this, $order, @columns) = @_;
95 45 100       102 return $this->_data->search(
96             { order_ => $order },
97             @columns ? { columns => \@columns } : ()
98             )->single;
99             }
100              
101             sub get_space {
102 16     16 1 810 my ($this, $order) = @_;
103 16         35 my $spaces = $this->_spaces;
104 16 100       44 return undef if !defined $spaces;
105 15         55 return $spaces->search({ order_ => $order })->single;
106             }
107              
108             sub iterate {
109 6     6 1 13 my ($this, $min, $max) = @_;
110 6         13 return _iterate($this->_data, $min, $max);
111             }
112              
113             sub iterate_properties {
114 5     5 1 3936 my ($this, $min, $max) = @_;
115 5         13 my @columns = qw(order_ base exponent modulus n_planes);
116 5         12 return _iterate($this->_data, $min, $max, @columns);
117             }
118              
119             sub iterate_spaces {
120 6     6 1 1765 my ($this, $min, $max) = @_;
121 6         16 my $spaces = $this->_spaces;
122 6 100   1   20 return sub {} if !defined $spaces;
123 5         15 return _iterate($spaces, $min, $max);
124             }
125              
126 4     4 1 2225 sub min_order { $_[0]->_data->get_column('order_')->min }
127 14     14 1 8536 sub max_order { $_[0]->_data->get_column('order_')->max }
128 5     5 1 7705 sub count { $_[0]->_data->search->count }
129 1     1 1 3195 sub path { $_[0]->_path }
130              
131             sub sp_min_order {
132 3     3 1 3256 my ($this) = @_;
133 3         10 my $spaces = $this->_spaces;
134 3 100       14 return undef if !defined $spaces;
135 2         8 return $spaces->get_column('order_')->min;
136             }
137              
138             sub sp_max_order {
139 9     9 1 2793 my ($this) = @_;
140 9         23 my $spaces = $this->_spaces;
141 9 100       25 return 0 if !defined $spaces;
142 8         48 return $spaces->get_column('order_')->max;
143             }
144              
145             sub sp_count {
146 3     3 1 3755 my ($this) = @_;
147 3         12 my $spaces = $this->_spaces;
148 3 100       18 return 0 if !defined $spaces;
149 2         8 return $spaces->search->count;
150             }
151              
152             1;
153              
154             __END__