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