Mercurial > pub > Impl
diff Lib/IMPL/SQL/Schema/Table.pm @ 165:76515373dac0
Added Class::Template,
Rewritten SQL::Schema
'use parent' directive instead of 'use base'
author | wizard |
---|---|
date | Sat, 23 Apr 2011 23:06:48 +0400 |
parents | 6ce1f052b90a |
children | 1f7a6d762394 |
line wrap: on
line diff
--- a/Lib/IMPL/SQL/Schema/Table.pm Mon Mar 28 01:36:24 2011 +0400 +++ b/Lib/IMPL/SQL/Schema/Table.pm Sat Apr 23 23:06:48 2011 +0400 @@ -1,42 +1,56 @@ use strict; package IMPL::SQL::Schema::Table; -use IMPL::SQL::Schema::Column; -use IMPL::SQL::Schema::Constraint; -use IMPL::SQL::Schema::Constraint::PrimaryKey; -use IMPL::SQL::Schema::Constraint::ForeignKey; +use IMPL::lang; -use base qw( +use parent qw( IMPL::Object IMPL::Object::Disposable - IMPL::Object::Clonable ); + +use IMPL::SQL::Schema::Column(); +use IMPL::SQL::Schema::Constraint(); +use IMPL::SQL::Schema::Constraint::PrimaryKey(); +use IMPL::SQL::Schema::Constraint::ForeignKey(); + use IMPL::Class::Property; use IMPL::Class::Property::Direct; BEGIN { - public _direct property Name => prop_get; - public _direct property Schema => prop_get; - public _direct property Columns => prop_get; - public _direct property Constraints => prop_get; - public _direct property ColumnsByName => prop_none; - public _direct property PrimaryKey => prop_get; - public _direct property Tag => prop_all; + public _direct property name => prop_get; + public _direct property schema => prop_get; + public _direct property columns => prop_get; + public _direct property constraints => prop_get; + public _direct property columnsByName => prop_none; + public _direct property primaryKey => prop_get; + public _direct property tag => prop_all; } sub CTOR { my ($this,%args) = @_; - $this->{$Name} = $args{'Name'} or die new IMPL::InvalidArgumentException('a table name is required'); - $this->{$Schema} = $args{'Schema'} or die new IMPL::InvalidArgumentException('a parent schema is required'); + $this->{$name} = $args{'name'} or die new IMPL::InvalidArgumentException('a table name is required'); + $this->{$schema} = $args{'schema'} or die new IMPL::InvalidArgumentException('a parent schema is required'); + + if ($args{columns}) { + die new IMPL::InvalidOperationException('A columns property should be a reference to an array') unless ref $args{columns} eq 'ARRAY'; + + $this->InsertColumn($_) foreach @{$args{columns}}; + } + + if ($args{constraints}) { + die new IMPL::InvalidOperationException('A constraints property should be a reference to an array') unless ref $args{constraints} eq 'ARRAY'; + + $this->AddConstraint($_) foreach @{$args{constraints}}; + } } sub InsertColumn { my ($this,$column,$index) = @_; - $index = ($this->{$Columns} ? scalar(@{$this->{$Columns}}) : 0) if not defined $index; + $index = ($this->{$columns} ? scalar(@{$this->{$columns}}) : 0) if not defined $index; - die new IMPL::InvalidArgumentException("The index is out of range") if ($index < 0 || $index > ($this->{$Columns} ? scalar(@{$this->{$Columns}}) : 0)); + die new IMPL::InvalidArgumentException("The index is out of range") if ($index < 0 || $index > ($this->{$columns} ? scalar(@{$this->{$columns}}) : 0)); if (UNIVERSAL::isa($column,'IMPL::SQL::Schema::Column')) { @@ -46,11 +60,11 @@ die new IMPL::InvalidArgumentException("The invalid column parameter"); } - if (exists $this->{$ColumnsByName}->{$column->Name}) { + if (exists $this->{$columnsByName}->{$column->name}) { die new IMPL::InvalidOperationException("The column already exists",$column->name); } else { - $this->{$ColumnsByName}->{$column->Name} = $column; - splice @{$this->{$Columns}},$index,0,$column; + $this->{$columnsByName}->{$column->name} = $column; + splice @{$this->{$columns}},$index,0,$column; } return $column; @@ -61,110 +75,129 @@ my $ColName; if (UNIVERSAL::isa($NameOrColumn,'IMPL::SQL::Schema::Column')) { - $ColName = $NameOrColumn->Name; + $ColName = $NameOrColumn->name; } elsif (not ref $NameOrColumn) { $ColName = $NameOrColumn; } - if (exists $this->{$ColumnsByName}->{$ColName}) { + if (exists $this->{$columnsByName}->{$ColName}) { my $index = 0; - foreach my $column(@{$this->{$Columns}}) { - last if $column->Name eq $ColName; + foreach my $column(@{$this->{$columns}}) { + last if $column->name eq $ColName; $index++; } - my $column = $this->{$Columns}[$index]; + my $column = $this->{$columns}[$index]; if (my @constraints = $this->GetColumnConstraints($column)){ $Force or die new IMPL::InvalidOperationException('Can\'t remove column which is used in the constraints',@constraints); $this->RemoveConstraint($_) foreach @constraints; } - my $removed = splice @{$this->{$Columns}},$index,1; - delete $this->{$ColumnsByName}->{$ColName}; + my $removed = splice @{$this->{$columns}},$index,1; + delete $this->{$columnsByName}->{$ColName}; return $removed; } else { - die new IMPL::InvalidOperationException("The column not found",$NameOrColumn->Name); + die new IMPL::InvalidOperationException("The column not found",$NameOrColumn->name); } } sub Column { my ($this,$name) = @_; - return $this->{$ColumnsByName}->{$name}; + return $this->{$columnsByName}->{$name}; } sub ColumnAt { my ($this,$index) = @_; - die new IMPL::InvalidArgumentException("The index is out of range") if $index < 0 || $index >= ($this->{$Columns} ? scalar(@{$this->{$Columns}}) : 0); + die new IMPL::InvalidArgumentException("The index is out of range") + if $index < 0 || $index >= ($this->{$columns} ? scalar(@{$this->{$columns}}) : 0); - return $this->{$Columns}[$index]; + return $this->{$columns}[$index]; +} + +sub ColumnsCount { + my ($this) = @_; + + return scalar(@{$this->{$columns}}); } sub AddConstraint { my ($this,$Constraint) = @_; - die new IMPL::InvalidArgumentException('The invalid parameter') if not UNIVERSAL::isa($Constraint,'IMPL::SQL::Schema::Constraint'); + if (ref $Constraint eq 'HASH') { + $Constraint = new IMPL::SQL::Schema::Constraint( %$Constraint, table => $this ); + } else { + die new IMPL::InvalidArgumentException('The invalid parameter') if not is($Constraint,typeof IMPL::SQL::Schema::Constraint); + } - $Constraint->Table == $this or die new IMPL::InvalidOperationException('The constaint must belong to the target table'); + $Constraint->table == $this or die new IMPL::InvalidOperationException('The constaint must belong to the target table'); - if (exists $this->{$Constraints}->{$Constraint->Name}) { - die new IMPL::InvalidOperationException('The table already has the specified constraint',$Constraint->Name); + if (exists $this->{$constraints}->{$Constraint->name}) { + die new IMPL::InvalidOperationException('The table already has the specified constraint',$Constraint->name); } else { if (UNIVERSAL::isa($Constraint,'IMPL::SQL::Schema::Constraint::PrimaryKey')) { - not $this->{$PrimaryKey} or die new IMPL::InvalidOperationException('The table already has a primary key'); - $this->{$PrimaryKey} = $Constraint; + not $this->{$primaryKey} or die new IMPL::InvalidOperationException('The table already has a primary key'); + $this->{$primaryKey} = $Constraint; } - $this->{$Constraints}->{$Constraint->Name} = $Constraint; + $this->{$constraints}->{$Constraint->name} = $Constraint; } } sub RemoveConstraint { my ($this,$Constraint,$Force) = @_; - my $cn = UNIVERSAL::isa($Constraint,'IMPL::SQL::Schema::Constraint') ? $Constraint->Name : $Constraint; - $Constraint = $this->{$Constraints}->{$cn} or die new IMPL::InvalidOperationException('The specified constraint doesn\'t exists',$cn); + my $cn = UNIVERSAL::isa($Constraint,'IMPL::SQL::Schema::Constraint') ? $Constraint->name : $Constraint; + $Constraint = $this->{$constraints}->{$cn} or die new IMPL::InvalidOperationException('The specified constraint doesn\'t exists',$cn); if (UNIVERSAL::isa($Constraint,'IMPL::SQL::Schema::Constraint::PrimaryKey')) { - not scalar keys %{$this->{$PrimaryKey}->ConnectedFK} or die new IMPL::InvalidOperationException('Can\'t remove Primary Key unless some foreign keys referenses it'); + not scalar keys %{$this->{$primaryKey}->ConnectedFK} or die new IMPL::InvalidOperationException('Can\'t remove Primary Key unless some foreign keys referenses it'); - delete $this->{$PrimaryKey}; + delete $this->{$primaryKey}; } $Constraint->Dispose; - delete $this->{$Constraints}->{$cn}; + delete $this->{$constraints}->{$cn}; return $cn; } +sub GetConstraint { + my ($this,$name) = @_; + + return $this->{$constraints}{$name}; +} + sub GetColumnConstraints { my ($this,@Columns) = @_; - my @cn = map { UNIVERSAL::isa($_ ,'IMPL::SQL::Schema::Column') ? $_ ->Name : $_ } @Columns; - exists $this->{$ColumnsByName}->{$_} or die new IMPL::InvalidOperationException('The specified column isn\'t found',$_) foreach @cn; + my @cn = map { UNIVERSAL::isa($_ ,'IMPL::SQL::Schema::Column') ? $_ ->name : $_ } @Columns; + exists $this->{$columnsByName}->{$_} or die new IMPL::InvalidOperationException('The specified column isn\'t found',$_) foreach @cn; - return grep {$_->HasColumn(@cn)} values %{$this->{$Constraints}}; + return grep {$_->HasColumn(@cn)} values %{$this->{$constraints}}; } sub SetPrimaryKey { my ($this,@ColumnList) = @_; - $this->AddConstraint(new IMPL::SQL::Schema::Constraint::PrimaryKey(Name => $this->{$Name}.'_PK', Table => $this,Columns => \@ColumnList)); + $this->AddConstraint(new IMPL::SQL::Schema::Constraint::PrimaryKey(name => $this->{$name}.'_PK', table => $this, columns => \@ColumnList)); } sub LinkTo { my ($this,$table,@ColumnList) = @_; - $table->PrimaryKey or die new IMPL::InvalidOperationException('The referenced table must have a primary key'); - my $constraintName = $this->{$Name}.'_'.$table->Name.'_FK_'.join('_',map {ref $_ ? $_->Name : $_} @ColumnList); - $this->AddConstraint(new IMPL::SQL::Schema::Constraint::ForeignKey(Name => $constraintName, Table => $this,Columns => \@ColumnList, ReferencedTable => $table, ReferencedColumns => $table->PrimaryKey->Columns)); + $table->primaryKey or die new IMPL::InvalidOperationException('The referenced table must have a primary key'); + my $constraintName = $this->{$name}.'_'.$table->name.'_FK_'.join('_',map {ref $_ ? $_->name : $_} @ColumnList); + $this->AddConstraint(new IMPL::SQL::Schema::Constraint::ForeignKey(name => $constraintName, table => $this, columns => \@ColumnList, referencedTable => $table, referencedColumns => $table->primaryKey->columns)); } sub Dispose { my ($this) = @_; - $_->Dispose() foreach values %{$this->{$Constraints}}; + $_->Dispose() foreach values %{$this->{$constraints}}; undef %{$this}; $this->SUPER::Dispose(); } 1; + +