Mercurial > pub > Impl
diff lib/IMPL/SQL/Schema/MySQL/Processor.pm @ 407:c6e90e02dd17 ref20150831
renamed Lib->lib
author | cin |
---|---|
date | Fri, 04 Sep 2015 19:40:23 +0300 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/IMPL/SQL/Schema/MySQL/Processor.pm Fri Sep 04 19:40:23 2015 +0300 @@ -0,0 +1,150 @@ +package IMPL::SQL::Schema::MySQL::Processor; +use strict; + +use mro; +use IMPL::Const qw(:prop); +use IMPL::declare { + require => { + MySQLFormatter => 'IMPL::SQL::Schema::MySQL::Formatter', + AlterTableDropConstraint => '-IMPL::SQL::Schema::Traits::AlterTableDropConstraint', + AlterTableAddConstraint => '-IMPL::SQL::Schema::Traits::AlterTableAddConstraint', + DropTable => '-IMPL::SQL::Schema::Traits::DropTable', + PrimitiveDropTable => '-IMPL::SQL::Schema::MySQL::Processor::PrimitiveDropTable', + CreateTable => '-IMPL::SQL::Schema::Traits::CreateTable', + Table => '-IMPL::SQL::Schema::Traits::Table', + ForeignKey => '-IMPL::SQL::Schema::Traits::ForeignKey', + + }, + base => [ + 'IMPL::SQL::Schema::Processor' => sub { $_[0] } + ], + props => [ + formatter => PROP_RO, + sqlBatch => PROP_RO + ] +}; +use IMPL::lang qw(is); + +sub CTOR { + my ( $this, $schema, %opts ) = @_; + + $this->formatter( $opts{formatter} || MySQLFormatter ); + $this->sqlBatch([]); +} + +sub AddSqlBatch { + my $this = shift; + + push @{$this->sqlBatch}, @_; +} + +sub ApplyOperation { + my ($this, $op, $iteration ) = @_; + + my @formatterParams; + + if ( is( $op, AlterTableDropConstraint ) ) { + my $constraint = $this + ->dbSchema + ->GetTable($op->tableName) + ->GetConstraint($op->constraintName); + + push @formatterParams, ref $constraint; + } else { + push @formatterParams, $this->dbSchema; + } + + if ( is( $op, CreateTable ) ) { + my @constraints; + my @fk; + my $table = $op->table; + + # отделяем создание внешних ключей от таблиц + + foreach my $c (@{$table->{constraints} || []}) { + if ( is($c,ForeignKey)) { + push @fk,$c; + } else { + push @constraints, $c; + } + } + + if (@fk) { + $op = CreateTable->new( + Table->new( + $table->{name}, + $table->{columns}, + \@constraints, + $table->{options} + ) + ); + + $this->AddPendingOperations( + map AlterTableAddConstraint->new($table->{name},$_), @fk + ); + } + } + + if (is($op, DropTable)) { + my $table = $this->dbSchema->GetTable($op->tableName); + + if(my $pk = $table->primaryKey) { + $this->ApplyOperation($_,$iteration) + foreach + map + AlterTableDropConstraint->new($_->table->name,$_->name), + values %{$pk->connectedFK || {}}; + } + } + + $this->next::method($op,$iteration); + + $this->AddSqlBatch( + $this->formatter->Format($op,@formatterParams) + ); +} + +package IMPL::SQL::Schema::MySQL::Processor::PrimitiveDropTable; +use IMPL::Const qw(:prop); +use IMPL::declare { + require => { + ArgException => '-IMPL::InvalidArgumentException' + }, + base => [ + 'IMPL::Object' => undef + ], + props => [ + tableName => PROP_RO, + ] +}; + +sub CTOR { + my ($this,$tableName) = @_; + + $this->tableName($tableName) or die ArgException->new("tableName is required"); +} + +sub CanApply { + my ($this,$schema) = @_; + + my $table = $schema->GetTable( $this->tableName ) + or return 0; + + my $pk = $table->primaryKey + or return 1; + + my $canDrop = keys(%{$pk->connectedFK || {}}) ? 0 : 1; + + warn "Can drop ", $this->tableName + if $canDrop; + + return $canDrop; +} + +sub Apply { + my ($this,$schema) = @_; + + $schema->RemoveTable($this->tableName); +} + +1;