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