Mercurial > pub > Impl
diff Lib/IMPL/SQL/Schema/Traits/Diff.pm @ 194:4d0e1962161c
Replaced tabs with spaces
IMPL::Web::View - fixed document model, new features (control classes, document constructor parameters)
author | cin |
---|---|
date | Tue, 10 Apr 2012 20:08:29 +0400 |
parents | d1676be8afcc |
children | 77df11605d3a |
line wrap: on
line diff
--- a/Lib/IMPL/SQL/Schema/Traits/Diff.pm Tue Apr 10 08:13:22 2012 +0400 +++ b/Lib/IMPL/SQL/Schema/Traits/Diff.pm Tue Apr 10 20:08:29 2012 +0400 @@ -7,159 +7,159 @@ use IMPL::SQL::Schema::Traits(); use constant { - schema_t => typeof IMPL::SQL::Schema # defining a constant is a good style to enable compile checks + schema_t => typeof IMPL::SQL::Schema # defining a constant is a good style to enable compile checks }; sub Diff { - my ($self,$src,$dst) = @_; - - die new IMPL::InvalidArgumentException( src => "A valid source schema is required") unless is($src,schema_t); - die new IMPL::InvalidArgumentException( dst => "A valid desctination schema is requried" ) unless is($src,schema_t); - - my %dstTables = map { $_->name, $_ } $dst->GetTables; - - my @operations; - - foreach my $srcTable ( $src->GetTables) { - my $dstTable = delete $dstTables{$srcTable->name}; - - if (not $dstTable) { - # if a source table doesn't have a corresponding destination table, it should be deleted - push @operations, new IMPL::SQL::Schema::Traits::DropTable($srcTable->name); - } else { - # a source table needs to be updated - push @operations, $self->_DiffTables($srcTable,$dstTable); - } - - } - - foreach my $tbl ( values %dstTables ) { - push @operations, new IMPL::SQL::Schema::Traits::CreateTable( - new IMPL::SQL::Schema::Traits::Table( - $tbl->name, - [ map _Column2Traits($_), @{$tbl->columns} ], - [ map _Constraint2Traits($_), $tbl->GetConstraints()], - $tbl->{tag} - ) - ) - } - - return \@operations; + my ($self,$src,$dst) = @_; + + die new IMPL::InvalidArgumentException( src => "A valid source schema is required") unless is($src,schema_t); + die new IMPL::InvalidArgumentException( dst => "A valid desctination schema is requried" ) unless is($src,schema_t); + + my %dstTables = map { $_->name, $_ } $dst->GetTables; + + my @operations; + + foreach my $srcTable ( $src->GetTables) { + my $dstTable = delete $dstTables{$srcTable->name}; + + if (not $dstTable) { + # if a source table doesn't have a corresponding destination table, it should be deleted + push @operations, new IMPL::SQL::Schema::Traits::DropTable($srcTable->name); + } else { + # a source table needs to be updated + push @operations, $self->_DiffTables($srcTable,$dstTable); + } + + } + + foreach my $tbl ( values %dstTables ) { + push @operations, new IMPL::SQL::Schema::Traits::CreateTable( + new IMPL::SQL::Schema::Traits::Table( + $tbl->name, + [ map _Column2Traits($_), @{$tbl->columns} ], + [ map _Constraint2Traits($_), $tbl->GetConstraints()], + $tbl->{tag} + ) + ) + } + + return \@operations; } sub _DiffTables { - my ($self,$src,$dst) = @_; - - my @dropConstraints; - my @createConstraints; - - my %srcConstraints = map { $_->name, $_ } $src->GetConstraints(); - my %dstConstraints = map { $_->name, $_ } $dst->GetConstraints(); - - foreach my $cnSrcName (keys %srcConstraints) { - if ( my $cnDst = delete $dstConstraints{$cnSrcName} ) { - unless ( $srcConstraints{$cnSrcName}->SameValue($cnDst) ) { - push @dropConstraints, - new IMPL::SQL::Schema::Traits::AlterTableDropConstraint( $src->name, $cnSrcName ); - push @createConstraints, - new IMPL::SQL::Schema::Traits::AlterTableAddConstraint( $dst->name, _Constraint2Traits($cnDst) ); - } - } else { - push @dropConstraints,new IMPL::SQL::Schema::Traits::AlterTableDropConstraint( $src->name, $cnSrcName ); - } - } - - foreach my $cnDst (values %dstConstraints) { - push @createConstraints, - IMPL::SQL::Schema::Traits::AlterTableAddConstraint->new( $dst->name, _Constraint2Traits($cnDst) ); - } - - my @deleteColumns; - my @addColumns; - my @updateColumns; - - my %dstColumnIndexes = map { - my $col = $dst->GetColumnAt($_); - ($col->name, { column => $col, index => $_ }) - } 0 .. $dst->ColumnsCount-1; - - my @columns; - - # remove old columns, mark for update changed columns - for( my $i=0; $i < $src->ColumnsCount; $i++) { - my $colSrc = $src->GetColumnAt($i); - - if ( my $infoDst = delete $dstColumnIndexes{$colSrc->name} ) { - $infoDst->{prevColumn} = $colSrc; - push @columns,$infoDst; - } else { - push @deleteColumns,new IMPL::SQL::Schema::Traits::AlterTableDropColumn($src->name,$colSrc->name); - } - } - - #insert new columns at specified positions - foreach ( sort { $a->{index} <=> $b->{index} } values %dstColumnIndexes ) { - splice(@columns,$_->{index},0,$_); - push @addColumns, new IMPL::SQL::Schema::Traits::AlterTableAddColumn($src->name, _Column2Traits( $_->{column}, position => $_->{index} )); - } - - # remember old indexes - for(my $i =0; $i< @columns; $i ++) { - $columns[$i]->{prevIndex} = $i; - } - - # reorder columns - @columns = sort { $a->{index} <=> $b->{index} } @columns; - - foreach my $info (@columns) { - if ($info->{prevColumn} && ( !$info->{column}->SameValue($info->{prevColumn}) or $info->{index}!= $info->{prevIndex} ) ) { - my $op = new IMPL::SQL::Schema::Traits::AlterTableChangeColumn($src->name,$info->{column}->name); + my ($self,$src,$dst) = @_; + + my @dropConstraints; + my @createConstraints; + + my %srcConstraints = map { $_->name, $_ } $src->GetConstraints(); + my %dstConstraints = map { $_->name, $_ } $dst->GetConstraints(); + + foreach my $cnSrcName (keys %srcConstraints) { + if ( my $cnDst = delete $dstConstraints{$cnSrcName} ) { + unless ( $srcConstraints{$cnSrcName}->SameValue($cnDst) ) { + push @dropConstraints, + new IMPL::SQL::Schema::Traits::AlterTableDropConstraint( $src->name, $cnSrcName ); + push @createConstraints, + new IMPL::SQL::Schema::Traits::AlterTableAddConstraint( $dst->name, _Constraint2Traits($cnDst) ); + } + } else { + push @dropConstraints,new IMPL::SQL::Schema::Traits::AlterTableDropConstraint( $src->name, $cnSrcName ); + } + } + + foreach my $cnDst (values %dstConstraints) { + push @createConstraints, + IMPL::SQL::Schema::Traits::AlterTableAddConstraint->new( $dst->name, _Constraint2Traits($cnDst) ); + } + + my @deleteColumns; + my @addColumns; + my @updateColumns; + + my %dstColumnIndexes = map { + my $col = $dst->GetColumnAt($_); + ($col->name, { column => $col, index => $_ }) + } 0 .. $dst->ColumnsCount-1; + + my @columns; + + # remove old columns, mark for update changed columns + for( my $i=0; $i < $src->ColumnsCount; $i++) { + my $colSrc = $src->GetColumnAt($i); + + if ( my $infoDst = delete $dstColumnIndexes{$colSrc->name} ) { + $infoDst->{prevColumn} = $colSrc; + push @columns,$infoDst; + } else { + push @deleteColumns,new IMPL::SQL::Schema::Traits::AlterTableDropColumn($src->name,$colSrc->name); + } + } + + #insert new columns at specified positions + foreach ( sort { $a->{index} <=> $b->{index} } values %dstColumnIndexes ) { + splice(@columns,$_->{index},0,$_); + push @addColumns, new IMPL::SQL::Schema::Traits::AlterTableAddColumn($src->name, _Column2Traits( $_->{column}, position => $_->{index} )); + } + + # remember old indexes + for(my $i =0; $i< @columns; $i ++) { + $columns[$i]->{prevIndex} = $i; + } + + # reorder columns + @columns = sort { $a->{index} <=> $b->{index} } @columns; + + foreach my $info (@columns) { + if ($info->{prevColumn} && ( !$info->{column}->SameValue($info->{prevColumn}) or $info->{index}!= $info->{prevIndex} ) ) { + my $op = new IMPL::SQL::Schema::Traits::AlterTableChangeColumn($src->name,$info->{column}->name); - $op->position( $info->{index} ) unless $info->{prevIndex} == $info->{index}; - $op->isNullable( $info->{column}->isNullable ) unless equals($info->{column}->isNullable,$info->{prevColumn}->isNullable); - $op->defaultValue( $info->{column}->defaultValue ) unless equals($info->{column}->defaultValue, $info->{prevColumn}->defaultValue); - - my $diff = hashDiff($info->{prevColumn}->tag,$info->{column}->tag); - $op->options($diff) if %$diff; - - push @updateColumns, $op; - } - } - - my @result = (@dropConstraints, @deleteColumns, @addColumns, @updateColumns, @createConstraints); - - return @result; + $op->position( $info->{index} ) unless $info->{prevIndex} == $info->{index}; + $op->isNullable( $info->{column}->isNullable ) unless equals($info->{column}->isNullable,$info->{prevColumn}->isNullable); + $op->defaultValue( $info->{column}->defaultValue ) unless equals($info->{column}->defaultValue, $info->{prevColumn}->defaultValue); + + my $diff = hashDiff($info->{prevColumn}->tag,$info->{column}->tag); + $op->options($diff) if %$diff; + + push @updateColumns, $op; + } + } + + my @result = (@dropConstraints, @deleteColumns, @addColumns, @updateColumns, @createConstraints); + + return @result; } sub _Column2Traits { - my ($column,%options) = @_; - - return new IMPL::SQL::Schema::Traits::Column( - $column->name, - $column->type, - isNullable => $column->isNullable, - defaultValue => $column->defaultValue, - tag => $column->tag, - %options - ); + my ($column,%options) = @_; + + return new IMPL::SQL::Schema::Traits::Column( + $column->name, + $column->type, + isNullable => $column->isNullable, + defaultValue => $column->defaultValue, + tag => $column->tag, + %options + ); } sub _Constraint2Traits { - my ($constraint) = @_; - - my $map = { - typeof IMPL::SQL::Schema::Constraint::ForeignKey , typeof IMPL::SQL::Schema::Traits::ForeignKey, - typeof IMPL::SQL::Schema::Constraint::PrimaryKey , typeof IMPL::SQL::Schema::Traits::PrimaryKey, - typeof IMPL::SQL::Schema::Constraint::Unique , typeof IMPL::SQL::Schema::Traits::Unique, - typeof IMPL::SQL::Schema::Constraint::Index , typeof IMPL::SQL::Schema::Traits::Index - }; - - my $class = $map->{$constraint->typeof} or die new IMPL::Exception("Can't map the constraint",$constraint->typeof); - - return $class->new( - $constraint->name, - [ map $_->name, $constraint->columns ] - ) + my ($constraint) = @_; + + my $map = { + typeof IMPL::SQL::Schema::Constraint::ForeignKey , typeof IMPL::SQL::Schema::Traits::ForeignKey, + typeof IMPL::SQL::Schema::Constraint::PrimaryKey , typeof IMPL::SQL::Schema::Traits::PrimaryKey, + typeof IMPL::SQL::Schema::Constraint::Unique , typeof IMPL::SQL::Schema::Traits::Unique, + typeof IMPL::SQL::Schema::Constraint::Index , typeof IMPL::SQL::Schema::Traits::Index + }; + + my $class = $map->{$constraint->typeof} or die new IMPL::Exception("Can't map the constraint",$constraint->typeof); + + return $class->new( + $constraint->name, + [ map $_->name, $constraint->columns ] + ) } 1;