annotate 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
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
165
76515373dac0 Added Class::Template,
wizard
parents:
diff changeset
1 package IMPL::SQL::Schema::Traits::Diff;
76515373dac0 Added Class::Template,
wizard
parents:
diff changeset
2 use strict;
76515373dac0 Added Class::Template,
wizard
parents:
diff changeset
3 use warnings;
168
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
4 use IMPL::lang qw(:compare :hash is);
165
76515373dac0 Added Class::Template,
wizard
parents:
diff changeset
5
76515373dac0 Added Class::Template,
wizard
parents:
diff changeset
6 use IMPL::SQL::Schema();
76515373dac0 Added Class::Template,
wizard
parents:
diff changeset
7 use IMPL::SQL::Schema::Traits();
76515373dac0 Added Class::Template,
wizard
parents:
diff changeset
8
76515373dac0 Added Class::Template,
wizard
parents:
diff changeset
9 use constant {
76515373dac0 Added Class::Template,
wizard
parents:
diff changeset
10 schema_t => typeof IMPL::SQL::Schema # defining a constant is a good style to enable compile checks
76515373dac0 Added Class::Template,
wizard
parents:
diff changeset
11 };
76515373dac0 Added Class::Template,
wizard
parents:
diff changeset
12
76515373dac0 Added Class::Template,
wizard
parents:
diff changeset
13 sub Diff {
76515373dac0 Added Class::Template,
wizard
parents:
diff changeset
14 my ($self,$src,$dst) = @_;
76515373dac0 Added Class::Template,
wizard
parents:
diff changeset
15
76515373dac0 Added Class::Template,
wizard
parents:
diff changeset
16 die new IMPL::InvalidArgumentException( src => "A valid source schema is required") unless is($src,schema_t);
76515373dac0 Added Class::Template,
wizard
parents:
diff changeset
17 die new IMPL::InvalidArgumentException( dst => "A valid desctination schema is requried" ) unless is($src,schema_t);
76515373dac0 Added Class::Template,
wizard
parents:
diff changeset
18
76515373dac0 Added Class::Template,
wizard
parents:
diff changeset
19 my %dstTables = map { $_->name, $_ } $dst->GetTables;
76515373dac0 Added Class::Template,
wizard
parents:
diff changeset
20
76515373dac0 Added Class::Template,
wizard
parents:
diff changeset
21 my @operations;
76515373dac0 Added Class::Template,
wizard
parents:
diff changeset
22
76515373dac0 Added Class::Template,
wizard
parents:
diff changeset
23 foreach my $srcTable ( $src->GetTables) {
76515373dac0 Added Class::Template,
wizard
parents:
diff changeset
24 my $dstTable = delete $dstTables{$srcTable->name};
76515373dac0 Added Class::Template,
wizard
parents:
diff changeset
25
76515373dac0 Added Class::Template,
wizard
parents:
diff changeset
26 if (not $dstTable) {
167
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
27 # if a source table doesn't have a corresponding destination table, it should be deleted
168
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
28 push @operations, new IMPL::SQL::Schema::Traits::DropTable($srcTable->name);
165
76515373dac0 Added Class::Template,
wizard
parents:
diff changeset
29 } else {
167
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
30 # a source table needs to be updated
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
31 push @operations, $self->_DiffTables($srcTable,$dstTable);
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
32 }
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
33
168
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
34 }
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
35
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
36 foreach my $tbl ( values %dstTables ) {
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
37 push @operations, new IMPL::SQL::Schema::Traits::CreateTable(
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
38 new IMPL::SQL::Schema::Traits::Table(
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
39 $tbl->name,
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
40 [ map _Column2Traits($_), @{$tbl->columns} ],
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
41 [ map _Constraint2Traits($_), $tbl->GetConstraints()],
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
42 $tbl->{tag}
167
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
43 )
168
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
44 )
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
45 }
165
76515373dac0 Added Class::Template,
wizard
parents:
diff changeset
46
168
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
47 return \@operations;
165
76515373dac0 Added Class::Template,
wizard
parents:
diff changeset
48 }
76515373dac0 Added Class::Template,
wizard
parents:
diff changeset
49
167
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
50 sub _DiffTables {
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
51 my ($self,$src,$dst) = @_;
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
52
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
53 my @dropConstraints;
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
54 my @createConstraints;
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
55
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
56 my %srcConstraints = map { $_->name, $_ } $src->GetConstraints();
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
57 my %dstConstraints = map { $_->name, $_ } $dst->GetConstraints();
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
58
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
59 foreach my $cnSrcName (keys %srcConstraints) {
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
60 if ( my $cnDst = delete $dstConstraints{$cnSrcName} ) {
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
61 unless ( $srcConstraints{$cnSrcName}->SameValue($cnDst) ) {
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
62 push @dropConstraints,
168
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
63 new IMPL::SQL::Schema::Traits::AlterTableDropConstraint( $src->name, $cnSrcName );
167
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
64 push @createConstraints,
168
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
65 new IMPL::SQL::Schema::Traits::AlterTableAddConstraint( $dst->name, _Constraint2Traits($cnDst) );
167
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
66 }
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
67 } else {
168
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
68 push @dropConstraints,new IMPL::SQL::Schema::Traits::AlterTableDropConstrait( $src->name, $cnSrcName );
167
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
69 }
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
70 }
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
71
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
72 foreach my $cnDst (values %dstConstraints) {
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
73 push @createConstraints,
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
74 IMPL::SQL::Schema::Traits::AlterTableAddConstraint->new( $dst->name, _Constraint2Traits($cnDst) );
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
75 }
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
76
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
77 my @deleteColumns;
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
78 my @addColumns;
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
79 my @updateColumns;
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
80
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
81 my %dstColumnIndexes = map {
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
82 my $col = $dst->GetColumnAt($_);
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
83 ($col->name, { column => $col, index => $_ })
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
84 } 0 .. $dst->ColumnsCount-1;
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
85
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
86 my @columns;
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
87
168
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
88 # remove old columns, mark for update changed columns
167
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
89 for( my $i=0; $i < $src->ColumnsCount; $i++) {
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
90 my $colSrc = $src->GetColumnAt($i);
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
91
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
92 if ( my $infoDst = delete $dstColumnIndexes{$colSrc->name} ) {
168
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
93 $infoDst->{prevColumn} = $colSrc;
167
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
94 push @columns,$infoDst;
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
95 } else {
168
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
96 push @deleteColumns,new IMPL::SQL::Schema::Traits::AlterTableDropColumn($src->name,$colSrc->name);
167
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
97 }
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
98 }
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
99
168
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
100 #insert new columns at specified positions
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
101 foreach ( sort { $a->{index} <=> $b->{index} } values %dstColumnIndexes ) {
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
102 splice(@columns,$_->{index},0,$_);
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
103 push @addColumns, new IMPL::SQL::Schema::Traits::AlterTableAddColumn($src->name, _Column2Traits( $_->{column}, position => $_->{index} ));
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
104 }
167
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
105
168
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
106 # remember old indexes
167
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
107 for(my $i =0; $i< @columns; $i ++) {
168
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
108 $columns[$i]->{prevIndex} = $i;
167
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
109 }
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
110
168
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
111 # reorder columns
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
112 @columns = sort { $a->{index} <=> $b->{index} } @columns;
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
113
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
114 foreach my $info (@columns) {
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
115 if ($info->{prevColumn} && ( !$info->{column}->SameValue($info->{prevColumn}) or $info->{index}!= $info->{prevIndex} ) ) {
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
116 my $op = new IMPL::SQL::Schema::Traits::AlterTableChangeColumn($src->name,$info->{column}->name);
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
117
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
118 $op->position( $info->{index} ) unless $info->{prevIndex} == $info->{index};
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
119 $op->isNullable( $info->{column}->isNullable ) unless equals($info->{column}->isNullable,$info->{prevColumn}->isNullable);
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
120 $op->defaultValue( $info->{column}->defaultValue ) unless equals($info->{column}->defaultValue, $info->{prevColumn}->defaultValue);
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
121
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
122 my %diff = hashDiff($info->{prevColumn},$info->{column});
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
123 $op->options(\%diff) if %diff;
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
124
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
125 push @updateColumns, $op;
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
126 }
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
127 }
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
128
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
129 my @result = (@dropConstraints, @deleteColumns, @addColumns, @updateColumns, @createConstraints);
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
130
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
131 return @result;
167
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
132 }
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
133
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
134 sub _Column2Traits {
168
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
135 my ($column,%options) = @_;
167
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
136
168
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
137 return new IMPL::SQL::Schema::Traits::Column(
167
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
138 $column->name,
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
139 $column->type,
168
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
140 isNullable => $column->isNullable,
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
141 defaultValue => $column->defaultValue,
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
142 tag => $column->tag,
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
143 %options
167
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
144 );
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
145 }
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
146
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
147 sub _Constraint2Traits {
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
148 my ($constraint) = @_;
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
149
168
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
150 my $map = {
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
151 typeof IMPL::SQL::Schema::Constraint::ForeignKey , typeof IMPL::SQL::Schema::Traits::ForeignKey,
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
152 typeof IMPL::SQL::Schema::Constraint::PrimaryKey , typeof IMPL::SQL::Schema::Traits::PrimaryKey,
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
153 typeof IMPL::SQL::Schema::Constraint::Unique , typeof IMPL::SQL::Schema::Traits::Unique,
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
154 typeof IMPL::SQL::Schema::Constraint::Index , typeof IMPL::SQL::Schema::Traits::Index
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
155 };
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
156
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
157 my $class = $map->{$constraint->typeof} or die new IMPL::Exception("Can't map the constraint",$constraint->typeof);
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
158
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
159 return $class->new(
167
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
160 $constraint->name,
168
6148f89bb7bf IMPL::SQL::Schema::Traits::Diff alfa version
sourcer
parents: 167
diff changeset
161 [ map $_->name, $constraint->columns ]
167
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
162 )
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
163 }
1f7a6d762394 SQL schema in progress
sourcer
parents: 165
diff changeset
164
165
76515373dac0 Added Class::Template,
wizard
parents:
diff changeset
165 1;