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;