view Lib/IMPL/SQL/Schema/MySQL/Processor.pm @ 279:af8af4b8337e

sync
author sergey
date Mon, 04 Feb 2013 17:16:45 +0400
parents 56364d0c4b4f
children 2f06250bab5f
line wrap: on
line source

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',
        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
            );
        }
    }
    
    $this->next::method($op,$iteration);
    
    $this->AddSqlBatch(
        $this->formatter->Format($op,@formatterParams)
    );
}

1;