Mercurial > pub > Impl
comparison Lib/Schema/DB/Table.pm @ 0:03e58a454b20
Создан репозитарий
| author | Sergey |
|---|---|
| date | Tue, 14 Jul 2009 12:54:37 +0400 |
| parents | |
| children | 16ada169ca75 |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:03e58a454b20 |
|---|---|
| 1 use strict; | |
| 2 package Schema::DB::Table; | |
| 3 use Carp; | |
| 4 use Common; | |
| 5 | |
| 6 use Schema::DB::Column; | |
| 7 use Schema::DB::Constraint; | |
| 8 use Schema::DB::Constraint::PrimaryKey; | |
| 9 use Schema::DB::Constraint::ForeignKey; | |
| 10 | |
| 11 our @ISA = qw(Object); | |
| 12 | |
| 13 srand time; | |
| 14 | |
| 15 BEGIN { | |
| 16 DeclareProperty Name => ACCESS_READ; | |
| 17 DeclareProperty Schema => ACCESS_READ; | |
| 18 DeclareProperty Columns => ACCESS_READ; | |
| 19 DeclareProperty Constraints => ACCESS_READ; | |
| 20 DeclareProperty ColumnsByName => ACCESS_NONE; | |
| 21 DeclareProperty PrimaryKey => ACCESS_READ; | |
| 22 DeclareProperty Tag => ACCESS_ALL; | |
| 23 } | |
| 24 | |
| 25 sub CTOR { | |
| 26 my ($this,%args) = @_; | |
| 27 | |
| 28 $this->{$Name} = $args{'Name'} or die new Exception('a table name is required'); | |
| 29 $this->{$Schema} = $args{'Schema'} or die new Exception('a parent schema is required'); | |
| 30 } | |
| 31 | |
| 32 sub InsertColumn { | |
| 33 my ($this,$column,$index) = @_; | |
| 34 | |
| 35 $index = ($this->{$Columns} ? scalar(@{$this->{$Columns}}) : 0) if not defined $index; | |
| 36 | |
| 37 die new Exception("Index is out of range") if ($index < 0 || $index > ($this->{$Columns} ? scalar(@{$this->{$Columns}}) : 0)); | |
| 38 | |
| 39 if (UNIVERSAL::isa($column,'Schema::DB::Column')) { | |
| 40 | |
| 41 } elsif (UNIVERSAL::isa($column,'HASH')) { | |
| 42 $column = new Schema::DB::Column(%{$column}); | |
| 43 } else { | |
| 44 die new Exception("The invalid parameter"); | |
| 45 } | |
| 46 | |
| 47 if (exists $this->{$ColumnsByName}->{$column->Name}) { | |
| 48 die new Exception("The column already exists",$column->name); | |
| 49 } else { | |
| 50 $this->{$ColumnsByName}->{$column->Name} = $column; | |
| 51 splice @{$this->{$Columns}},$index,0,$column; | |
| 52 } | |
| 53 | |
| 54 return $column; | |
| 55 } | |
| 56 | |
| 57 sub RemoveColumn { | |
| 58 my ($this,$NameOrColumn,$Force) = @_; | |
| 59 | |
| 60 my $ColName; | |
| 61 if (UNIVERSAL::isa($NameOrColumn,'Schema::DB::Column')) { | |
| 62 $ColName = $NameOrColumn->Name; | |
| 63 } elsif (not ref $NameOrColumn) { | |
| 64 $ColName = $NameOrColumn; | |
| 65 } | |
| 66 | |
| 67 if (exists $this->{$ColumnsByName}->{$ColName}) { | |
| 68 my $index = 0; | |
| 69 foreach my $column(@{$this->{$Columns}}) { | |
| 70 last if $column->Name eq $ColName; | |
| 71 $index++; | |
| 72 } | |
| 73 | |
| 74 my $column = $this->{$Columns}[$index]; | |
| 75 if (my @constraints = $this->GetColumnConstraints($column)){ | |
| 76 $Force or die new Exception('Can\'t remove column which is used in the constraints',@constraints); | |
| 77 $this->RemoveConstraint($_) foreach @constraints; | |
| 78 } | |
| 79 | |
| 80 my $removed = splice @{$this->{$Columns}},$index,1; | |
| 81 delete $this->{$ColumnsByName}->{$ColName}; | |
| 82 return $removed; | |
| 83 } else { | |
| 84 die new Exception("The column not found",$NameOrColumn->Name); | |
| 85 } | |
| 86 } | |
| 87 | |
| 88 sub Column { | |
| 89 my ($this,$name) = @_; | |
| 90 | |
| 91 return $this->{$ColumnsByName}->{$name}; | |
| 92 } | |
| 93 | |
| 94 sub ColumnAt { | |
| 95 my ($this,$index) = @_; | |
| 96 | |
| 97 die new Exception("The index is out of range") if $index < 0 || $index >= ($this->{$Columns} ? scalar(@{$this->{$Columns}}) : 0); | |
| 98 | |
| 99 return $this->{$Columns}[$index]; | |
| 100 } | |
| 101 | |
| 102 sub AddConstraint { | |
| 103 my ($this,$Constraint) = @_; | |
| 104 | |
| 105 die new Exception('The invalid parameter') if not UNIVERSAL::isa($Constraint,'Schema::DB::Constraint'); | |
| 106 | |
| 107 $Constraint->Table == $this or die new Exception('The constaint must belong to the target table'); | |
| 108 | |
| 109 if (exists $this->{$Constraints}->{$Constraint->Name}) { | |
| 110 die new Exception('The table already has the specified constraint',$Constraint->Name); | |
| 111 } else { | |
| 112 if (UNIVERSAL::isa($Constraint,'Schema::DB::Constraint::PrimaryKey')) { | |
| 113 not $this->{$PrimaryKey} or die new Exception('The table already has a primary key'); | |
| 114 $this->{$PrimaryKey} = $Constraint; | |
| 115 } | |
| 116 | |
| 117 $this->{$Constraints}->{$Constraint->Name} = $Constraint; | |
| 118 } | |
| 119 } | |
| 120 | |
| 121 sub RemoveConstraint { | |
| 122 my ($this,$Constraint,$Force) = @_; | |
| 123 | |
| 124 my $cn = UNIVERSAL::isa($Constraint,'Schema::DB::Constraint') ? $Constraint->Name : $Constraint; | |
| 125 $Constraint = $this->{$Constraints}->{$cn} or die new Exception('The specified constraint doesn\'t exists',$cn); | |
| 126 | |
| 127 if (UNIVERSAL::isa($Constraint,'Schema::DB::Constraint::PrimaryKey')) { | |
| 128 not scalar keys %{$this->{$PrimaryKey}->ConnectedFK} or die new Exception('Can\'t remove Primary Key unless some foreign keys referenses it'); | |
| 129 | |
| 130 delete $this->{$PrimaryKey}; | |
| 131 } | |
| 132 $Constraint->Dispose; | |
| 133 delete $this->{$Constraints}->{$cn}; | |
| 134 return $cn; | |
| 135 } | |
| 136 | |
| 137 sub GetColumnConstraints { | |
| 138 my ($this,@Columns) = @_; | |
| 139 | |
| 140 my @cn = map { UNIVERSAL::isa($_ ,'Schema::DB::Column') ? $_ ->Name : $_ } @Columns; | |
| 141 exists $this->{$ColumnsByName}->{$_} or die new Exception('The specified column isn\'t found',$_) foreach @cn; | |
| 142 | |
| 143 return grep {$_->HasColumn(@cn)} values %{$this->{$Constraints}}; | |
| 144 } | |
| 145 | |
| 146 sub SetPrimaryKey { | |
| 147 my ($this,@ColumnList) = @_; | |
| 148 | |
| 149 $this->AddConstraint(new Schema::DB::Constraint::PrimaryKey(Name => $this->{$Name}.'_PK', Table => $this,Columns => \@ColumnList)); | |
| 150 } | |
| 151 | |
| 152 sub LinkTo { | |
| 153 my ($this,$table,@ColumnList) = @_; | |
| 154 $table->PrimaryKey or die new Exception('The referenced table must have a primary key'); | |
| 155 my $constraintName = $this->{$Name}.'_'.$table->Name.'_FK_'.join('_',map {ref $_ ? $_->Name : $_} @ColumnList); | |
| 156 $this->AddConstraint(new Schema::DB::Constraint::ForeignKey(Name => $constraintName, Table => $this,Columns => \@ColumnList, ReferencedTable => $table, ReferencedColumns => scalar($table->PrimaryKey->Columns))); | |
| 157 } | |
| 158 | |
| 159 sub Dispose { | |
| 160 my ($this) = @_; | |
| 161 | |
| 162 $_->Dispose() foreach values %{$this->{$Constraints}}; | |
| 163 | |
| 164 undef %{$this}; | |
| 165 $this->SUPER::Dispose(); | |
| 166 } | |
| 167 | |
| 168 1; |
