comparison Lib/Deployment/Batch/CDBIUpdate.pm @ 0:03e58a454b20

Создан репозитарий
author Sergey
date Tue, 14 Jul 2009 12:54:37 +0400
parents
children 16ada169ca75
comparison
equal deleted inserted replaced
-1:000000000000 0:03e58a454b20
1 use strict;
2 package Deployment::Batch::CDBIUpdate;
3 use Common;
4 use base qw(Deployment::Batch::Generic);
5
6 use DBI;
7 use Schema::DataSource;
8 use Schema::DataSource::CDBIBuilder;
9
10
11 BEGIN {
12 DeclareProperty DataSchemaFile => ACCESS_READ;
13 DeclareProperty DataSourceDir => ACCESS_READ;
14 DeclareProperty DSNamespace => ACCESS_READ;
15 DeclareProperty DBConnection => ACCESS_READ;
16 DeclareProperty DBTraitsClass => ACCESS_READ;
17 DeclareProperty SchemaPrev => ACCESS_READ;
18 }
19
20 sub CTOR {
21 my ($this,%args) = @_;
22
23 $this->{$DataSchemaFile} = $args{'Source'} or die new Exception('A data shema file is required');
24 $this->{$DataSourceDir} = $args{'Output'} or die new Exception('A directory for a data source is required');
25 $this->{$DSNamespace} = $args{'Namespace'} || 'DataSource';
26 $this->{$DBTraitsClass} = $args{'DBTraits'} or die new Exception('A DBTraitsClass is required');
27
28 (my $modname = $args{'DBTraits'}.'.pm') =~ s/::/\//g;
29 $this->Log("Loading DBTraits '$modname'");
30 require $modname;
31 }
32
33 sub Run {
34 my ($this) = @_;
35
36 $this->{$DBConnection} = $this->Context->{Connection};
37
38 my $prefix = $this->{$DSNamespace}.'::';
39
40 my $schemaDS = new Schema::DataSource(DataSourceBuilder => new Schema::DataSource::CDBIBuilder);
41 $schemaDS->BuildSchema($this->{$DataSchemaFile});
42
43 my $schemaDB = $schemaDS->DataSourceBuilder->BuildDBSchema();
44 (my $fname = $this->{$DataSourceDir}.$this->{$DSNamespace}.'.pm') =~ s/::/\//g;
45
46 # we are in the immediate mode, so the file will be backupped immediatelly;
47 $this->Log("Backup $fname");
48 Deployment::Batch->Backup( File => $fname );
49
50 $this->Log("Write the datasource '$this->{$DSNamespace}' to '$this->{$DataSourceDir}'");
51 $schemaDS->DataSourceBuilder->WriteModules($fname,$prefix);
52
53 if ($this->{$DBConnection}) {
54 $this->Log("Update the database '$this->{$DBConnection}[0]'");
55
56 $this->{$SchemaPrev} = $this->UpdateDBToSchema($schemaDB);
57
58 }
59 $schemaDB->Dispose;
60 }
61
62 sub Rollback {
63 my ($this) = @_;
64
65 if ($this->{$SchemaPrev}) {
66 $this->Log("Rallback the DB schema");
67 $this->UpdateDBToSchema($this->{$SchemaPrev})->Dispose;
68 $this->{$SchemaPrev}->Dispose;
69 delete $this->{$SchemaPrev};
70 }
71
72 }
73
74 sub UpdateDBToSchema {
75 my ($this,$schemaDB) = @_;
76 my $dbh = DBI->connect(@{$this->{$DBConnection}}) or die new Exception('Failed to connect to the database',@{$this->{$DBConnection}});
77 my $SchemaSource;
78
79 if (UNIVERSAL::can($this->{$DBTraitsClass},'GetMetaTable')) {
80 $SchemaSource = new Deployment::CDBI::SQLSchemeSource (MetaTable => $this->{$DBTraitsClass}->GetMetaTable($dbh));
81 } else {
82 die new Exception("Can't get a meta table",$this->{$DBTraitsClass});
83 }
84
85 my $schemaDBOld = $SchemaSource->ReadSchema($schemaDB->Name);
86
87 my $updater = $this->{$DBTraitsClass}->new(SrcSchema => $schemaDBOld, DstSchema => $schemaDB);
88 $updater->UpdateSchema();
89
90 $dbh->do($_) or die new Exception('Failed to execute the sql statement', $_) foreach $updater->Handler->Sql;
91
92 $SchemaSource->SaveSchema($schemaDB);
93 return $schemaDBOld;
94 }
95
96 sub DESTROY {
97 my $this = shift;
98
99 $this->{$SchemaPrev}->Dispose if $this->{$SchemaPrev};
100 }
101
102 package Deployment::CDBI::SQLSchemeSource;
103 use Common;
104 use Data::Dumper;
105 use MIME::Base64;
106 use Storable qw(nstore_fd fd_retrieve);
107 our @ISA = qw(Object);
108
109 BEGIN {
110 DeclareProperty MetaTable => ACCESS_NONE;
111 }
112
113 sub ReadSchema {
114 my ($this,$name) = @_;
115
116 my $schema = decode_base64($this->{$MetaTable}->ReadProperty("db_schema_$name"));
117 if ($schema) {
118 open my $hvar,"<",\$schema or die new Exception("Failed to create a handle to the variable");
119 return fd_retrieve($hvar);
120 } else {
121 return new Schema::DB(Name => $name, Version => 0);
122 }
123 }
124
125 sub SaveSchema {
126 my ($this,$schema) = @_;
127
128 my $name = $schema->Name;
129
130 my $data = "";
131 {
132 open my $hvar,">",\$data or die new Exception("Failed to create a handle to the variable");
133 nstore_fd($schema,$hvar);
134 }
135
136 $this->{$MetaTable}->SetProperty("db_schema_$name",encode_base64($data));
137 }
138
139 1;