Mercurial > pub > Impl
diff Lib/IMPL/SQL/Schema/Traits/Diff.pm @ 168:6148f89bb7bf
IMPL::SQL::Schema::Traits::Diff alfa version
IMPL::lang added hash traits
author | sourcer |
---|---|
date | Mon, 16 May 2011 04:30:38 +0400 |
parents | 1f7a6d762394 |
children | fd92830036c3 |
line wrap: on
line diff
--- a/Lib/IMPL/SQL/Schema/Traits/Diff.pm Thu May 12 08:57:19 2011 +0400 +++ b/Lib/IMPL/SQL/Schema/Traits/Diff.pm Mon May 16 04:30:38 2011 +0400 @@ -1,7 +1,7 @@ package IMPL::SQL::Schema::Traits::Diff; use strict; use warnings; -use IMPL::lang; +use IMPL::lang qw(:compare :hash is); use IMPL::SQL::Schema(); use IMPL::SQL::Schema::Traits(); @@ -25,24 +25,26 @@ 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() + 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->constraints], - $tbl->{tag} - ) + } + + 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 { @@ -58,12 +60,12 @@ if ( my $cnDst = delete $dstConstraints{$cnSrcName} ) { unless ( $srcConstraints{$cnSrcName}->SameValue($cnDst) ) { push @dropConstraints, - IMPL::SQL::Schema::Traits::AlterTableDropConstraint->new( $src->name, $cnSrcName ); + new IMPL::SQL::Schema::Traits::AlterTableDropConstraint( $src->name, $cnSrcName ); push @createConstraints, - IMPL::SQL::Schema::Traits::AlterTableAddConstraint->new( $dst->name, _Constraint2Traits($cnDst) ); + new IMPL::SQL::Schema::Traits::AlterTableAddConstraint( $dst->name, _Constraint2Traits($cnDst) ); } } else { - push @dropConstraints, IMPL::SQL::Schema::Traits::AlterTableDropConstrait->new( $src->name, $cnSrcName ); + push @dropConstraints,new IMPL::SQL::Schema::Traits::AlterTableDropConstrait( $src->name, $cnSrcName ); } } @@ -81,52 +83,82 @@ ($col->name, { column => $col, index => $_ }) } 0 .. $dst->ColumnsCount-1; - # get changed and - 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->{update} = 1 unless $infoDst->{column}->SameValue($colSrc); + $infoDst->{prevColumn} = $colSrc; push @columns,$infoDst; } else { - push @deleteColumns, IMPL::SQL::Schema::Traits::AlterTableDropColumn($src->name,$colSrc->name); + push @deleteColumns,new IMPL::SQL::Schema::Traits::AlterTableDropColumn($src->name,$colSrc->name); } } - splice(@columns,$_->{index},0,$_) foreach ( sort { $a->{index} <=> $b->{index} } values %dstColumnIndexes ); + #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; } - # determine constraints to be dropped, - # drop columns - # create columns - # update/reorder columns - # create constraints + # 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},$info->{column}); + $op->options(\%diff) if %diff; + + push @updateColumns, $op; + } + } + + my @result = (@dropConstraints, @deleteColumns, @addColumns, @updateColumns, @createConstraints); + + return @result; } sub _Column2Traits { - my ($column) = @_; + my ($column,%options) = @_; - return new IMPL::SQL::Schema::Traits::Columns( + return new IMPL::SQL::Schema::Traits::Column( $column->name, $column->type, - $column->isNullable, - $column->defaultValue, - $column->tag + isNullable => $column->isNullable, + defaultValue => $column->defaultValue, + tag => $column->tag, + %options ); } sub _Constraint2Traits { my ($constraint) = @_; - return new IMPL::SQL::Schema::Traits::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, $_->columns ] + [ map $_->name, $constraint->columns ] ) }