1*b1cdbd2cSJim Jagielski#************************************************************** 2*b1cdbd2cSJim Jagielski# 3*b1cdbd2cSJim Jagielski# Licensed to the Apache Software Foundation (ASF) under one 4*b1cdbd2cSJim Jagielski# or more contributor license agreements. See the NOTICE file 5*b1cdbd2cSJim Jagielski# distributed with this work for additional information 6*b1cdbd2cSJim Jagielski# regarding copyright ownership. The ASF licenses this file 7*b1cdbd2cSJim Jagielski# to you under the Apache License, Version 2.0 (the 8*b1cdbd2cSJim Jagielski# "License"); you may not use this file except in compliance 9*b1cdbd2cSJim Jagielski# with the License. You may obtain a copy of the License at 10*b1cdbd2cSJim Jagielski# 11*b1cdbd2cSJim Jagielski# http://www.apache.org/licenses/LICENSE-2.0 12*b1cdbd2cSJim Jagielski# 13*b1cdbd2cSJim Jagielski# Unless required by applicable law or agreed to in writing, 14*b1cdbd2cSJim Jagielski# software distributed under the License is distributed on an 15*b1cdbd2cSJim Jagielski# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*b1cdbd2cSJim Jagielski# KIND, either express or implied. See the License for the 17*b1cdbd2cSJim Jagielski# specific language governing permissions and limitations 18*b1cdbd2cSJim Jagielski# under the License. 19*b1cdbd2cSJim Jagielski# 20*b1cdbd2cSJim Jagielski#************************************************************** 21*b1cdbd2cSJim Jagielski 22*b1cdbd2cSJim Jagielskipackage installer::patch::MsiTable; 23*b1cdbd2cSJim Jagielski 24*b1cdbd2cSJim Jagielski=head1 NAME 25*b1cdbd2cSJim Jagielski 26*b1cdbd2cSJim Jagielski package installer::patch::MsiTable - Class that represents one table of an Msi file. 27*b1cdbd2cSJim Jagielski 28*b1cdbd2cSJim Jagielski=cut 29*b1cdbd2cSJim Jagielski 30*b1cdbd2cSJim Jagielskiuse installer::patch::MsiRow; 31*b1cdbd2cSJim Jagielski 32*b1cdbd2cSJim Jagielskiuse strict; 33*b1cdbd2cSJim Jagielski 34*b1cdbd2cSJim Jagielski=head new ($class, $filename, $table_name) 35*b1cdbd2cSJim Jagielski 36*b1cdbd2cSJim Jagielski Create a new MsiTable object from the output of a previous 37*b1cdbd2cSJim Jagielski msidb.exe run. The table is named $table_name, its data is read 38*b1cdbd2cSJim Jagielski from $filename. 39*b1cdbd2cSJim Jagielski 40*b1cdbd2cSJim Jagielski=cut 41*b1cdbd2cSJim Jagielskisub new ($$$) 42*b1cdbd2cSJim Jagielski{ 43*b1cdbd2cSJim Jagielski my ($class, $filename, $table_name) = @_; 44*b1cdbd2cSJim Jagielski 45*b1cdbd2cSJim Jagielski my $self = { 46*b1cdbd2cSJim Jagielski 'name' => $table_name, 47*b1cdbd2cSJim Jagielski 'filename' => $filename, 48*b1cdbd2cSJim Jagielski 'columns' => undef, 49*b1cdbd2cSJim Jagielski 'column_specs' => undef, 50*b1cdbd2cSJim Jagielski 'codepage' => undef, 51*b1cdbd2cSJim Jagielski 'is_valid' => 1, 52*b1cdbd2cSJim Jagielski 'is_modified' => 0 53*b1cdbd2cSJim Jagielski }; 54*b1cdbd2cSJim Jagielski bless($self, $class); 55*b1cdbd2cSJim Jagielski 56*b1cdbd2cSJim Jagielski if (defined $filename && -f $filename) 57*b1cdbd2cSJim Jagielski { 58*b1cdbd2cSJim Jagielski $self->ReadFile($filename); 59*b1cdbd2cSJim Jagielski } 60*b1cdbd2cSJim Jagielski return $self; 61*b1cdbd2cSJim Jagielski} 62*b1cdbd2cSJim Jagielski 63*b1cdbd2cSJim Jagielski 64*b1cdbd2cSJim Jagielski 65*b1cdbd2cSJim Jagielski 66*b1cdbd2cSJim Jagielskisub SetColumnData ($@) 67*b1cdbd2cSJim Jagielski{ 68*b1cdbd2cSJim Jagielski my ($self, @data) = @_; 69*b1cdbd2cSJim Jagielski 70*b1cdbd2cSJim Jagielski if (((scalar @data) % 2) != 0) 71*b1cdbd2cSJim Jagielski { 72*b1cdbd2cSJim Jagielski installer::logger::PrintError("column data has to have an even number of elements: (<column-name> <data-spec>)+)\n"); 73*b1cdbd2cSJim Jagielski $self->{'is_valid'} = 0; 74*b1cdbd2cSJim Jagielski return; 75*b1cdbd2cSJim Jagielski } 76*b1cdbd2cSJim Jagielski 77*b1cdbd2cSJim Jagielski $self->{'columns'} = []; 78*b1cdbd2cSJim Jagielski $self->{'column_specs'} = []; 79*b1cdbd2cSJim Jagielski while (scalar @data > 0) 80*b1cdbd2cSJim Jagielski { 81*b1cdbd2cSJim Jagielski my $name = shift @data; 82*b1cdbd2cSJim Jagielski my $spec = shift @data; 83*b1cdbd2cSJim Jagielski push @{$self->{'columns'}}, $name; 84*b1cdbd2cSJim Jagielski push @{$self->{'column_specs'}}, $spec; 85*b1cdbd2cSJim Jagielski } 86*b1cdbd2cSJim Jagielski} 87*b1cdbd2cSJim Jagielski 88*b1cdbd2cSJim Jagielski 89*b1cdbd2cSJim Jagielski 90*b1cdbd2cSJim Jagielski 91*b1cdbd2cSJim Jagielskisub SetIndexColumns ($@) 92*b1cdbd2cSJim Jagielski{ 93*b1cdbd2cSJim Jagielski my ($self, @index_columns) = @_; 94*b1cdbd2cSJim Jagielski 95*b1cdbd2cSJim Jagielski $self->{'index_columns'} = [@index_columns]; 96*b1cdbd2cSJim Jagielski} 97*b1cdbd2cSJim Jagielski 98*b1cdbd2cSJim Jagielski 99*b1cdbd2cSJim Jagielski 100*b1cdbd2cSJim Jagielski 101*b1cdbd2cSJim Jagielskisub SetCodepage ($$) 102*b1cdbd2cSJim Jagielski{ 103*b1cdbd2cSJim Jagielski my ($self, $codepage) = @_; 104*b1cdbd2cSJim Jagielski 105*b1cdbd2cSJim Jagielski $self->{'codepage'} = $codepage; 106*b1cdbd2cSJim Jagielski} 107*b1cdbd2cSJim Jagielski 108*b1cdbd2cSJim Jagielski 109*b1cdbd2cSJim Jagielski 110*b1cdbd2cSJim Jagielski 111*b1cdbd2cSJim Jagielskisub IsValid ($) 112*b1cdbd2cSJim Jagielski{ 113*b1cdbd2cSJim Jagielski my ($self) = @_; 114*b1cdbd2cSJim Jagielski return $self->{'is_valid'}; 115*b1cdbd2cSJim Jagielski} 116*b1cdbd2cSJim Jagielski 117*b1cdbd2cSJim Jagielski 118*b1cdbd2cSJim Jagielski 119*b1cdbd2cSJim Jagielski 120*b1cdbd2cSJim Jagielskisub Trim ($) 121*b1cdbd2cSJim Jagielski{ 122*b1cdbd2cSJim Jagielski my $line = shift; 123*b1cdbd2cSJim Jagielski 124*b1cdbd2cSJim Jagielski $line =~ s/(^\s+|\s+$)//g; 125*b1cdbd2cSJim Jagielski 126*b1cdbd2cSJim Jagielski return $line; 127*b1cdbd2cSJim Jagielski} 128*b1cdbd2cSJim Jagielski 129*b1cdbd2cSJim Jagielski 130*b1cdbd2cSJim Jagielski 131*b1cdbd2cSJim Jagielski=head2 ReadFile($self, $filename) 132*b1cdbd2cSJim Jagielski 133*b1cdbd2cSJim Jagielski Read the content of the table from the specified .idt file. 134*b1cdbd2cSJim Jagielski For each row a MsiRow object is appended to $self->{'rows'}. 135*b1cdbd2cSJim Jagielski 136*b1cdbd2cSJim Jagielski=cut 137*b1cdbd2cSJim Jagielskisub ReadFile ($$) 138*b1cdbd2cSJim Jagielski{ 139*b1cdbd2cSJim Jagielski my ($self, $filename) = @_; 140*b1cdbd2cSJim Jagielski 141*b1cdbd2cSJim Jagielski if ( ! (-f $filename && -r $filename)) 142*b1cdbd2cSJim Jagielski { 143*b1cdbd2cSJim Jagielski printf STDERR ("can not open idt file %s for reading\n", $filename); 144*b1cdbd2cSJim Jagielski $self->{'is_valid'} = 0; 145*b1cdbd2cSJim Jagielski return; 146*b1cdbd2cSJim Jagielski } 147*b1cdbd2cSJim Jagielski 148*b1cdbd2cSJim Jagielski open my $in, "<", $filename; 149*b1cdbd2cSJim Jagielski 150*b1cdbd2cSJim Jagielski my $columns = Trim(<$in>); 151*b1cdbd2cSJim Jagielski $self->{'columns'} = [split(/\t/, $columns)]; 152*b1cdbd2cSJim Jagielski 153*b1cdbd2cSJim Jagielski my $column_specs = Trim(<$in>); 154*b1cdbd2cSJim Jagielski $self->{'column_specs'} = [split(/\t/, $column_specs)]; 155*b1cdbd2cSJim Jagielski 156*b1cdbd2cSJim Jagielski # Table name, index columns. 157*b1cdbd2cSJim Jagielski my $line = Trim(<$in>); 158*b1cdbd2cSJim Jagielski my @items = split(/\t/, $line); 159*b1cdbd2cSJim Jagielski my $item_count = scalar @items; 160*b1cdbd2cSJim Jagielski if ($item_count>=1 && $items[0] eq $self->{'name'}) 161*b1cdbd2cSJim Jagielski { 162*b1cdbd2cSJim Jagielski # No codepage. 163*b1cdbd2cSJim Jagielski } 164*b1cdbd2cSJim Jagielski elsif ($item_count>=2 && $items[1] eq $self->{'name'}) 165*b1cdbd2cSJim Jagielski { 166*b1cdbd2cSJim Jagielski $self->{'codepage'} = shift @items; 167*b1cdbd2cSJim Jagielski } 168*b1cdbd2cSJim Jagielski else 169*b1cdbd2cSJim Jagielski { 170*b1cdbd2cSJim Jagielski printf STDERR ("reading wrong table data for table '%s' (got %s)\n", $self->{'name'}, $items[0]); 171*b1cdbd2cSJim Jagielski $self->{'is_valid'} = 0; 172*b1cdbd2cSJim Jagielski return; 173*b1cdbd2cSJim Jagielski } 174*b1cdbd2cSJim Jagielski shift @items; 175*b1cdbd2cSJim Jagielski $self->{'index_columns'} = [@items]; 176*b1cdbd2cSJim Jagielski $self->{'index_column_index'} = $self->GetColumnIndex($items[0]); 177*b1cdbd2cSJim Jagielski 178*b1cdbd2cSJim Jagielski my $rows = []; 179*b1cdbd2cSJim Jagielski while (<$in>) 180*b1cdbd2cSJim Jagielski { 181*b1cdbd2cSJim Jagielski # Remove all trailing returns and newlines. Keep trailing spaces and tabs. 182*b1cdbd2cSJim Jagielski s/[\r\n]+$//g; 183*b1cdbd2cSJim Jagielski 184*b1cdbd2cSJim Jagielski my @items = split(/\t/, $_); 185*b1cdbd2cSJim Jagielski push @$rows, new installer::patch::MsiRow($self, @items); 186*b1cdbd2cSJim Jagielski } 187*b1cdbd2cSJim Jagielski $self->{'rows'} = $rows; 188*b1cdbd2cSJim Jagielski 189*b1cdbd2cSJim Jagielski return $self; 190*b1cdbd2cSJim Jagielski} 191*b1cdbd2cSJim Jagielski 192*b1cdbd2cSJim Jagielski 193*b1cdbd2cSJim Jagielski 194*b1cdbd2cSJim Jagielski 195*b1cdbd2cSJim Jagielski=head WriteFile($self, $filename) 196*b1cdbd2cSJim Jagielski 197*b1cdbd2cSJim Jagielski Write a text file containing the current table content. 198*b1cdbd2cSJim Jagielski 199*b1cdbd2cSJim Jagielski=cut 200*b1cdbd2cSJim Jagielskisub WriteFile ($$) 201*b1cdbd2cSJim Jagielski{ 202*b1cdbd2cSJim Jagielski my ($self, $filename) = @_; 203*b1cdbd2cSJim Jagielski 204*b1cdbd2cSJim Jagielski open my $out, ">".$self->{'filename'}; 205*b1cdbd2cSJim Jagielski 206*b1cdbd2cSJim Jagielski print $out join("\t", @{$self->{'columns'}})."\r\n"; 207*b1cdbd2cSJim Jagielski print $out join("\t", @{$self->{'column_specs'}})."\r\n"; 208*b1cdbd2cSJim Jagielski if (defined $self->{'codepage'}) 209*b1cdbd2cSJim Jagielski { 210*b1cdbd2cSJim Jagielski print $out $self->{'codepage'} . "\t"; 211*b1cdbd2cSJim Jagielski } 212*b1cdbd2cSJim Jagielski print $out $self->{'name'} . "\t"; 213*b1cdbd2cSJim Jagielski print $out join("\t",@{$self->{'index_columns'}})."\r\n"; 214*b1cdbd2cSJim Jagielski 215*b1cdbd2cSJim Jagielski foreach my $row (@{$self->{'rows'}}) 216*b1cdbd2cSJim Jagielski { 217*b1cdbd2cSJim Jagielski print $out $row->Format("\t")."\r\n"; 218*b1cdbd2cSJim Jagielski } 219*b1cdbd2cSJim Jagielski 220*b1cdbd2cSJim Jagielski close $out; 221*b1cdbd2cSJim Jagielski} 222*b1cdbd2cSJim Jagielski 223*b1cdbd2cSJim Jagielski 224*b1cdbd2cSJim Jagielski 225*b1cdbd2cSJim Jagielski 226*b1cdbd2cSJim Jagielskisub UpdateTimestamp ($) 227*b1cdbd2cSJim Jagielski{ 228*b1cdbd2cSJim Jagielski my $self = shift; 229*b1cdbd2cSJim Jagielski 230*b1cdbd2cSJim Jagielski utime(undef,undef, $self->{'filename'}); 231*b1cdbd2cSJim Jagielski} 232*b1cdbd2cSJim Jagielski 233*b1cdbd2cSJim Jagielski 234*b1cdbd2cSJim Jagielski 235*b1cdbd2cSJim Jagielski 236*b1cdbd2cSJim Jagielskisub GetName ($) 237*b1cdbd2cSJim Jagielski{ 238*b1cdbd2cSJim Jagielski my $self = shift; 239*b1cdbd2cSJim Jagielski 240*b1cdbd2cSJim Jagielski return $self->{'name'}; 241*b1cdbd2cSJim Jagielski} 242*b1cdbd2cSJim Jagielski 243*b1cdbd2cSJim Jagielski 244*b1cdbd2cSJim Jagielski 245*b1cdbd2cSJim Jagielski 246*b1cdbd2cSJim Jagielski=head2 GetColumnCount($self) 247*b1cdbd2cSJim Jagielski 248*b1cdbd2cSJim Jagielski Return the number of columns in the table. 249*b1cdbd2cSJim Jagielski 250*b1cdbd2cSJim Jagielski=cut 251*b1cdbd2cSJim Jagielskisub GetColumnCount ($) 252*b1cdbd2cSJim Jagielski{ 253*b1cdbd2cSJim Jagielski my ($self) = @_; 254*b1cdbd2cSJim Jagielski 255*b1cdbd2cSJim Jagielski return scalar @{$self->{'columns'}}; 256*b1cdbd2cSJim Jagielski} 257*b1cdbd2cSJim Jagielski 258*b1cdbd2cSJim Jagielski 259*b1cdbd2cSJim Jagielski 260*b1cdbd2cSJim Jagielski 261*b1cdbd2cSJim Jagielski=head2 GetRowCount($self) 262*b1cdbd2cSJim Jagielski 263*b1cdbd2cSJim Jagielski Return the number of rows in the table. 264*b1cdbd2cSJim Jagielski 265*b1cdbd2cSJim Jagielski=cut 266*b1cdbd2cSJim Jagielskisub GetRowCount ($) 267*b1cdbd2cSJim Jagielski{ 268*b1cdbd2cSJim Jagielski my ($self) = @_; 269*b1cdbd2cSJim Jagielski 270*b1cdbd2cSJim Jagielski return scalar @{$self->{'rows'}}; 271*b1cdbd2cSJim Jagielski} 272*b1cdbd2cSJim Jagielski 273*b1cdbd2cSJim Jagielski 274*b1cdbd2cSJim Jagielski 275*b1cdbd2cSJim Jagielski 276*b1cdbd2cSJim Jagielski=head2 GetColumnIndx($self, $column_name) 277*b1cdbd2cSJim Jagielski 278*b1cdbd2cSJim Jagielski Return the 0 based index of the column named $column_name. Use 279*b1cdbd2cSJim Jagielski this to speed up (slightly) access to column values when accessing 280*b1cdbd2cSJim Jagielski many or all rows of a table. 281*b1cdbd2cSJim Jagielski 282*b1cdbd2cSJim Jagielski=cut 283*b1cdbd2cSJim Jagielskisub GetColumnIndex ($$) 284*b1cdbd2cSJim Jagielski{ 285*b1cdbd2cSJim Jagielski my ($self, $column_name) = @_; 286*b1cdbd2cSJim Jagielski 287*b1cdbd2cSJim Jagielski my $index = 0; 288*b1cdbd2cSJim Jagielski foreach my $name (@{$self->{'columns'}}) 289*b1cdbd2cSJim Jagielski { 290*b1cdbd2cSJim Jagielski if ($name eq $column_name) 291*b1cdbd2cSJim Jagielski { 292*b1cdbd2cSJim Jagielski return $index; 293*b1cdbd2cSJim Jagielski } 294*b1cdbd2cSJim Jagielski ++$index; 295*b1cdbd2cSJim Jagielski } 296*b1cdbd2cSJim Jagielski 297*b1cdbd2cSJim Jagielski printf STDERR ("did not find column %s in %s\n", $column_name, join(" and ", @{$self->{'columns'}})); 298*b1cdbd2cSJim Jagielski return -1; 299*b1cdbd2cSJim Jagielski} 300*b1cdbd2cSJim Jagielski 301*b1cdbd2cSJim Jagielski 302*b1cdbd2cSJim Jagielski 303*b1cdbd2cSJim Jagielski=head2 GetRowIndex($self, $index_column_index, $index_column_value) 304*b1cdbd2cSJim Jagielski 305*b1cdbd2cSJim Jagielski Return the index, starting at 0, of the (first) row that has value $index_column_value 306*b1cdbd2cSJim Jagielski in column with index $index_column_index. 307*b1cdbd2cSJim Jagielski 308*b1cdbd2cSJim Jagielski Return -1 if now such row is found. 309*b1cdbd2cSJim Jagielski 310*b1cdbd2cSJim Jagielski=cut 311*b1cdbd2cSJim Jagielskisub GetRowIndex ($$$) 312*b1cdbd2cSJim Jagielski{ 313*b1cdbd2cSJim Jagielski my ($self, $index_column_index, $index_column_value) = @_; 314*b1cdbd2cSJim Jagielski 315*b1cdbd2cSJim Jagielski my $rows = $self->{'rows'}; 316*b1cdbd2cSJim Jagielski for (my ($row_index,$row_count)=(0,scalar @$rows); $row_index<$row_count; ++$row_index) 317*b1cdbd2cSJim Jagielski { 318*b1cdbd2cSJim Jagielski my $row = $rows->[$row_index]; 319*b1cdbd2cSJim Jagielski if ($row->GetValue($index_column_index) eq $index_column_value) 320*b1cdbd2cSJim Jagielski { 321*b1cdbd2cSJim Jagielski return $row_index; 322*b1cdbd2cSJim Jagielski } 323*b1cdbd2cSJim Jagielski } 324*b1cdbd2cSJim Jagielski 325*b1cdbd2cSJim Jagielski return -1; 326*b1cdbd2cSJim Jagielski} 327*b1cdbd2cSJim Jagielski 328*b1cdbd2cSJim Jagielski 329*b1cdbd2cSJim Jagielski 330*b1cdbd2cSJim Jagielski 331*b1cdbd2cSJim Jagielski=head2 GetValue($self, $selector_column, $selector_column_value, $value_column) 332*b1cdbd2cSJim Jagielski 333*b1cdbd2cSJim Jagielski Find the row in which the $selector_column has value 334*b1cdbd2cSJim Jagielski $selector_column_value and return its value in the $value_column. 335*b1cdbd2cSJim Jagielski 336*b1cdbd2cSJim Jagielski=cut 337*b1cdbd2cSJim Jagielski 338*b1cdbd2cSJim Jagielskisub GetValue ($$$$) 339*b1cdbd2cSJim Jagielski{ 340*b1cdbd2cSJim Jagielski my ($self, $selector_column, $selector_column_value, $value_column) = @_; 341*b1cdbd2cSJim Jagielski 342*b1cdbd2cSJim Jagielski my $row = $self->GetRow($selector_column, $selector_column_value); 343*b1cdbd2cSJim Jagielski if (defined $row) 344*b1cdbd2cSJim Jagielski { 345*b1cdbd2cSJim Jagielski return $row->GetValue($value_column); 346*b1cdbd2cSJim Jagielski } 347*b1cdbd2cSJim Jagielski else 348*b1cdbd2cSJim Jagielski { 349*b1cdbd2cSJim Jagielski return undef; 350*b1cdbd2cSJim Jagielski } 351*b1cdbd2cSJim Jagielski} 352*b1cdbd2cSJim Jagielski 353*b1cdbd2cSJim Jagielski 354*b1cdbd2cSJim Jagielski 355*b1cdbd2cSJim Jagielski 356*b1cdbd2cSJim Jagielski=head2 GetRow($self, $column, $value) 357*b1cdbd2cSJim Jagielski 358*b1cdbd2cSJim Jagielski Return the (first) row which has $value in $column. 359*b1cdbd2cSJim Jagielski 360*b1cdbd2cSJim Jagielski=cut 361*b1cdbd2cSJim Jagielskisub GetRow ($$$) 362*b1cdbd2cSJim Jagielski{ 363*b1cdbd2cSJim Jagielski my ($self, $column, $value) = @_; 364*b1cdbd2cSJim Jagielski 365*b1cdbd2cSJim Jagielski my $column_index = $self->GetColumnIndex($column); 366*b1cdbd2cSJim Jagielski if ($column_index<0) 367*b1cdbd2cSJim Jagielski { 368*b1cdbd2cSJim Jagielski printf STDERR "ERROR: unknown column $column in table $self->{'name'}\n"; 369*b1cdbd2cSJim Jagielski return undef; 370*b1cdbd2cSJim Jagielski } 371*b1cdbd2cSJim Jagielski 372*b1cdbd2cSJim Jagielski foreach my $row (@{$self->{'rows'}}) 373*b1cdbd2cSJim Jagielski { 374*b1cdbd2cSJim Jagielski if ($row->GetValue($column_index) eq $value) 375*b1cdbd2cSJim Jagielski { 376*b1cdbd2cSJim Jagielski return $row; 377*b1cdbd2cSJim Jagielski } 378*b1cdbd2cSJim Jagielski } 379*b1cdbd2cSJim Jagielski 380*b1cdbd2cSJim Jagielski printf STDERR ("ERROR: did not find row for %s->%s in %s\n", 381*b1cdbd2cSJim Jagielski $column, 382*b1cdbd2cSJim Jagielski $value, 383*b1cdbd2cSJim Jagielski table $self->{'name'}); 384*b1cdbd2cSJim Jagielski 385*b1cdbd2cSJim Jagielski return undef; 386*b1cdbd2cSJim Jagielski} 387*b1cdbd2cSJim Jagielski 388*b1cdbd2cSJim Jagielski 389*b1cdbd2cSJim Jagielski 390*b1cdbd2cSJim Jagielski 391*b1cdbd2cSJim Jagielski=head2 GetAllRows ($self) 392*b1cdbd2cSJim Jagielski 393*b1cdbd2cSJim Jagielski Return the reference to an array that contains all rows of the table. 394*b1cdbd2cSJim Jagielski 395*b1cdbd2cSJim Jagielski=cut 396*b1cdbd2cSJim Jagielski 397*b1cdbd2cSJim Jagielskisub GetAllRows ($) 398*b1cdbd2cSJim Jagielski{ 399*b1cdbd2cSJim Jagielski my $self = shift; 400*b1cdbd2cSJim Jagielski 401*b1cdbd2cSJim Jagielski return $self->{'rows'}; 402*b1cdbd2cSJim Jagielski} 403*b1cdbd2cSJim Jagielski 404*b1cdbd2cSJim Jagielski 405*b1cdbd2cSJim Jagielski 406*b1cdbd2cSJim Jagielski 407*b1cdbd2cSJim Jagielski=head2 SetRow($self, {$key, $value}*) 408*b1cdbd2cSJim Jagielski 409*b1cdbd2cSJim Jagielski Replace an existing row. If no matching row is found then add the row. 410*b1cdbd2cSJim Jagielski 411*b1cdbd2cSJim Jagielski The row is defined by a set of key/value pairs. Their order is defined by the keys (column names) 412*b1cdbd2cSJim Jagielski and their indices as defined in $self->{'columns'}. 413*b1cdbd2cSJim Jagielski 414*b1cdbd2cSJim Jagielski Rows are compared by their values of the index column. By default this is the first element of 415*b1cdbd2cSJim Jagielski $self->{'index_columns'} but is overruled by the last key that starts with a '*'. 416*b1cdbd2cSJim Jagielski 417*b1cdbd2cSJim Jagielski=cut 418*b1cdbd2cSJim Jagielskisub SetRow ($@) 419*b1cdbd2cSJim Jagielski{ 420*b1cdbd2cSJim Jagielski my $self = shift; 421*b1cdbd2cSJim Jagielski my @data = @_; 422*b1cdbd2cSJim Jagielski 423*b1cdbd2cSJim Jagielski my @items = (); 424*b1cdbd2cSJim Jagielski my $index_column = $self->{'index_columns'}->[0]; 425*b1cdbd2cSJim Jagielski 426*b1cdbd2cSJim Jagielski # Key/Value has to have an even number of entries. 427*b1cdbd2cSJim Jagielski MsiTools::Die("invalid arguments given to MsiTable::SetRow()\n") if (scalar @data%2) != 0; 428*b1cdbd2cSJim Jagielski 429*b1cdbd2cSJim Jagielski # Find column indices for column names. 430*b1cdbd2cSJim Jagielski while (scalar @data > 0) 431*b1cdbd2cSJim Jagielski { 432*b1cdbd2cSJim Jagielski my $column_name = shift @data; 433*b1cdbd2cSJim Jagielski if ($column_name =~ /^\*(.*)$/) 434*b1cdbd2cSJim Jagielski { 435*b1cdbd2cSJim Jagielski # Column name starts with a '*'. Use it as index column. 436*b1cdbd2cSJim Jagielski $column_name = $1; 437*b1cdbd2cSJim Jagielski $index_column = $1; 438*b1cdbd2cSJim Jagielski } 439*b1cdbd2cSJim Jagielski my $value = shift @data; 440*b1cdbd2cSJim Jagielski my $column_index = $self->GetColumnIndex($column_name); 441*b1cdbd2cSJim Jagielski $items[$column_index] = $value; 442*b1cdbd2cSJim Jagielski } 443*b1cdbd2cSJim Jagielski 444*b1cdbd2cSJim Jagielski my $index_column_index = $self->GetColumnIndex($index_column); 445*b1cdbd2cSJim Jagielski my $row_index = $self->GetRowIndex($index_column_index, $items[$index_column_index]); 446*b1cdbd2cSJim Jagielski 447*b1cdbd2cSJim Jagielski if ($row_index < 0) 448*b1cdbd2cSJim Jagielski { 449*b1cdbd2cSJim Jagielski # Row does not yet exist. Add it. 450*b1cdbd2cSJim Jagielski push @{$self->{'rows'}}, installer::patch::MsiRow->new($self, @items); 451*b1cdbd2cSJim Jagielski } 452*b1cdbd2cSJim Jagielski else 453*b1cdbd2cSJim Jagielski { 454*b1cdbd2cSJim Jagielski # Row does already exist. Replace it. 455*b1cdbd2cSJim Jagielski $self->{'rows'}->[$row_index] = installer::patch::MsiRow->new($self, @items); 456*b1cdbd2cSJim Jagielski } 457*b1cdbd2cSJim Jagielski 458*b1cdbd2cSJim Jagielski $self->MarkAsModified(); 459*b1cdbd2cSJim Jagielski} 460*b1cdbd2cSJim Jagielski 461*b1cdbd2cSJim Jagielski 462*b1cdbd2cSJim Jagielski 463*b1cdbd2cSJim Jagielski 464*b1cdbd2cSJim Jagielskisub MarkAsModified ($) 465*b1cdbd2cSJim Jagielski{ 466*b1cdbd2cSJim Jagielski my $self = shift; 467*b1cdbd2cSJim Jagielski 468*b1cdbd2cSJim Jagielski $self->{'is_modified'} = 1; 469*b1cdbd2cSJim Jagielski} 470*b1cdbd2cSJim Jagielski 471*b1cdbd2cSJim Jagielski 472*b1cdbd2cSJim Jagielski 473*b1cdbd2cSJim Jagielski 474*b1cdbd2cSJim Jagielskisub MarkAsUnmodified ($) 475*b1cdbd2cSJim Jagielski{ 476*b1cdbd2cSJim Jagielski my $self = shift; 477*b1cdbd2cSJim Jagielski 478*b1cdbd2cSJim Jagielski $self->{'is_modified'} = 0; 479*b1cdbd2cSJim Jagielski} 480*b1cdbd2cSJim Jagielski 481*b1cdbd2cSJim Jagielski 482*b1cdbd2cSJim Jagielski 483*b1cdbd2cSJim Jagielski 484*b1cdbd2cSJim Jagielskisub IsModified ($) 485*b1cdbd2cSJim Jagielski{ 486*b1cdbd2cSJim Jagielski my $self = shift; 487*b1cdbd2cSJim Jagielski 488*b1cdbd2cSJim Jagielski return $self->{'is_modified'}; 489*b1cdbd2cSJim Jagielski} 490*b1cdbd2cSJim Jagielski 491*b1cdbd2cSJim Jagielski 492*b1cdbd2cSJim Jagielski1; 493