| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Embedix::DB::Pg; | 
| 2 |  |  |  |  |  |  |  | 
| 3 | 2 |  |  | 2 |  | 12 | use strict; | 
|  | 2 |  |  |  |  | 2 |  | 
|  | 2 |  |  |  |  | 126 |  | 
| 4 | 2 |  |  | 2 |  | 13 | use vars qw($AUTOLOAD); | 
|  | 2 |  |  |  |  | 4 |  | 
|  | 2 |  |  |  |  | 103 |  | 
| 5 |  |  |  |  |  |  |  | 
| 6 |  |  |  |  |  |  | # for warning message from the caller's perspective | 
| 7 | 2 |  |  | 2 |  | 11 | use Carp; | 
|  | 2 |  |  |  |  | 5 |  | 
|  | 2 |  |  |  |  | 150 |  | 
| 8 |  |  |  |  |  |  |  | 
| 9 |  |  |  |  |  |  | # for loading data from files | 
| 10 | 2 |  |  | 2 |  | 11 | use Embedix::ECD; | 
|  | 2 |  |  |  |  | 4 |  | 
|  | 2 |  |  |  |  | 52 |  | 
| 11 |  |  |  |  |  |  |  | 
| 12 |  |  |  |  |  |  | # for database support | 
| 13 | 2 |  |  | 2 |  | 5218 | use DBI; | 
|  | 2 |  |  |  |  | 105966 |  | 
|  | 2 |  |  |  |  | 24058 |  | 
| 14 |  |  |  |  |  |  |  | 
| 15 |  |  |  |  |  |  | # constructor | 
| 16 |  |  |  |  |  |  | #_______________________________________ | 
| 17 |  |  |  |  |  |  | sub new { | 
| 18 | 0 |  |  | 0 | 1 |  | my $proto = shift; | 
| 19 | 0 |  | 0 |  |  |  | my $class = ref($proto) || $proto; | 
| 20 | 0 | 0 |  |  |  |  | (@_ & 1) && croak("Odd number of parameters."); | 
| 21 | 0 |  |  |  |  |  | my %opt   = @_; | 
| 22 |  |  |  |  |  |  |  | 
| 23 | 0 |  | 0 |  |  |  | my $dbh  = DBI->connect(@{$opt{source}}) || croak($DBI::errstr); | 
| 24 | 0 |  |  |  |  |  | my $self = { | 
| 25 |  |  |  |  |  |  | dbh        => $dbh, | 
| 26 |  |  |  |  |  |  | distro     => undef,    # hashref w/ info on current working distro | 
| 27 |  |  |  |  |  |  | path_cache => { },      # $path_cache->{node_id} eq $path | 
| 28 |  |  |  |  |  |  | }; | 
| 29 | 0 |  |  |  |  |  | bless($self => $class); | 
| 30 |  |  |  |  |  |  |  | 
| 31 |  |  |  |  |  |  | #self->workOnDistro(name => $opt{name}, board => $opt{board}); | 
| 32 | 0 |  |  |  |  |  | return $self; | 
| 33 |  |  |  |  |  |  | } | 
| 34 |  |  |  |  |  |  |  | 
| 35 |  |  |  |  |  |  | # destructor | 
| 36 |  |  |  |  |  |  | #_______________________________________ | 
| 37 |  |  |  |  |  |  | sub DESTROY { | 
| 38 | 0 |  |  | 0 |  |  | my $self = shift; | 
| 39 | 0 |  |  |  |  |  | $self->{dbh}->disconnect(); | 
| 40 |  |  |  |  |  |  | } | 
| 41 |  |  |  |  |  |  |  | 
| 42 |  |  |  |  |  |  | # for when things go wrong... | 
| 43 |  |  |  |  |  |  | #_______________________________________ | 
| 44 |  |  |  |  |  |  | sub rollbackAndCroak { | 
| 45 | 0 |  |  | 0 | 0 |  | my $self = shift; | 
| 46 | 0 |  |  |  |  |  | my $msg  = shift; | 
| 47 | 0 |  |  |  |  |  | my $dbh  = $self->{dbh}; | 
| 48 | 0 |  |  |  |  |  | my $err  = $dbh->errstr . "\n$msg"; | 
| 49 | 0 |  |  |  |  |  | $dbh->rollback; | 
| 50 | 0 |  |  |  |  |  | croak($err); | 
| 51 |  |  |  |  |  |  | } | 
| 52 |  |  |  |  |  |  |  | 
| 53 |  |  |  |  |  |  | # $insert_statement = $hotel->buildInsertStatement ( | 
| 54 |  |  |  |  |  |  | #     table => "table", | 
| 55 |  |  |  |  |  |  | #     data  => \%column | 
| 56 |  |  |  |  |  |  | # ); | 
| 57 |  |  |  |  |  |  | #_______________________________________ | 
| 58 |  |  |  |  |  |  | sub buildInsertStatement { | 
| 59 | 0 |  |  | 0 | 0 |  | my $self = shift; | 
| 60 | 0 |  |  |  |  |  | my $dbh  = $self->{dbh}; | 
| 61 |  |  |  |  |  |  |  | 
| 62 | 0 | 0 |  |  |  |  | (@_ & 1) && croak "Odd number of parameters\n"; | 
| 63 | 0 |  |  |  |  |  | my %opt    = @_; | 
| 64 | 0 |  |  |  |  |  | my $column = $opt{data}; | 
| 65 |  |  |  |  |  |  |  | 
| 66 | 0 |  |  |  |  |  | my $insert = "insert into $opt{table} ( "; | 
| 67 | 0 |  |  |  |  |  | $insert .= join(", ", keys %$column); | 
| 68 | 0 |  |  |  |  |  | $insert =~ s/, $//; | 
| 69 | 0 |  |  |  |  |  | $insert .= " ) values ( "; | 
| 70 | 0 |  |  |  |  |  | $insert .= join(", ", map { $dbh->quote($_) } values %$column); | 
|  | 0 |  |  |  |  |  |  | 
| 71 | 0 |  |  |  |  |  | $insert =~ s/, $//; | 
| 72 | 0 |  |  |  |  |  | $insert .= " );"; | 
| 73 |  |  |  |  |  |  |  | 
| 74 | 0 |  |  |  |  |  | return $insert; | 
| 75 |  |  |  |  |  |  | } | 
| 76 |  |  |  |  |  |  |  | 
| 77 |  |  |  |  |  |  | # $update_statement = $hotel->buildUpdateStatement ( | 
| 78 |  |  |  |  |  |  | #     table => "table", | 
| 79 |  |  |  |  |  |  | #     data  => \%column, | 
| 80 |  |  |  |  |  |  | #     where => "id = 'whatever'", | 
| 81 |  |  |  |  |  |  | #     primary_key => 'id', | 
| 82 |  |  |  |  |  |  | # ); | 
| 83 |  |  |  |  |  |  | # | 
| 84 |  |  |  |  |  |  | # note that you should use 'where' xor 'primary_key'. | 
| 85 |  |  |  |  |  |  | # do not use both at the same time | 
| 86 |  |  |  |  |  |  | # use at least one of them.  ...xor | 
| 87 |  |  |  |  |  |  | #_______________________________________ | 
| 88 |  |  |  |  |  |  | sub buildUpdateStatement { | 
| 89 | 0 |  |  | 0 | 0 |  | my $self = shift; | 
| 90 | 0 |  |  |  |  |  | my $dbh  = $self->{dbh}; | 
| 91 |  |  |  |  |  |  |  | 
| 92 | 0 | 0 |  |  |  |  | (@_ & 1) && croak "Odd number of parameters\n"; | 
| 93 | 0 |  |  |  |  |  | my %opt    = @_; | 
| 94 | 0 |  |  |  |  |  | my $column = $opt{data}; | 
| 95 |  |  |  |  |  |  |  | 
| 96 | 0 |  |  |  |  |  | my $update = "update $opt{table} set "; | 
| 97 | 0 |  |  |  |  |  | foreach (keys %$column) { | 
| 98 | 0 |  |  |  |  |  | $update .= "$_ = " . $dbh->quote($column->{$_}) . ", "; | 
| 99 |  |  |  |  |  |  | } | 
| 100 | 0 |  |  |  |  |  | $update =~ s/, $//; | 
| 101 |  |  |  |  |  |  |  | 
| 102 | 0 |  |  |  |  |  | $update .= " where "; | 
| 103 | 0 | 0 |  |  |  |  | if (defined $opt{where}) { | 
|  |  | 0 |  |  |  |  |  | 
| 104 | 0 |  |  |  |  |  | $update .= "$opt{where};"; | 
| 105 |  |  |  |  |  |  | } elsif (defined $opt{primary_key}) { | 
| 106 | 0 |  |  |  |  |  | my $pk = $opt{primary_key}; | 
| 107 | 0 |  |  |  |  |  | $update .= "$pk = '$column->{$pk}';"; | 
| 108 |  |  |  |  |  |  | } else { | 
| 109 | 0 |  |  |  |  |  | croak "buildUpdateStatement w/o a WHERE clause\n"; | 
| 110 |  |  |  |  |  |  | } | 
| 111 |  |  |  |  |  |  |  | 
| 112 | 0 |  |  |  |  |  | return $update; | 
| 113 |  |  |  |  |  |  | } | 
| 114 |  |  |  |  |  |  |  | 
| 115 |  |  |  |  |  |  | # return the current value of a sequence. | 
| 116 |  |  |  |  |  |  | # This is a front end to PostgreSQL's currval() function. | 
| 117 |  |  |  |  |  |  | #_______________________________________ | 
| 118 |  |  |  |  |  |  | sub currval { | 
| 119 | 0 |  |  | 0 | 0 |  | my $self = shift; | 
| 120 | 0 |  |  |  |  |  | my $seq  = shift; | 
| 121 | 0 |  |  |  |  |  | my $dbh  = $self->{dbh}; | 
| 122 | 0 |  |  |  |  |  | my $sth  = $dbh->prepare("select currval('$seq')"); | 
| 123 | 0 |  |  |  |  |  | $sth->execute; | 
| 124 | 0 |  |  |  |  |  | my @val  = $sth->fetchrow_array; | 
| 125 | 0 |  |  |  |  |  | $sth->finish; | 
| 126 | 0 |  |  |  |  |  | return $val[0]; | 
| 127 |  |  |  |  |  |  | } | 
| 128 |  |  |  |  |  |  |  | 
| 129 |  |  |  |  |  |  | # return the next value of a sequence. | 
| 130 |  |  |  |  |  |  | # This is a front end to PostgreSQL's currval() function. | 
| 131 |  |  |  |  |  |  | #_______________________________________ | 
| 132 |  |  |  |  |  |  | sub nextval { | 
| 133 | 0 |  |  | 0 | 0 |  | my $self = shift; | 
| 134 | 0 |  |  |  |  |  | my $seq  = shift; | 
| 135 | 0 |  |  |  |  |  | my $dbh  = $self->{dbh}; | 
| 136 | 0 |  |  |  |  |  | my $sth  = $dbh->prepare("select nextval('$seq')"); | 
| 137 | 0 |  |  |  |  |  | $sth->execute; | 
| 138 | 0 |  |  |  |  |  | my @val  = $sth->fetchrow_array; | 
| 139 | 0 |  |  |  |  |  | $sth->finish; | 
| 140 | 0 |  |  |  |  |  | return $val[0]; | 
| 141 |  |  |  |  |  |  | } | 
| 142 |  |  |  |  |  |  |  | 
| 143 |  |  |  |  |  |  | # Set the distribution that database opererations will work on. | 
| 144 |  |  |  |  |  |  | # If the distribution is not found, this method will croak(). | 
| 145 |  |  |  |  |  |  | #_______________________________________ | 
| 146 |  |  |  |  |  |  | sub workOnDistro { | 
| 147 | 0 | 0 |  | 0 | 1 |  | my $self = shift; (@_ & 1) && croak("Odd number of parameters."); | 
|  | 0 |  |  |  |  |  |  | 
| 148 | 0 |  |  |  |  |  | my %opt  = @_; | 
| 149 |  |  |  |  |  |  |  | 
| 150 | 0 | 0 |  |  |  |  | defined($opt{name})  || croak('name => REQUIRED!'); | 
| 151 | 0 | 0 |  |  |  |  | defined($opt{board}) || croak('board => REQUIRED!'); | 
| 152 |  |  |  |  |  |  |  | 
| 153 |  |  |  |  |  |  | # get distro from database | 
| 154 | 0 |  |  |  |  |  | my $q = qq{ select * from distro where distro_name = ? and board = ? }; | 
| 155 | 0 |  |  |  |  |  | my $dbh = $self->{dbh}; | 
| 156 | 0 |  |  |  |  |  | my $sth = $dbh->prepare($q); | 
| 157 |  |  |  |  |  |  |  | 
| 158 | 0 |  |  |  |  |  | $sth->execute($opt{name}, $opt{board}); | 
| 159 | 0 |  |  |  |  |  | my $distro = $sth->fetchrow_hashref(); | 
| 160 | 0 |  |  |  |  |  | $sth->finish; | 
| 161 |  |  |  |  |  |  |  | 
| 162 | 0 | 0 |  |  |  |  | if (defined($distro)) { | 
| 163 | 0 |  |  |  |  |  | $self->{distro} = $distro; | 
| 164 |  |  |  |  |  |  | } else { | 
| 165 | 0 |  |  |  |  |  | croak("$opt{name} for $opt{board} was not found."); | 
| 166 |  |  |  |  |  |  | } | 
| 167 |  |  |  |  |  |  |  | 
| 168 |  |  |  |  |  |  | # reinitialize caches | 
| 169 | 0 |  |  |  |  |  | $self->{path_cache} = { }; | 
| 170 |  |  |  |  |  |  |  | 
| 171 | 0 |  |  |  |  |  | return $self->{distro}; | 
| 172 |  |  |  |  |  |  | } | 
| 173 |  |  |  |  |  |  |  | 
| 174 |  |  |  |  |  |  | # adds an new entry into the distro table as well as an entry | 
| 175 |  |  |  |  |  |  | # in the node table for the root node. | 
| 176 |  |  |  |  |  |  | #_______________________________________ | 
| 177 |  |  |  |  |  |  | sub addDistro { | 
| 178 | 0 | 0 |  | 0 | 1 |  | my $self = shift; (@_ & 1) && croak("Odd number of parameters."); | 
|  | 0 |  |  |  |  |  |  | 
| 179 | 0 |  |  |  |  |  | my %opt  = @_; | 
| 180 | 0 |  |  |  |  |  | my $dbh  = $self->{dbh}; | 
| 181 | 0 |  |  |  |  |  | my ($sth1, $sth2, $q); | 
| 182 |  |  |  |  |  |  |  | 
| 183 |  |  |  |  |  |  | # get root_node_id | 
| 184 | 0 | 0 |  |  |  |  | my $root_node_id = defined($opt{root_node_id}) | 
| 185 |  |  |  |  |  |  | ? $opt{root_node_id} | 
| 186 |  |  |  |  |  |  | : $self->nextval('node_node_id_seq'); | 
| 187 |  |  |  |  |  |  |  | 
| 188 |  |  |  |  |  |  | # distro table entry | 
| 189 | 0 |  | 0 |  |  |  | my $distro = { | 
|  |  |  | 0 |  |  |  |  | 
|  |  |  | 0 |  |  |  |  | 
| 190 |  |  |  |  |  |  | distro_name  => $opt{name}          || croak("name required"), | 
| 191 |  |  |  |  |  |  | board        => $opt{board}         || croak("board required"), | 
| 192 |  |  |  |  |  |  | description  => $opt{description}   || "no description available", | 
| 193 |  |  |  |  |  |  | root_node_id => $root_node_id, | 
| 194 |  |  |  |  |  |  | }; | 
| 195 | 0 |  |  |  |  |  | $q = $self->buildInsertStatement(table => "distro", data => $distro); | 
| 196 | 0 |  |  |  |  |  | $sth1 = $dbh->prepare($q); | 
| 197 | 0 | 0 |  |  |  |  | $sth1->execute || do { $self->rollbackAndCroak($q) }; | 
|  | 0 |  |  |  |  |  |  | 
| 198 | 0 |  |  |  |  |  | $sth1->finish; | 
| 199 |  |  |  |  |  |  |  | 
| 200 |  |  |  |  |  |  | # get distro_id | 
| 201 | 0 |  |  |  |  |  | my $distro_id = $self->currval('distro_distro_id_seq'); | 
| 202 | 0 |  |  |  |  |  | $distro->{distro_id} = $distro_id; | 
| 203 |  |  |  |  |  |  |  | 
| 204 |  |  |  |  |  |  | # root node | 
| 205 | 0 |  |  |  |  |  | my $root = { | 
| 206 |  |  |  |  |  |  | node_id    => $root_node_id, | 
| 207 |  |  |  |  |  |  | node_name  => 'ecd', | 
| 208 |  |  |  |  |  |  | node_class => 'Root', | 
| 209 |  |  |  |  |  |  | }; | 
| 210 |  |  |  |  |  |  |  | 
| 211 |  |  |  |  |  |  | # make a root node if necessary | 
| 212 | 0 | 0 |  |  |  |  | unless (defined($opt{root_node_id})) { | 
| 213 | 0 |  |  |  |  |  | $q = $self->buildInsertStatement(table => "node", data => $root); | 
| 214 | 0 |  |  |  |  |  | $sth2 = $dbh->prepare($q); | 
| 215 | 0 | 0 |  |  |  |  | $sth2->execute || do { $self->rollbackAndCroak($q) }; | 
|  | 0 |  |  |  |  |  |  | 
| 216 | 0 |  |  |  |  |  | $sth2->finish; | 
| 217 |  |  |  |  |  |  | #rint STDERR "[edb relating: $root->{node_id} To: $distro->{distro_id}]\n"; | 
| 218 | 0 |  |  |  |  |  | $self->relateNode(node => $root, distro => $distro); | 
| 219 |  |  |  |  |  |  | } | 
| 220 | 0 |  |  |  |  |  | $dbh->commit; | 
| 221 | 0 |  |  |  |  |  | return $distro; | 
| 222 |  |  |  |  |  |  | } | 
| 223 |  |  |  |  |  |  |  | 
| 224 |  |  |  |  |  |  | # associate a node with a distro by adding an entry | 
| 225 |  |  |  |  |  |  | # to the node_distro table | 
| 226 |  |  |  |  |  |  | #_______________________________________ | 
| 227 |  |  |  |  |  |  | sub relateNode { | 
| 228 | 0 | 0 |  | 0 | 0 |  | my $self = shift; (@_ & 1) && croak("Odd number of parameters."); | 
|  | 0 |  |  |  |  |  |  | 
| 229 | 0 |  |  |  |  |  | my %opt  = @_; | 
| 230 | 0 | 0 |  |  |  |  | defined ($opt{node})   || croak('node => REQUIRED!'); | 
| 231 | 0 | 0 |  |  |  |  | defined ($opt{distro}) || croak('distro => REQUIRED!'); | 
| 232 | 0 |  |  |  |  |  | my $dbh  = $self->{dbh}; | 
| 233 | 0 |  |  |  |  |  | my $s    = qq/ | 
| 234 |  |  |  |  |  |  | insert into node_distro (node_id, distro_id) | 
| 235 |  |  |  |  |  |  | values ($opt{node}{node_id}, $opt{distro}{distro_id}) | 
| 236 |  |  |  |  |  |  | /; | 
| 237 | 0 | 0 |  |  |  |  | $dbh->do($s) || $self->rollbackAndCroak($s); | 
| 238 |  |  |  |  |  |  | } | 
| 239 |  |  |  |  |  |  |  | 
| 240 |  |  |  |  |  |  | # remove association of node from distro by deleting an entry | 
| 241 |  |  |  |  |  |  | # in the node_distro table | 
| 242 |  |  |  |  |  |  | #_______________________________________ | 
| 243 |  |  |  |  |  |  | sub unrelateNode { | 
| 244 | 0 | 0 |  | 0 | 0 |  | my $self = shift; (@_ & 1) && croak("Odd number of parameters."); | 
|  | 0 |  |  |  |  |  |  | 
| 245 | 0 |  |  |  |  |  | my %opt  = @_; | 
| 246 | 0 | 0 |  |  |  |  | defined ($opt{node})   || croak('node => REQUIRED!'); | 
| 247 | 0 | 0 |  |  |  |  | defined ($opt{distro}) || croak('distro => REQUIRED!'); | 
| 248 | 0 |  |  |  |  |  | my $dbh  = $self->{dbh}; | 
| 249 | 0 |  |  |  |  |  | my $s    = qq/ | 
| 250 |  |  |  |  |  |  | delete from node_distro | 
| 251 |  |  |  |  |  |  | where node_id   = $opt{node}{node_id} | 
| 252 |  |  |  |  |  |  | and distro_id = $opt{distro}{distro_id} | 
| 253 |  |  |  |  |  |  | /; | 
| 254 | 0 | 0 |  |  |  |  | $dbh->do($s) || $self->rollbackAndCroak($s); | 
| 255 |  |  |  |  |  |  |  | 
| 256 |  |  |  |  |  |  | } | 
| 257 |  |  |  |  |  |  |  | 
| 258 |  |  |  |  |  |  | # using the current working distro, make an exact | 
| 259 |  |  |  |  |  |  | # clone for another architecture. | 
| 260 |  |  |  |  |  |  | #_______________________________________ | 
| 261 |  |  |  |  |  |  | sub cloneDistro { | 
| 262 | 0 | 0 |  | 0 | 1 |  | my $self = shift; (@_ & 1) && croak("Odd number of parameters."); | 
|  | 0 |  |  |  |  |  |  | 
| 263 | 0 |  |  |  |  |  | my %opt  = @_; | 
| 264 | 0 |  |  |  |  |  | my $dbh  = $self->{dbh}; | 
| 265 |  |  |  |  |  |  |  | 
| 266 | 0 | 0 |  |  |  |  | defined($opt{board}) || croak('board => REQUIRED!'); | 
| 267 |  |  |  |  |  |  |  | 
| 268 |  |  |  |  |  |  | # get root_node_id | 
| 269 | 0 |  |  |  |  |  | my $root_node_id = $self->{distro}{root_node_id}; | 
| 270 |  |  |  |  |  |  |  | 
| 271 |  |  |  |  |  |  | # cloned distro entry | 
| 272 | 0 |  |  |  |  |  | my $distro = $self->{distro}; | 
| 273 | 0 |  | 0 |  |  |  | my $clone  = $self->addDistro ( | 
| 274 |  |  |  |  |  |  | name         => $distro->{distro_name}, | 
| 275 |  |  |  |  |  |  | board        => $opt{board}, | 
| 276 |  |  |  |  |  |  | description  => $opt{description} || $distro->{description}, | 
| 277 |  |  |  |  |  |  | root_node_id => $root_node_id, | 
| 278 |  |  |  |  |  |  | ); | 
| 279 |  |  |  |  |  |  |  | 
| 280 |  |  |  |  |  |  | # get distro_id | 
| 281 | 0 |  |  |  |  |  | my $distro_id = $self->currval('distro_distro_id_seq'); | 
| 282 | 0 |  |  |  |  |  | $clone->{distro_id} = $distro_id; | 
| 283 |  |  |  |  |  |  |  | 
| 284 |  |  |  |  |  |  | # node_id collection | 
| 285 | 0 |  |  |  |  |  | my $s = qq/ | 
| 286 |  |  |  |  |  |  | select n.node_id | 
| 287 |  |  |  |  |  |  | from node n, node_distro nd | 
| 288 |  |  |  |  |  |  | where n.node_id = nd.node_id | 
| 289 |  |  |  |  |  |  | and nd.distro_id = $self->{distro}{distro_id} | 
| 290 |  |  |  |  |  |  | /; | 
| 291 | 0 |  |  |  |  |  | my $node_list = $dbh->selectall_arrayref($s); | 
| 292 |  |  |  |  |  |  |  | 
| 293 |  |  |  |  |  |  | # node_distro manipulation | 
| 294 | 0 |  |  |  |  |  | $s = qq/ insert into node_distro (node_id, distro_id) values (?, ?) /; | 
| 295 | 0 |  |  |  |  |  | my $sth = $dbh->prepare_cached($s); | 
| 296 | 0 |  |  |  |  |  | my $node; | 
| 297 | 0 |  |  |  |  |  | foreach $node (@$node_list) { | 
| 298 | 0 | 0 |  |  |  |  | $sth->execute($node->[0], $distro_id) | 
| 299 |  |  |  |  |  |  | || $self->rollbackAndCroak($node->[0]); | 
| 300 |  |  |  |  |  |  | } | 
| 301 | 0 |  |  |  |  |  | $sth->finish; | 
| 302 | 0 |  |  |  |  |  | $dbh->commit; | 
| 303 | 0 |  |  |  |  |  | return $clone; | 
| 304 |  |  |  |  |  |  | } | 
| 305 |  |  |  |  |  |  |  | 
| 306 |  |  |  |  |  |  | # delete a node and all its children | 
| 307 |  |  |  |  |  |  | #_______________________________________ | 
| 308 |  |  |  |  |  |  | sub deleteNode { | 
| 309 | 0 | 0 |  | 0 | 0 |  | my $self = shift; (@_ & 1) && croak("Odd number of parameters."); | 
|  | 0 |  |  |  |  |  |  | 
| 310 | 0 |  |  |  |  |  | my %opt  = @_; | 
| 311 | 0 |  |  |  |  |  | my $dbh  = $self->{dbh}; | 
| 312 |  |  |  |  |  |  |  | 
| 313 | 0 | 0 |  |  |  |  | $dbh->do("delete from node where node_id = $opt{node_id}") | 
| 314 |  |  |  |  |  |  | || $self->rollbackAndCroak("failed delete"); | 
| 315 |  |  |  |  |  |  | } | 
| 316 |  |  |  |  |  |  |  | 
| 317 |  |  |  |  |  |  | #_______________________________________ | 
| 318 |  |  |  |  |  |  | sub selectNode { | 
| 319 | 0 | 0 |  | 0 | 0 |  | my $self = shift; (@_ & 1) && croak("Odd number of parameters."); | 
|  | 0 |  |  |  |  |  |  | 
| 320 | 0 |  |  |  |  |  | my %opt  = @_; | 
| 321 |  |  |  |  |  |  |  | 
| 322 | 0 |  |  |  |  |  | my $q = qq( | 
| 323 |  |  |  |  |  |  | select n.node_id, | 
| 324 |  |  |  |  |  |  | n.node_class, | 
| 325 |  |  |  |  |  |  | n.node_name, | 
| 326 |  |  |  |  |  |  | n.value, | 
| 327 |  |  |  |  |  |  | n.value_type, | 
| 328 |  |  |  |  |  |  | n.default_value, | 
| 329 |  |  |  |  |  |  | n.range, | 
| 330 |  |  |  |  |  |  | n.help, | 
| 331 |  |  |  |  |  |  | n.prompt, | 
| 332 |  |  |  |  |  |  | n.srpm, | 
| 333 |  |  |  |  |  |  | n.specpatch, | 
| 334 |  |  |  |  |  |  | n.static_size, n.min_dynamic_size, | 
| 335 |  |  |  |  |  |  | n.storage_size, n.startup_time | 
| 336 |  |  |  |  |  |  | from node n, node_parent np, node_distro nd | 
| 337 |  |  |  |  |  |  | where n.node_id        = np.node_id | 
| 338 |  |  |  |  |  |  | and n.node_id    = nd.node_id | 
| 339 |  |  |  |  |  |  | and nd.distro_id = $self->{distro}{distro_id} | 
| 340 |  |  |  |  |  |  | and n.node_name  = ? | 
| 341 |  |  |  |  |  |  | and np.parent_id = ? | 
| 342 |  |  |  |  |  |  | ); | 
| 343 |  |  |  |  |  |  |  | 
| 344 | 0 |  |  |  |  |  | my $dbh = $self->{dbh}; | 
| 345 | 0 |  |  |  |  |  | my $sth = $dbh->prepare($q); | 
| 346 | 0 |  |  |  |  |  | my ($name, $parent_id); | 
| 347 | 0 | 0 |  |  |  |  | if (defined $opt{path}) { | 
| 348 |  |  |  |  |  |  |  | 
| 349 |  |  |  |  |  |  | # XXX => implement getIdForPath() | 
| 350 |  |  |  |  |  |  |  | 
| 351 |  |  |  |  |  |  | } else { | 
| 352 | 0 |  |  |  |  |  | $name      = $opt{name}; | 
| 353 | 0 |  |  |  |  |  | $parent_id = $opt{parent_id}; | 
| 354 |  |  |  |  |  |  | } | 
| 355 | 0 |  |  |  |  |  | $sth->execute($name, $parent_id); | 
| 356 | 0 |  |  |  |  |  | my $node = $sth->fetchrow_hashref;  # there can only be one | 
| 357 | 0 |  |  |  |  |  | $sth->finish; | 
| 358 | 0 |  |  |  |  |  | return $node; | 
| 359 |  |  |  |  |  |  | } | 
| 360 |  |  |  |  |  |  |  | 
| 361 |  |  |  |  |  |  | # prereq => no provides entry for $node_id must exist | 
| 362 |  |  |  |  |  |  | #_______________________________________ | 
| 363 |  |  |  |  |  |  | sub insertProvides { | 
| 364 | 0 |  |  | 0 | 0 |  | my $self     = shift; | 
| 365 | 0 |  |  |  |  |  | my $provides = shift; | 
| 366 | 0 | 0 |  |  |  |  | return unless ($provides); | 
| 367 | 0 |  | 0 |  |  |  | my $node_id  = shift || croak("node_id REQUIRED!"); | 
| 368 | 0 |  |  |  |  |  | my $dbh      = $self->{dbh}; | 
| 369 | 0 |  |  |  |  |  | my %item; | 
| 370 |  |  |  |  |  |  |  | 
| 371 | 0 |  |  |  |  |  | my $s = qq{ insert into provides (node_id, entry) values ( ?, ? ) }; | 
| 372 | 0 |  |  |  |  |  | my $sth = $dbh->prepare($s); | 
| 373 | 0 | 0 |  |  |  |  | $provides = [ $provides ] unless (ref($provides)); | 
| 374 | 0 |  |  |  |  |  | foreach (@$provides) { | 
| 375 | 0 | 0 |  |  |  |  | next if /^$/; | 
| 376 | 0 | 0 |  |  |  |  | if (defined $item{$_}) { | 
| 377 | 0 |  |  |  |  |  | carp("[ $node_id, $_ ] already exists"); | 
| 378 |  |  |  |  |  |  | } else { | 
| 379 | 0 |  |  |  |  |  | $item{$_} = 1; | 
| 380 | 0 | 0 |  |  |  |  | $sth->execute($node_id, $_) || | 
| 381 |  |  |  |  |  |  | croak("[ $node_id, $_ ] " . $dbh->errstr); | 
| 382 |  |  |  |  |  |  | } | 
| 383 |  |  |  |  |  |  | } | 
| 384 | 0 |  |  |  |  |  | $sth->finish; | 
| 385 |  |  |  |  |  |  | } | 
| 386 |  |  |  |  |  |  |  | 
| 387 |  |  |  |  |  |  | # prereq => no keeplist entry for $node_id must exist | 
| 388 |  |  |  |  |  |  | #_______________________________________ | 
| 389 |  |  |  |  |  |  | sub insertKeeplist { | 
| 390 | 0 |  |  | 0 | 0 |  | my $self     = shift; | 
| 391 | 0 |  |  |  |  |  | my $keeplist = shift; | 
| 392 | 0 | 0 |  |  |  |  | return unless ($keeplist); | 
| 393 | 0 |  | 0 |  |  |  | my $node_id  = shift || croak("node_id REQUIRED!"); | 
| 394 | 0 |  |  |  |  |  | my $dbh      = $self->{dbh}; | 
| 395 | 0 |  |  |  |  |  | my %item; | 
| 396 |  |  |  |  |  |  |  | 
| 397 | 0 |  |  |  |  |  | my $s = qq{ insert into keeplist (node_id, entry) values ( ?, ? ) }; | 
| 398 | 0 |  |  |  |  |  | my $sth = $dbh->prepare($s); | 
| 399 | 0 | 0 |  |  |  |  | $keeplist = [ $keeplist ] unless (ref($keeplist)); | 
| 400 | 0 |  |  |  |  |  | foreach (@$keeplist) { | 
| 401 | 0 | 0 |  |  |  |  | next if /^$/; | 
| 402 | 0 | 0 |  |  |  |  | if (defined $item{$_}) { | 
| 403 | 0 |  |  |  |  |  | carp("[ $node_id, $_ ] already exists"); | 
| 404 |  |  |  |  |  |  | } else { | 
| 405 | 0 |  |  |  |  |  | $item{$_} = 1; | 
| 406 | 0 | 0 |  |  |  |  | $sth->execute($node_id, $_) || | 
| 407 |  |  |  |  |  |  | croak("[ $node_id, $_ ] " . $dbh->errstr); | 
| 408 |  |  |  |  |  |  | } | 
| 409 |  |  |  |  |  |  | } | 
| 410 | 0 |  |  |  |  |  | $sth->finish; | 
| 411 |  |  |  |  |  |  | } | 
| 412 |  |  |  |  |  |  |  | 
| 413 |  |  |  |  |  |  | # prereq => no build_vars entry for $node_id must exist | 
| 414 |  |  |  |  |  |  | #_______________________________________ | 
| 415 |  |  |  |  |  |  | sub insertBuildVars { | 
| 416 | 0 |  |  | 0 | 0 |  | my $self     = shift; | 
| 417 | 0 |  |  |  |  |  | my $build_vars = shift; | 
| 418 | 0 | 0 |  |  |  |  | return unless ($build_vars); | 
| 419 | 0 |  | 0 |  |  |  | my $node_id  = shift || croak("node_id REQUIRED!"); | 
| 420 | 0 |  |  |  |  |  | my $dbh      = $self->{dbh}; | 
| 421 | 0 |  |  |  |  |  | my %item; | 
| 422 |  |  |  |  |  |  |  | 
| 423 | 0 |  |  |  |  |  | my $s = 'insert into build_vars (node_id, name, value) values (?, ?, ?)'; | 
| 424 | 0 |  |  |  |  |  | my $sth = $dbh->prepare($s); | 
| 425 | 0 | 0 |  |  |  |  | $build_vars = [ $build_vars ] unless (ref($build_vars)); | 
| 426 | 0 |  |  |  |  |  | foreach (@$build_vars) { | 
| 427 | 0 | 0 |  |  |  |  | next if /^$/; | 
| 428 | 0 |  |  |  |  |  | my ($n, $v) = split(/\s*=\s*/); | 
| 429 | 0 | 0 |  |  |  |  | if (defined $item{$n}) { | 
| 430 | 0 |  |  |  |  |  | carp("[ $node_id, $n ] already exists"); | 
| 431 |  |  |  |  |  |  | } else { | 
| 432 | 0 |  |  |  |  |  | $item{$n} = 1; | 
| 433 | 0 | 0 |  |  |  |  | $sth->execute($node_id, $n, $v) || | 
| 434 |  |  |  |  |  |  | croak("[ $node_id, $_ ] " . $dbh->errstr); | 
| 435 |  |  |  |  |  |  | } | 
| 436 |  |  |  |  |  |  | } | 
| 437 | 0 |  |  |  |  |  | $sth->finish; | 
| 438 |  |  |  |  |  |  | } | 
| 439 |  |  |  |  |  |  |  | 
| 440 |  |  |  |  |  |  | #_______________________________________ | 
| 441 |  |  |  |  |  |  | sub insertNode { | 
| 442 | 0 | 0 |  | 0 | 0 |  | my $self = shift; (@_ & 1) && croak("Odd number of parameters."); | 
|  | 0 |  |  |  |  |  |  | 
| 443 | 0 |  |  |  |  |  | my %opt  = @_; | 
| 444 |  |  |  |  |  |  |  | 
| 445 | 0 |  | 0 |  |  |  | my $ecd  = $opt{ecd} || croak('ecd => REQUIRED!'); | 
| 446 |  |  |  |  |  |  |  | 
| 447 |  |  |  |  |  |  | # insert into node table | 
| 448 | 0 |  |  |  |  |  | my $node = $self->hashrefFromECD($ecd); | 
| 449 | 0 |  |  |  |  |  | my $s    = $self->buildInsertStatement(table => "node", data => $node); | 
| 450 | 0 |  |  |  |  |  | my $dbh  = $self->{dbh}; | 
| 451 | 0 |  |  |  |  |  | my $sth  = $dbh->prepare($s); | 
| 452 |  |  |  |  |  |  |  | 
| 453 | 0 | 0 |  |  |  |  | $sth->execute || do { $self->rollbackAndCroak($s) }; | 
|  | 0 |  |  |  |  |  |  | 
| 454 | 0 |  |  |  |  |  | $sth->finish; | 
| 455 | 0 |  |  |  |  |  | my $id = $node->{node_id} = $self->currval('node_node_id_seq'); | 
| 456 |  |  |  |  |  |  |  | 
| 457 |  |  |  |  |  |  | # insert aggregate attributes | 
| 458 | 0 |  |  |  |  |  | eval { | 
| 459 | 0 |  |  |  |  |  | $self->insertProvides($ecd->provides, $id); | 
| 460 | 0 |  |  |  |  |  | $self->insertKeeplist($ecd->keeplist, $id); | 
| 461 | 0 |  |  |  |  |  | $self->insertBuildVars($ecd->build_vars, $id); | 
| 462 |  |  |  |  |  |  | }; | 
| 463 | 0 | 0 |  |  |  |  | if ($@) { $self->rollbackAndCroak($@) } | 
|  | 0 |  |  |  |  |  |  | 
| 464 |  |  |  |  |  |  |  | 
| 465 |  |  |  |  |  |  | # insert into node_parent table | 
| 466 | 0 |  |  |  |  |  | my $np   = { node_id => $id, parent_id => $opt{parent_id} }; | 
| 467 | 0 |  |  |  |  |  | my $s2   = $self->buildInsertStatement(table=> "node_parent", data=> $np); | 
| 468 | 0 |  |  |  |  |  | my $sth2 = $dbh->prepare($s2); | 
| 469 | 0 | 0 |  |  |  |  | $sth2->execute || do { $self->rollbackAndCroak($s2) }; | 
|  | 0 |  |  |  |  |  |  | 
| 470 | 0 |  |  |  |  |  | $sth2->finish; | 
| 471 |  |  |  |  |  |  |  | 
| 472 |  |  |  |  |  |  | # insert into node_distro_table | 
| 473 | 0 |  |  |  |  |  | $self->relateNode(node => $node, distro => $self->{distro}); | 
| 474 |  |  |  |  |  |  |  | 
| 475 | 0 |  |  |  |  |  | $dbh->commit; | 
| 476 | 0 |  |  |  |  |  | return $node; | 
| 477 |  |  |  |  |  |  | } | 
| 478 |  |  |  |  |  |  |  | 
| 479 |  |  |  |  |  |  | # XXX : deal w/ aggregate attributes | 
| 480 |  |  |  |  |  |  | #_______________________________________ | 
| 481 |  |  |  |  |  |  | sub updateNode { | 
| 482 | 0 | 0 |  | 0 | 0 |  | my $self = shift; (@_ & 1) && croak("Odd number of parameters."); | 
|  | 0 |  |  |  |  |  |  | 
| 483 | 0 |  |  |  |  |  | my %opt  = @_; | 
| 484 |  |  |  |  |  |  |  | 
| 485 | 0 |  | 0 |  |  |  | my $ecd  = $opt{ecd} || croak('ecd => REQUIRED!'); | 
| 486 |  |  |  |  |  |  |  | 
| 487 | 0 |  |  |  |  |  | my $node = $self->hashrefFromECD($ecd); | 
| 488 | 0 |  | 0 |  |  |  | $node->{node_id} = $opt{node_id} || croak('node_id => REQUIRED!'); | 
| 489 | 0 |  |  |  |  |  | my $s    = $self->buildUpdateStatement( | 
| 490 |  |  |  |  |  |  | table       => "node", | 
| 491 |  |  |  |  |  |  | data        => $node, | 
| 492 |  |  |  |  |  |  | primary_key => "node_id", | 
| 493 |  |  |  |  |  |  | ); | 
| 494 | 0 |  |  |  |  |  | my $dbh  = $self->{dbh}; | 
| 495 | 0 |  |  |  |  |  | my $sth  = $dbh->prepare($s); | 
| 496 |  |  |  |  |  |  |  | 
| 497 | 0 | 0 |  |  |  |  | $sth->execute || do { $self->rollbackAndCroak($s) }; | 
|  | 0 |  |  |  |  |  |  | 
| 498 | 0 |  |  |  |  |  | $sth->finish; | 
| 499 |  |  |  |  |  |  |  | 
| 500 |  |  |  |  |  |  | # nuke aggregate attributes from orbit (it's the only way to be sure) | 
| 501 |  |  |  |  |  |  |  | 
| 502 |  |  |  |  |  |  | # insert aggregate attributes XXX | 
| 503 |  |  |  |  |  |  |  | 
| 504 | 0 |  |  |  |  |  | $dbh->commit; | 
| 505 | 0 |  |  |  |  |  | return $node; | 
| 506 |  |  |  |  |  |  | } | 
| 507 |  |  |  |  |  |  |  | 
| 508 |  |  |  |  |  |  | # Create a hashref suitable for insertion into the node table. | 
| 509 |  |  |  |  |  |  | # This does NOT handle aggregates (but it does handle the range pair). | 
| 510 |  |  |  |  |  |  | #_______________________________________ | 
| 511 |  |  |  |  |  |  | my @node_attribute = qw( | 
| 512 |  |  |  |  |  |  | value type default_value range help prompt srpm specpatch | 
| 513 |  |  |  |  |  |  | requires requiresexpr | 
| 514 |  |  |  |  |  |  | ); | 
| 515 |  |  |  |  |  |  | my @node_eval_attribute = qw( | 
| 516 |  |  |  |  |  |  | static_size min_dynamic_size storage_size startup_time | 
| 517 |  |  |  |  |  |  | ); | 
| 518 |  |  |  |  |  |  | sub hashrefFromECD { | 
| 519 | 0 |  |  | 0 | 0 |  | my $self = shift; | 
| 520 | 0 |  |  |  |  |  | my $ecd  = shift; | 
| 521 | 0 |  |  |  |  |  | my %node = ( | 
| 522 |  |  |  |  |  |  | node_class => $ecd->getNodeClass(), | 
| 523 |  |  |  |  |  |  | node_name  => $ecd->name(), | 
| 524 |  |  |  |  |  |  | ); | 
| 525 | 0 |  |  |  |  |  | my $attr; | 
| 526 | 0 |  |  |  |  |  | foreach (@node_attribute) { | 
| 527 | 0 | 0 |  |  |  |  | if (defined($attr = $ecd->getAttribute($_))) { | 
| 528 | 0 | 0 |  |  |  |  | if (ref($attr)) { | 
| 529 | 0 |  |  |  |  |  | $attr = join("\n", @$attr); | 
| 530 |  |  |  |  |  |  | } | 
| 531 | 0 | 0 |  |  |  |  | if ($_ eq "range") { | 
| 532 | 0 |  |  |  |  |  | my ($x, $y) = split($attr, ":");    # turn it into a pg array | 
| 533 | 0 |  |  |  |  |  | $attr = "{$x, $y}"; | 
| 534 |  |  |  |  |  |  | } | 
| 535 | 0 |  |  |  |  |  | $node{$_} = $attr; | 
| 536 |  |  |  |  |  |  | } | 
| 537 |  |  |  |  |  |  | } | 
| 538 | 0 |  |  |  |  |  | foreach (@node_eval_attribute) { | 
| 539 | 0 | 0 |  |  |  |  | if (defined($attr = $ecd->getAttribute($_))) { | 
| 540 | 0 |  |  |  |  |  | my $eval_method = "eval_$_"; | 
| 541 | 0 |  |  |  |  |  | my ($size, $give_or_take) = $ecd->$eval_method(); | 
| 542 | 0 |  |  |  |  |  | $attr = "{$size, $give_or_take}"; | 
| 543 | 0 |  |  |  |  |  | $node{$_} = $attr; | 
| 544 |  |  |  |  |  |  | } | 
| 545 |  |  |  |  |  |  | } | 
| 546 | 0 | 0 |  |  |  |  | if (defined $node{type}) { | 
| 547 | 0 |  |  |  |  |  | $node{value_type} = $node{type}; | 
| 548 | 0 |  |  |  |  |  | delete($node{type}); | 
| 549 |  |  |  |  |  |  | } | 
| 550 | 0 | 0 | 0 |  |  |  | warn("$node{node_name} has a requires and requiresexpr which is bad.") | 
| 551 |  |  |  |  |  |  | if (defined $node{requires} && defined($node{requiresexpr})); | 
| 552 | 0 | 0 |  |  |  |  | if (defined $node{requires}) { | 
| 553 | 0 |  |  |  |  |  | $node{requires_type} = 'list'; | 
| 554 |  |  |  |  |  |  | } | 
| 555 | 0 | 0 |  |  |  |  | if (defined $node{requiresexpr}) { | 
| 556 | 0 |  |  |  |  |  | $node{requires_type} = 'expr'; | 
| 557 | 0 |  |  |  |  |  | $node{requires} = $node{requiresexpr}; | 
| 558 | 0 |  |  |  |  |  | delete($node{requiresexpr}); | 
| 559 |  |  |  |  |  |  | }; | 
| 560 | 0 |  |  |  |  |  | return \%node; | 
| 561 |  |  |  |  |  |  | } | 
| 562 |  |  |  |  |  |  |  | 
| 563 |  |  |  |  |  |  | # add info in $ecd to current working distribution | 
| 564 |  |  |  |  |  |  | #_______________________________________ | 
| 565 |  |  |  |  |  |  | sub updateDistro { | 
| 566 | 0 | 0 |  | 0 | 1 |  | my $self = shift; (@_ & 1) && croak("Odd number of parameters."); | 
|  | 0 |  |  |  |  |  |  | 
| 567 | 0 |  |  |  |  |  | my %opt  = @_; | 
| 568 | 0 |  | 0 |  |  |  | my $ecd       = $opt{ecd}       || croak("ecd => REQUIRED!"); | 
| 569 | 0 |  | 0 |  |  |  | my $parent_id = $opt{parent_id} || undef; | 
| 570 | 0 |  |  |  |  |  | my ($child, $node); | 
| 571 |  |  |  |  |  |  |  | 
| 572 | 0 | 0 |  |  |  |  | unless (defined($self->{distro})) { | 
| 573 | 0 |  |  |  |  |  | croak("Cannot add an ECD until a distribution to work on is selected."); | 
| 574 |  |  |  |  |  |  | } | 
| 575 |  |  |  |  |  |  |  | 
| 576 | 0 | 0 |  |  |  |  | if ($ecd->getDepth == 0) { | 
| 577 |  |  |  |  |  |  | # handle root nodes (root node identification could be more robust) | 
| 578 | 0 |  |  |  |  |  | $node = { }; | 
| 579 | 0 |  |  |  |  |  | $node->{node_id} = $self->{distro}{root_node_id}; | 
| 580 |  |  |  |  |  |  | } else { | 
| 581 |  |  |  |  |  |  | # all other nodes | 
| 582 | 0 |  |  |  |  |  | $node = $self->selectNode( | 
| 583 |  |  |  |  |  |  | name      => $ecd->name(), | 
| 584 |  |  |  |  |  |  | parent_id => $parent_id, | 
| 585 |  |  |  |  |  |  | ); | 
| 586 | 0 | 0 |  |  |  |  | if (defined($node)) { | 
| 587 | 0 |  |  |  |  |  | $node = $self->updateNode(ecd => $ecd, node_id => $node->{node_id}); | 
| 588 |  |  |  |  |  |  | } else { | 
| 589 | 0 |  |  |  |  |  | $node = $self->insertNode(ecd => $ecd, parent_id => $parent_id); | 
| 590 |  |  |  |  |  |  | }; | 
| 591 |  |  |  |  |  |  | } | 
| 592 |  |  |  |  |  |  |  | 
| 593 | 0 |  |  |  |  |  | foreach $child ($ecd->getChildren) { | 
| 594 | 0 |  |  |  |  |  | $self->updateDistro(ecd => $child, parent_id => $node->{node_id}); | 
| 595 |  |  |  |  |  |  | } | 
| 596 |  |  |  |  |  |  | } | 
| 597 |  |  |  |  |  |  |  | 
| 598 |  |  |  |  |  |  | # get node_id for a given path | 
| 599 |  |  |  |  |  |  | #_______________________________________ | 
| 600 |  |  |  |  |  |  | sub getIdForPath { | 
| 601 | 0 |  |  | 0 | 0 |  | my $self = shift; | 
| 602 | 0 |  |  |  |  |  | my $path = shift; | 
| 603 |  |  |  |  |  |  |  | 
| 604 |  |  |  |  |  |  | } | 
| 605 |  |  |  |  |  |  |  | 
| 606 |  |  |  |  |  |  | # return full path of a node | 
| 607 |  |  |  |  |  |  | #_______________________________________ | 
| 608 |  |  |  |  |  |  | sub getNodePath { | 
| 609 | 0 |  |  | 0 | 0 |  | my $self = shift; | 
| 610 | 0 |  |  |  |  |  | my $id   = shift; | 
| 611 | 0 |  |  |  |  |  | my $p    = $self->{path_cache}; | 
| 612 |  |  |  |  |  |  |  | 
| 613 | 0 |  |  |  |  |  | my $root_node_id = $self->{distro}{root_node_id}; | 
| 614 | 0 | 0 |  |  |  |  | if ($id == $root_node_id) { | 
| 615 | 0 |  |  |  |  |  | return '/'; | 
| 616 |  |  |  |  |  |  | } | 
| 617 | 0 |  |  |  |  |  | my $distro_id = $self->{distro}{distro_id}; | 
| 618 |  |  |  |  |  |  |  | 
| 619 | 0 | 0 |  |  |  |  | unless (defined $p->{$id}) { | 
| 620 | 0 |  |  |  |  |  | my $q = qq{ | 
| 621 |  |  |  |  |  |  | select n.node_id, n.node_name, np.parent_id | 
| 622 |  |  |  |  |  |  | from node n, | 
| 623 |  |  |  |  |  |  | node_parent np, | 
| 624 |  |  |  |  |  |  | node_distro nd | 
| 625 |  |  |  |  |  |  | where n.node_id        = np.node_id | 
| 626 |  |  |  |  |  |  | and n.node_id    = nd.node_id | 
| 627 |  |  |  |  |  |  | and nd.distro_id = $distro_id | 
| 628 |  |  |  |  |  |  | and n.node_id    = ? | 
| 629 |  |  |  |  |  |  | }; | 
| 630 | 0 |  |  |  |  |  | my $sth = $self->{dbh}->prepare($q); | 
| 631 | 0 |  |  |  |  |  | my $i   = $id; | 
| 632 | 0 |  |  |  |  |  | my @path; | 
| 633 |  |  |  |  |  |  | my $node; | 
| 634 | 0 |  |  |  |  |  | do { | 
| 635 | 0 |  |  |  |  |  | $sth->execute($i); | 
| 636 | 0 |  |  |  |  |  | $node = $sth->fetchrow_hashref; | 
| 637 | 0 |  |  |  |  |  | $i = $node->{parent_id}; | 
| 638 | 0 |  |  |  |  |  | unshift(@path, $node->{node_name}); | 
| 639 | 0 |  |  |  |  |  | $sth->finish; | 
| 640 |  |  |  |  |  |  | } while ($i != $root_node_id); | 
| 641 | 0 |  |  |  |  |  | $p->{$id} = '/' . join('/', @path); | 
| 642 |  |  |  |  |  |  | } | 
| 643 | 0 |  |  |  |  |  | return $p->{$id}; | 
| 644 |  |  |  |  |  |  | } | 
| 645 |  |  |  |  |  |  |  | 
| 646 |  |  |  |  |  |  | # return an arrayref of component names of the form | 
| 647 |  |  |  |  |  |  | # [ | 
| 648 |  |  |  |  |  |  | #   [ "category0", [ $node, ... ] ], | 
| 649 |  |  |  |  |  |  | #   [ "category1", [ $node, ... ] ], | 
| 650 |  |  |  |  |  |  | #   ... | 
| 651 |  |  |  |  |  |  | # ] | 
| 652 |  |  |  |  |  |  | # where $node is [ n.node_id, n.node_name ], and it's all SORTED -- yay! | 
| 653 |  |  |  |  |  |  | #_______________________________________ | 
| 654 |  |  |  |  |  |  | sub getComponentList { | 
| 655 | 0 |  |  | 0 | 1 |  | my $self = shift; | 
| 656 | 0 |  |  |  |  |  | my $dbh  = $self->{dbh}; | 
| 657 |  |  |  |  |  |  |  | 
| 658 | 0 |  |  |  |  |  | my $q = qq# | 
| 659 |  |  |  |  |  |  | select np.parent_id, n.node_id, n.node_name | 
| 660 |  |  |  |  |  |  | from node n, | 
| 661 |  |  |  |  |  |  | node_parent np, | 
| 662 |  |  |  |  |  |  | node_distro nd | 
| 663 |  |  |  |  |  |  | where n.node_id        = np.node_id | 
| 664 |  |  |  |  |  |  | and n.node_id    = nd.node_id | 
| 665 |  |  |  |  |  |  | and n.node_class = 'Component' | 
| 666 |  |  |  |  |  |  | and nd.distro_id = $self->{distro}{distro_id} | 
| 667 |  |  |  |  |  |  | #; | 
| 668 |  |  |  |  |  |  |  | 
| 669 |  |  |  |  |  |  | # get them all categorized | 
| 670 | 0 |  |  |  |  |  | my (%cat, $path, $comp, $list); | 
| 671 | 0 |  |  |  |  |  | $list = $dbh->selectall_arrayref($q); | 
| 672 | 0 |  |  |  |  |  | foreach $comp (@$list) { | 
| 673 | 0 |  |  |  |  |  | $path = $self->getNodePath($comp->[0]); | 
| 674 | 0 | 0 |  |  |  |  | if (defined $cat{$path}) { | 
| 675 | 0 |  |  |  |  |  | push(@{$cat{$path}}, [$comp->[1], $comp->[2]]); | 
|  | 0 |  |  |  |  |  |  | 
| 676 |  |  |  |  |  |  | } else { | 
| 677 | 0 |  |  |  |  |  | my $first   = [ [$comp->[1], $comp->[2]] ]; | 
| 678 | 0 |  |  |  |  |  | $cat{$path} = $first; | 
| 679 |  |  |  |  |  |  | } | 
| 680 |  |  |  |  |  |  | } | 
| 681 |  |  |  |  |  |  |  | 
| 682 |  |  |  |  |  |  | # sort each category | 
| 683 | 0 |  |  |  |  |  | my @cl; | 
| 684 | 0 |  |  |  |  |  | foreach (sort keys %cat) { | 
| 685 | 0 |  |  |  |  |  | $list = $cat{$_}; | 
| 686 | 0 |  |  |  |  |  | my $sorted_list = [ sort { $a->[1] cmp $b->[1] } @$list ]; | 
|  | 0 |  |  |  |  |  |  | 
| 687 | 0 |  |  |  |  |  | push @cl, [ $_, $sorted_list ]; | 
| 688 |  |  |  |  |  |  | } | 
| 689 | 0 |  |  |  |  |  | return \@cl; | 
| 690 |  |  |  |  |  |  | } | 
| 691 |  |  |  |  |  |  |  | 
| 692 |  |  |  |  |  |  | # | 
| 693 |  |  |  |  |  |  | #_______________________________________ | 
| 694 |  |  |  |  |  |  | sub getDistroList { | 
| 695 | 0 |  |  | 0 | 1 |  | my $self = shift; | 
| 696 | 0 |  |  |  |  |  | my $dbh  = $self->{dbh}; | 
| 697 | 0 |  |  |  |  |  | my $q    = qq/select distro_name, board, description from distro/; | 
| 698 | 0 |  |  |  |  |  | my $list = $dbh->selectall_arrayref($q); | 
| 699 |  |  |  |  |  |  |  | 
| 700 |  |  |  |  |  |  | # get them grouped by distribution | 
| 701 | 0 |  |  |  |  |  | my (%board_list, $distro, $cat); | 
| 702 | 0 |  |  |  |  |  | foreach $distro (@$list) { | 
| 703 | 0 |  | 0 |  |  |  | $cat = $board_list{$distro->{distro_name}} ||= [ ]; | 
| 704 | 0 |  |  |  |  |  | push @$cat, $distro; | 
| 705 |  |  |  |  |  |  | } | 
| 706 |  |  |  |  |  |  |  | 
| 707 |  |  |  |  |  |  | # sort | 
| 708 | 0 |  |  |  |  |  | my @dl; | 
| 709 | 0 |  |  |  |  |  | foreach (sort keys %board_list) { | 
| 710 | 0 |  |  |  |  |  | $list = $board_list{$_}; | 
| 711 | 0 |  |  |  |  |  | my $sorted_list = [ sort { $a->[0] cmp $b->[0] } @$list ]; | 
|  | 0 |  |  |  |  |  |  | 
| 712 | 0 |  |  |  |  |  | push @dl, [ $_, $sorted_list ]; | 
| 713 |  |  |  |  |  |  | } | 
| 714 | 0 |  |  |  |  |  | return \@dl; | 
| 715 |  |  |  |  |  |  | } | 
| 716 |  |  |  |  |  |  |  | 
| 717 |  |  |  |  |  |  | # need to do something clever here | 
| 718 |  |  |  |  |  |  | #_______________________________________ | 
| 719 |  |  |  |  |  |  | sub AUTOLOAD { | 
| 720 | 0 |  |  | 0 |  |  | croak('Help beppu@cpan.org think of a clever use for AUTOLOAD.'); | 
| 721 |  |  |  |  |  |  | } | 
| 722 |  |  |  |  |  |  |  | 
| 723 |  |  |  |  |  |  | 1; | 
| 724 |  |  |  |  |  |  |  | 
| 725 |  |  |  |  |  |  | __END__ |