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;
+
+