Mercurial > pub > Impl
comparison Lib/IMPL/SQL/Schema.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 | eb3e9861a761 |
| children | 1f7a6d762394 |
comparison
equal
deleted
inserted
replaced
| 164:eb3e9861a761 | 165:76515373dac0 |
|---|---|
| 1 use strict; | 1 use strict; |
| 2 package IMPL::SQL::Schema; | 2 package IMPL::SQL::Schema; |
| 3 | 3 |
| 4 use base qw( | 4 use IMPL::_core::version; |
| 5 use IMPL::lang; | |
| 6 use parent qw( | |
| 5 IMPL::Object | 7 IMPL::Object |
| 6 IMPL::Object::Disposable | 8 IMPL::Object::Disposable |
| 7 IMPL::Object::Autofill | 9 IMPL::Object::Autofill |
| 8 IMPL::Object::Clonable | 10 IMPL::Object::Clonable |
| 9 ); | 11 ); |
| 12 | |
| 10 use IMPL::Class::Property; | 13 use IMPL::Class::Property; |
| 11 use IMPL::Class::Property::Direct; | 14 use IMPL::Class::Property::Direct; |
| 12 | 15 |
| 13 require IMPL::SQL::Schema::Table; | 16 require IMPL::SQL::Schema::Table; |
| 14 | 17 |
| 15 __PACKAGE__->PassThroughArgs; | 18 __PACKAGE__->PassThroughArgs; |
| 16 | 19 |
| 17 BEGIN { | 20 BEGIN { |
| 18 public _direct property Version => prop_get; | 21 public _direct property version => prop_get; |
| 19 public _direct property Name => prop_get; | 22 public _direct property name => prop_get; |
| 20 public _direct property Tables => prop_get; | 23 private _direct property tables => prop_get; |
| 21 } | 24 } |
| 22 | 25 |
| 23 sub AddTable { | 26 sub AddTable { |
| 24 my ($this,$table) = @_; | 27 my ($this,$table) = @_; |
| 25 | 28 |
| 26 if (UNIVERSAL::isa($table,'IMPL::SQL::Schema::Table')) { | 29 if (UNIVERSAL::isa($table,'IMPL::SQL::Schema::Table')) { |
| 30 | |
| 27 $table->Schema == $this or die new IMPL::InvalidOperationException('The specified table must belong to the database'); | 31 $table->Schema == $this or die new IMPL::InvalidOperationException('The specified table must belong to the database'); |
| 28 not exists $this->{$Tables}->{$table->Name} or die new IMPL::InvalidOperationException('a table with the same name already exists in the database'); | 32 not exists $this->{$tables}->{$table->name} or die new IMPL::InvalidOperationException('a table with the same name already exists in the database'); |
| 33 | |
| 29 } elsif (UNIVERSAL::isa($table,'HASH')) { | 34 } elsif (UNIVERSAL::isa($table,'HASH')) { |
| 30 not exists $this->{$Tables}->{$table->{'Name'}} or die new IMPL::InvalidOperationException('a table with the same name already exists in the database'); | 35 |
| 31 $table->{'Schema'} = $this; | 36 not exists $this->{$tables}->{$table->{'name'}} or die new IMPL::InvalidOperationException('a table with the same name already exists in the database'); |
| 37 $table = { %$table }; | |
| 38 $table->{'schema'} = $this; | |
| 32 $table = new IMPL::SQL::Schema::Table(%{$table}); | 39 $table = new IMPL::SQL::Schema::Table(%{$table}); |
| 33 } else { | 40 } else { |
| 34 die new IMPL::InvalidArgumentException('Either a table object or a hash with table parameters is required'); | 41 die new IMPL::InvalidArgumentException('Either a table object or a hash with table parameters is required'); |
| 35 } | 42 } |
| 36 | 43 |
| 37 $this->{$Tables}{$table->Name} = $table; | 44 $this->{$tables}{$table->name} = $table; |
| 38 } | 45 } |
| 39 | 46 |
| 40 sub RemoveTable { | 47 sub RemoveTable { |
| 41 my ($this,$table) = @_; | 48 my ($this,$table) = @_; |
| 42 | 49 |
| 43 my $tn = UNIVERSAL::isa($table,'IMPL::SQL::Schema::Table') ? $table->Name : $table; | 50 my $tn = UNIVERSAL::isa($table,'IMPL::SQL::Schema::Table') ? $table->name : $table; |
| 44 $table = delete $this->{$Tables}{$tn} or die new IMPL::InvalidArgumentException('The table doesn\'t exists',$tn); | 51 |
| 52 $table = delete $this->{$tables}{$tn} or die new IMPL::InvalidArgumentException('The table doesn\'t exists',$tn); | |
| 45 | 53 |
| 46 # drop foreign keys | 54 # drop foreign keys |
| 47 map { $_->Table->RemoveConstraint($_) } values %{$table->PrimaryKey->ConnectedFK} if $table->PrimaryKey; | 55 map { $_->table->RemoveConstraint($_) } values %{$table->primaryKey->connectedFK} if $table->primaryKey; |
| 48 | 56 |
| 49 # drop table contents | 57 # drop table contents |
| 50 $table->Dispose(); | 58 $table->Dispose(); |
| 51 | 59 |
| 52 return 1; | 60 return 1; |
| 53 } | 61 } |
| 54 | 62 |
| 55 sub ResolveTable { | 63 sub ResolveTable { |
| 56 my ($this,$table) = @_; | 64 my ($this,$table) = @_; |
| 57 | 65 |
| 58 UNIVERSAL::isa($table,'IMPL::SQL::Schema::Table') ? $table : $this->{$Tables}{$table}; | 66 UNIVERSAL::isa($table,'IMPL::SQL::Schema::Table') ? $table : $this->{$tables}{$table}; |
| 67 } | |
| 68 | |
| 69 sub Table { | |
| 70 goto &GetTable; | |
| 59 } | 71 } |
| 60 | 72 |
| 61 sub GetTable { | 73 sub GetTable { |
| 62 my ($this,$tableName) = @_; | 74 my ($this,$tableName) = @_; |
| 63 return $this->{$Tables}{$tableName}; | 75 return $this->{$tables}{$tableName}; |
| 76 } | |
| 77 | |
| 78 sub GetTables { | |
| 79 my ($this) = @_; | |
| 80 | |
| 81 return wantarray ? values %{$this->{$tables}} : [values %{$this->{$tables}}]; | |
| 64 } | 82 } |
| 65 | 83 |
| 66 sub RenameTable { | 84 sub RenameTable { |
| 67 my ($this,$oldName,$newName) = @_; | 85 my ($this,$oldName,$newName) = @_; |
| 68 | 86 |
| 87 die new IMPL::InvalidOperationException("A source table doesn't exists", $oldName) unless exists $this->{$tables}{$oldName}; | |
| 88 die new IMPL::InvalidOperationException("A target table already exists", $newName) if exists $this->{$tables}{$newName}; | |
| 69 | 89 |
| 90 my $table = delete $this->{$tables}{$oldName}; | |
| 91 $table->_setName($newName); | |
| 92 $this->{$tables}{$newName} = $table; | |
| 70 } | 93 } |
| 71 | 94 |
| 72 sub Dispose { | 95 sub Dispose { |
| 73 my ($this) = @_; | 96 my ($this) = @_; |
| 74 | 97 |
| 75 $_->Dispose foreach values %{$this->{$Tables}}; | 98 $_->Dispose foreach values %{$this->{$tables}}; |
| 76 | 99 |
| 77 delete $this->{$Tables}; | 100 delete $this->{$tables}; |
| 78 | 101 |
| 79 $this->SUPER::Dispose; | 102 $this->SUPER::Dispose; |
| 80 } | 103 } |
| 81 | 104 |
| 82 1; | 105 1; |
| 83 | 106 |
| 84 __END__ | 107 __END__ |
| 85 =pod | 108 =pod |
| 86 | 109 |
| 87 =head1 SINOPSYS | 110 =head1 SYNOPSIS |
| 88 | 111 |
| 89 =begin code | 112 =begin code |
| 90 | 113 |
| 91 require IMPL::SQL::Schema; | 114 require IMPL::SQL::Schema; |
| 92 use IMPL::SQL::Types qw(Varchar Integer); | 115 use IMPL::SQL::Types qw(Varchar Integer); |
| 93 | 116 |
| 94 my $dbSchema = new IMPL::SQL::Schema; | 117 my $dbSchema = new IMPL::SQL::Schema; |
| 95 | 118 |
| 96 my $tbl = $dbSchema->AddTable({Name => 'Person' }); | 119 my $tbl = $dbSchema->AddTable({name => 'Person' }); |
| 97 $tbl->AddColumn({ | 120 $tbl->AddColumn({ |
| 98 Name => 'FirstName', | 121 name => 'FirstName', |
| 99 CanBeNull => 1, | 122 canBeNull => 1, |
| 100 Type => Varchar(255) | 123 type => Varchar(255) |
| 101 }); | 124 }); |
| 102 $tbl->AddColumn({ | 125 $tbl->AddColumn({ |
| 103 Name => 'Age', | 126 name => 'Age', |
| 104 Type => Integer | 127 type => Integer |
| 105 }); | 128 }); |
| 106 | 129 |
| 107 # so on | 130 # so on |
| 108 | 131 |
| 109 # and finally don't forget to | 132 # and finally don't forget to |
| 115 =head1 DESCRIPTION | 138 =head1 DESCRIPTION |
| 116 | 139 |
| 117 Схема реляциоонной базы данных, орентированная на язык SQL, содержит описания таблиц | 140 Схема реляциоонной базы данных, орентированная на язык SQL, содержит описания таблиц |
| 118 которые являются частью базы. Позволяет создавать и удалать таблицы. | 141 которые являются частью базы. Позволяет создавать и удалать таблицы. |
| 119 | 142 |
| 120 Имея две схемы можно создавать скрипты для примениения изменений схемы данных C<<IMPL::SQL::Traits>> | 143 =head1 MEMBERS |
| 144 | |
| 145 =over | |
| 146 | |
| 147 =item C<CTOR(%props)> | |
| 148 | |
| 149 Конструктор заполняет объект свойствами из C<props>. | |
| 150 | |
| 151 =item C<[get]name> | |
| 152 | |
| 153 Имя схемы. | |
| 154 | |
| 155 =item C<[get]version> | |
| 156 | |
| 157 Версия схемы. | |
| 158 | |
| 159 =item C<AddTable($table)> | |
| 160 | |
| 161 Доавляет таблицу в схему. C<$table> может быть либо таблице, либо хешем с набором | |
| 162 свойств для создания новой таблицы. Если таблица с таким именем уже существует в сехеме, | |
| 163 то вызывается исключение. | |
| 164 | |
| 165 =item C<GetTable($name)> | |
| 166 | |
| 167 Возвращает таблицу с именем C<$name> или C<undef>. | |
| 168 | |
| 169 =item C<GetTables()> | |
| 170 | |
| 171 Возвращает список таблиц. В скалярном контексте - ссылку на массив с таблицами. | |
| 172 | |
| 173 =item C<ResolveTable($table)> | |
| 174 | |
| 175 Если параметр C<$table> - таблица, то возвращается C<$table>, если C<$table> строка, то | |
| 176 ищется таблица с таким именем, если таблица не найдена, возвращается C<undef>. | |
| 177 | |
| 178 =item C<RenameTable($oldName,$newName)> | |
| 179 | |
| 180 Происходит переименование таблицы. Если C<$oldName> не существует, либо если C<$newName> | |
| 181 существует, вызывается исключение. | |
| 182 | |
| 183 =item C<RemoveTable($table)> | |
| 184 | |
| 185 Удаляется таблица C<$table> с удалением всех связей и ограничений. Если такой таблицы нет, | |
| 186 то вызывается исключение. C<$table> может быть либо именем таблицы, либо объектом. | |
| 187 | |
| 188 =back | |
| 121 | 189 |
| 122 =cut | 190 =cut |
