Mercurial > pub > Impl
view Lib/IMPL/SQL/Schema/Traits.pm @ 188:029c9610528c
Memory leak tests in IMPL::Web::View
author | cin |
---|---|
date | Tue, 03 Apr 2012 20:08:42 +0400 |
parents | d1676be8afcc |
children | 4d0e1962161c |
line wrap: on
line source
package IMPL::SQL::Schema::Traits; use strict; use IMPL::_core::version; use IMPL::Exception(); use parent qw(IMPL::Object); use IMPL::Code::Loader(); # required for use with typeof operator use IMPL::SQL::Schema::Constraint::PrimaryKey(); use IMPL::SQL::Schema::Constraint::Index(); use IMPL::SQL::Schema::Constraint::Unique(); use IMPL::SQL::Schema::Constraint::ForeignKey(); ################################################### package IMPL::SQL::Schema::Traits::Table; use base qw(IMPL::Object::Fields); use fields qw( name columns constraints options ); sub CTOR { my ($this,$table,$columns,$constraints,$options) = @_; $this->{name} = $table or die new IMPL::InvalidArgumentException(table => "A table name is required"); $this->{columns} = $columns if defined $columns; $this->{constraints} = $constraints if defined $constraints; $this->{options} = $options if defined $options; } ################################################### package IMPL::SQL::Schema::Traits::Column; use base qw(IMPL::Object::Fields); use fields qw( name type isNullable defaultValue tag ); sub CTOR { my ($this, $name, $type, %args) = @_; $this->{name} = $name or die new IMPL::InvalidArgumentException("name"); $this->{type} = $type or die new IMPL::InvalidArgumentException("type"); $this->{isNullable} = $args{isNullable} if exists $args{isNullable}; $this->{defaultValue} = $args{defaultValue} if exists $args{defaultValue}; $this->{tag} = $args{tag} if exists $args{tag}; } ################################################## package IMPL::SQL::Schema::Traits::Constraint; use base qw(IMPL::Object::Fields); use fields qw( name columns ); sub CTOR { my ($this, $name, $columns) = @_; $this->{name} = $name; $this->{columns} = $columns; # list of columnNames } sub constraintClass { die new IMPL::NotImplementedException(); } ################################################## package IMPL::SQL::Schema::Traits::PrimaryKey; use base qw(IMPL::SQL::Schema::Traits::Constraint); __PACKAGE__->PassThroughArgs; use constant { constraintClass => typeof IMPL::SQL::Schema::Constraint::PrimaryKey }; ################################################## package IMPL::SQL::Schema::Traits::Index; use base qw(IMPL::SQL::Schema::Traits::Constraint); __PACKAGE__->PassThroughArgs; use constant { constraintClass => typeof IMPL::SQL::Schema::Constraint::Index }; ################################################## package IMPL::SQL::Schema::Traits::Unique; use base qw(IMPL::SQL::Schema::Traits::Constraint); __PACKAGE__->PassThroughArgs; use constant { constraintClass => typeof IMPL::SQL::Schema::Constraint::Unique }; ################################################## package IMPL::SQL::Schema::Traits::ForeignKey; use base qw(IMPL::SQL::Schema::Traits::Constraint); use fields qw( foreignTable foreignColumns ); use constant { constraintClass => typeof IMPL::SQL::Schema::Constraint::ForeignKey }; our %CTOR = ( 'IMPL::SQL::Schema::Traits::Constraint' => sub { @_[0..1] } ); sub CTOR { my ($this,$foreignTable,$foreignColumns) = @_[0,3,4]; $this->{foreignTable} = $foreignTable; $this->{foreignColunms} = $foreignColumns; } ################################################## package IMPL::SQL::Schema::Traits::CreateTable; use parent qw(-norequire IMPL::SQL::Schema::Traits); use IMPL::Class::Property; use IMPL::lang; BEGIN { public property table => prop_get | owner_set; } sub CTOR { my ($this,$table) = @_; die new IMPL::InvalidArgumentException("table", "An object of IMPL::SQL::Schema::Traits::Table type is required") unless is $table, typeof IMPL::SQL::Schema::Traits::Table; $this->table($table); } sub apply { my ($this,$schema) = @_; return 0 if ( $schema->GetTable( $this->table->{name} ) ); $schema->AddTable($this->table); return 1; } ################################################## package IMPL::SQL::Schema::Traits::DropTable; use parent qw(-norequire IMPL::SQL::Schema::Traits); use IMPL::Class::Property; BEGIN { public property tableName => prop_get | owner_set; } sub CTOR { my ($this,$tableName) = @_; $this->tableName($tableName) or die new IMPL::InvalidArgumentException("tableName is required"); } sub apply { my ($this,$schema) = @_; return 0 if $schema->GetTable( $this->tableName ); $schema->RemoveTable($this->tableName); return 1; } ################################################## package IMPL::SQL::Schema::Traits::RenameTable; use parent qw(-norequire IMPL::SQL::Schema::Traits); use IMPL::Class::Property; BEGIN { public property tableName => prop_get | owner_set; public property tableNewName => prop_get | owner_set; } sub CTOR { my ($this, $oldName, $newName) = @_; $this->tableName($oldName) or die new IMPL::InvalidArgumentException("A table name is required"); $this->tableNewName($newName) or die new IMPL::InvalidArgumentException("A new table name is required"); } sub apply { my ($this,$schema) = @_; return 0 if not $schema->GetTable($this->tableName) or $schema->GetTable($this->tableNewName); $this->RenameTable($this->tableName, $this->tableNewName); return 1; } ################################################# package IMPL::SQL::Schema::Traits::AlterTableAddColumn; use parent qw(-norequire IMPL::SQL::Schema::Traits); use IMPL::Class::Property; use IMPL::lang; BEGIN { public property tableName => prop_get | owner_set; public property column => prop_get | owner_set; } sub CTOR { my ($this,$tableName,$column) = @_; $this->tableName($tableName) or die new IMPL::InvalidArgumentException("A table name is required"); die new IMPL::InvalidArgumentException("A column should be a IMPL::SQL::Schema::Traits::Column object") unless is $column, typeof IMPL::SQL::Schema::Traits::Column; $this->column($column); } sub apply { my ($this,$schema) = @_; my $table = $schema->GetTable($this->tableName) or return 0; return 0 if $table->GetColumn( $this->column->{name} ); $table->AddColumn($this->column); return 1; } ################################################# package IMPL::SQL::Schema::Traits::AlterTableDropColumn; use parent qw(-norequire IMPL::SQL::Schema::Traits); use IMPL::Class::Property; BEGIN { public property tableName => prop_get | owner_set; public property columnName => prop_get | owner_set; } sub CTOR { my ($this,$table,$column) = @_; $this->tableName($table) or die new IMPL::InvalidArgumentException(tableName => "A table name should be specified"); $this->columnName($column) or die new IMPL::InvalidArgumentException(columnName => "A column name should be specified"); } sub apply { my ($this,$schema) = @_; local $@; return eval { $schema->GetTable($this->tableName)->RemoveColumn($this->columnName); return 1; } || 0; } ################################################# package IMPL::SQL::Schema::Traits::AlterTableChangeColumn; use parent qw(-norequire IMPL::SQL::Schema::Traits); use IMPL::Class::Property; BEGIN { public property tableName => prop_get | owner_set; public property columnName => prop_get | owner_set; public property columnType => prop_all; public property defaultValue => prop_all; public property isNullable => prop_all; public property options => prop_all; # hash diff format, (keys have a prefix '+' - add or update value, '-' remove value) } sub CTOR { my ($this, $table,$column,%args) = @_; $this->tableName($table) or die new IMPL::InvalidArgumentException(tableName => "A table name is required"); $this->columnName($column) or die new IMPL::InvalidArgumentException(columnName => "A column name is required"); $this->$_($args{$_}) for (grep exists $args{$_}, qw(columnType defaultValue isNullable options)); } sub apply { my ($this,$schema) = @_; local $@; return eval { my $column = $schema->GetTable($this->tableName)->GetColumn($this->columnName); $column->SetType($this->columnType) if defined $this->columnType; $column->SetNullable($this->isNullable) if defined $this->isNullable; $column->SetDefaultValue($this->defaultValue) if defined $this->defaultValue; $column->SetOptions($this->options) if defined $this->options; return 1; } || 0; } ################################################# package IMPL::SQL::Schema::Traits::AlterTableAddConstraint; use parent qw(-norequire IMPL::SQL::Schema::Traits); use IMPL::Class::Property; use IMPL::lang; BEGIN { public property tableName => prop_get | owner_set; public property constraint => prop_get | owner_set; } sub CTOR { my ($this,$table,$constraint) = @_; $this->tableName($table) or die new IMPL::InvalidArgumentException( tableName => "A table name is required"); die new IMPL::InvalidArgumentException(constaraint => "A valid IMPL::SQL::Schema::Traits::Constarint is required") unless is $constraint, typeof IMPL::SQL::Schema::Traits::Constraint; $this->constraint($constraint); } sub apply { my ($this,$schema) = @_; local $@; return eval { $schema->GetTable($this->tableName)->AddConstraint($this->constraint->constraintClass, $this->constraint); return 1; } || 0; } ################################################# package IMPL::SQL::Schema::Traits::AlterTableDropConstraint; use parent qw(-norequire IMPL::SQL::Schema::Traits); use IMPL::Class::Property; BEGIN { public property tableName => prop_get | owner_set; public property constraintName => prop_get | owner_set; } sub CTOR { my ($this,$table,$constraint) = @_; die new IMPL::InvalidArgumentException( tableName => "A table name is required" ) unless $table; die new IMPL::InvalidArgumentException( constraintName => "A constraint name is required" ) unless $constraint; $this->tableName($table); $this->constraintName($constraint); } sub apply { my ($this,$schema) = @_; my $table = $schema->GetTable($this->tableName) or return 0; return 0 unless $table->GetConstraint($this->constraintName); $table->RemoveConstraint($this->constraintName); return 1; } 1; __END__ =pod =head1 NAME C<IMPL::SQL::Traits> - Операции над объектками SQL схемы. =head1 DESCRIPTION Изменения схемы могу быть представлены в виде последовательности примитивных операций. Правила выполнения последовательности примитывных действий могут варьироваться в зависимости от процессора, который их выполняет. Например C<IMPL::SQL::Schema::Traits::Processor>. Данные, которые содержаться в примитивных операциях не могут существовать независимо от схемы. =head1 OPEARATIONS =head2 General Методы обще для всех примитивных операций. =over =item C<apply($schema)> Пытается приминить операцию к указанной схеме. Возвращаемое значение: =over =item C<true> Операция успешно применена к схеме. =item C<false> Операция не может быть применена к схеме. =back =back =head2 Primitive operations =over =item C<IMPL::SQL::Schema::Traits::CreateTable> Создает таблицу =over =item C<CTOR($table)> =item C<[get]table> C<IMPL::SQL::Schema::Traits::Table> - описание создаваемой таблицы =back =item C<IMPL::SQL::Schema::Traits::DropTable> Удалает таблицу по имени =over =item C<CTOR($tableName)> =item C<[get]tableName> Имя удаляемой таблицы =back =item C<IMPL::SQL::Schema::Traits::RenameTable> =over =item C<CTOR($tableName,$tableNewName)> =item C<[get]tableName> Имя таблицы, которую требуется переименовать =item C<[get]tableNewName> Новое имя таблицы =back =item C<IMPL::SQL::Schema::Traits::AlterTableAddColumn> Добавляет столбец в таблицу =over =item C<CTOR($tableName,$column)> =item C<[get]tableName> Имя таблицы в которую нужно добавить столбец =item C<[get]column> C<IMPL::SQL::Schema::Traits::Column> - описание столбца который нужно добавить =back =item C<IMPL::SQL::Schema::Traits::AlterTableDropColumn> Удаляет столбец из таблицы =over =item C<CTOR($tableName,$columnName)> =item C<[get]tableName> Имя таблицы в которой нужно удалить столбец =item C<[get]columnName> Имя столбца для удаления =back =item C<IMPL::SQL::Schema::Traits::AlterTableChangeColumn> Меняет описание столбца =over =item C<CTOR($tableName,$columnName,%args)> C<%args> - хеш, ключами которого являются оставшиеся свойства создаваемого объекта. =item C<[get]tableName> Имя таблицы в которой находится столбец. =item C<[get]columnName> Имя столбца для изменения =item C<[get]columnType> Новый тип столбца. Не задан, если тип не меняется =item C<[get]defaultValue> Значение по умолчанию. Не задано, если не меняется =item C<[get]isNullable> Может ли столбец содержать C<NULL>. Не задано, если не меняется. =item C<[get]options> Хеш опций, не задан, если опции не меняются =back =item C<IMPL::SQL::Schema::Traits::AlterTableAddConstraint> Базовый класс для операций по добавлению ограничений =over =item C<CTOR($tableName,$constraint)> =item C<[get]tableName> Имя таблицы в которую добавляется ограничение. =item C<[get]constraint> C<IMPL::SQL::Schema::Traits::Constraint> - описние ограничения, которое нужно добавить. =back =item C<IMPL::SQL::Schema::Traits::AlterTableDropConstraint> Удаляет ограничение на таблицу =over =item C<CTOR($tableName,$constraintName)> =item C<[get]tableName> Имя таблицы в которой требуется удалить ограничение. =item C<[get]constraintName> Имя ограничения для удаления. =back =back =cut