Mercurial > pub > Impl
diff Lib/Deployment/CDBI.pm @ 0:03e58a454b20
Создан репозитарий
author | Sergey |
---|---|
date | Tue, 14 Jul 2009 12:54:37 +0400 |
parents | |
children | 16ada169ca75 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Lib/Deployment/CDBI.pm Tue Jul 14 12:54:37 2009 +0400 @@ -0,0 +1,101 @@ +use strict; +package Deployment::CDBI; +use Common; +use DBI; +use Schema::DataSource; +use Schema::DataSource::CDBIBuilder; + +our @ISA = qw(Object); + +BEGIN { + DeclareProperty DataSchemaFile => ACCESS_READ; + DeclareProperty DataSourceDir => ACCESS_READ; + DeclareProperty DSNamespace => ACCESS_READ; + DeclareProperty DBConnection => ACCESS_READ; + DeclareProperty DBTraitsClass => ACCESS_READ; +} + +sub CTOR { + my ($this,%args) = @_; + + $this->{$DataSchemaFile} = $args{'DataSchemaFile'} or die new Exception('A data shema file is required'); + $this->{$DataSourceDir} = $args{'DataSourceDir'} or die new Exception('A directory for a data source is required'); + $this->{$DSNamespace} = $args{'DSNamespace'} || 'DataSource'; + $this->{$DBTraitsClass} = $args{'DBTraitsClass'} or die new Exception('A DBTraitsClass is required'); + $this->{$DBConnection} = $args{'DBConnection'}; +} + +sub Update { + my ($this) = @_; + + my $prefix = $this->{$DSNamespace}.'::'; + + my $schemaDS = new Schema::DataSource(DataSourceBuilder => new Schema::DataSource::CDBIBuilder); + $schemaDS->BuildSchema($this->{$DataSchemaFile}); + + my $schemaDB = $schemaDS->DataSourceBuilder->BuildDBSchema(); + (my $fname = $this->{$DSNamespace} ) =~ s/::/\//g; + $schemaDS->DataSourceBuilder->WriteModules($this->{$DataSourceDir}.$fname.'.pm',$prefix); + + if ($this->{$DBConnection}) { + + my $dbh = DBI->connect(@{$this->{$DBConnection}}) or die new Exception('Failed to connect to the database',@{$this->{$DBConnection}}); + my $SchemaSource; + if (UNIVERSAL::can($this->{$DBTraitsClass},'GetMetaTable')) { + $SchemaSource = new Deployment::CDBI::SQLSchemeSource (MetaTable => $this->{$DBTraitsClass}->GetMetaTable($dbh)); + } else { + die new Exception("Can't get meta table"); + } + + my $schemaDBOld = $SchemaSource->ReadSchema($schemaDB->Name); + + my $updater = $this->{$DBTraitsClass}->new(SrcSchema => $schemaDBOld, DstSchema => $schemaDB); + $updater->UpdateSchema(); + + $dbh->do($_) or die new Exception('Failed to execute the sql statement', $_) foreach $updater->Handler->Sql; + + $SchemaSource->SaveSchema($schemaDB); + + $schemaDBOld->Dispose; + } + $schemaDB->Dispose; +} + +package Deployment::CDBI::SQLSchemeSource; +use Common; +use Data::Dumper; +use MIME::Base64; +use Storable qw(nstore_fd fd_retrieve); +our @ISA = qw(Object); + +BEGIN { + DeclareProperty MetaTable => ACCESS_NONE; +} + +sub ReadSchema { + my ($this,$name) = @_; + + my $schema = decode_base64($this->{$MetaTable}->ReadProperty("db_schema_$name")); + if ($schema) { + open my $hvar,"<",\$schema or die new Exception("Failed to create a handle to the variable"); + return fd_retrieve($hvar); + } else { + return new Schema::DB(Name => $name, Version => 0); + } +} + +sub SaveSchema { + my ($this,$schema) = @_; + + my $name = $schema->Name; + + my $data; + { + open my $hvar,">",\$data or die new Exception("Failed to create a handle to the variable"); + nstore_fd($schema,$hvar); + } + + $this->{$MetaTable}->SetProperty("db_schema_$name",encode_base64($data)); +} + +1;