File Coverage

blib/lib/DBIx/Migrate.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             package DBIx::Migrate;
2              
3 1     1   51314 use strict;
  1         3  
  1         49  
4 1     1   7 use Carp;
  1         2  
  1         117  
5 1     1   6 use vars qw( $VERSION );
  1         8  
  1         60  
6 1     1   522 use DBI;
  0            
  0            
7             use Data::Dumper;
8            
9             $VERSION=0.01;
10              
11             my $data_types = {
12             qw!
13             1 char
14             2 numeric
15             3 decimal
16             4 integer
17             5 smallint
18             6 float
19             7 real
20             8 double
21             9 date
22             10 time
23             11 timestamp
24             12 varchar
25             -1 text
26             -2 binary
27             -3 varbinary
28             -4 blob
29             -5 bigint
30             -6 tinyint
31             -7 bit
32             -8 wchar
33             -9 wvarchar
34             -10 wlongvarchar
35             ! };
36              
37             # Constructor
38             sub new {
39             my($class, %parm) = @_;
40             croak 'Expecting a class' if ref $class;
41              
42             ## don't overwrite target table if it already exists
43             my $self = { CLOBBER => 0,
44             TYPE_TRANSLATE => $data_types
45             };
46              
47             ## the lazy method
48             while(my($k, $v) = each(%parm)) { $self->{$k} = $v};
49              
50             ## retrieve all tables in source database
51             unless(%{ $self->{SOURCE_TABLES} } = map { $_ => 1 } $self->{SOURCE}->tables) {
52             croak('no tables in source database');
53             }
54              
55             # croak if requested source table doesn't exist
56             for (@{ $self->{TABLES} }) {
57             croak("source table: $_ not found")
58             unless exists($self->{SOURCE_TABLES}{$_});
59             }
60              
61             ## retrieve all tables in target database
62             if( $self->{TARGET}->tables ) {
63             %{ $self->{TARGET_TABLES} } = map { $_ => 1 } $self->{TARGET}->tables;
64             }
65              
66             ## check CLOBBER and croak if table already exists target database
67             my @common = ();
68             for (keys %{ $self->{SOURCE_TABLES} } ) {
69             push(@common, $_) if exists $self->{TARGET_TABLES}{$_};
70             }
71             if( @common && !($self->{CLOBBER}) ) {
72             croak("@common target table(s) already exist; set CLOBBER to overwrite");
73             }
74             bless $self, $class;
75             return $self;
76             }
77              
78             sub migrate {
79             my ($self, %parm) = @_;
80             my ($source, $target, $tbl_count);
81             ## the lazy method
82             while(my($k, $v) = each(%parm)) { $self->{$k} = $v };
83             for my $table (@{ $self->{TABLES} })
84             {
85             $source = $self->{SOURCE}->prepare("SELECT * from $table");
86             $source->execute();
87            
88             ## Guess data types and precision of source table
89             my $create = "CREATE TABLE $table (\n";
90             for( my $i=0; $i <= $source->{NUM_OF_FIELDS}; $i++) {
91             next unless( $source->{NAME}->[$i] &&
92             $source->{TYPE}->[$i] &&
93             $source->{PRECISION}->[$i]
94             );
95             $create .= "$source->{NAME}->[$i] $self->{TYPE_TRANSLATE}{$source->{TYPE}->[$i]}";
96             $create .= "($source->{PRECISION}->[$i])" unless($source->{TYPE}->[$i] == 9);
97              
98             $create .= " NOT NULL" unless($source->{NULLABLE}->[$i]);
99             if ( $source->{NAME}->[$i+1] &&
100             $source->{TYPE}->[$i+1] &&
101             $source->{PRECISION}->[$i+1]
102             )
103             {
104             $create .= ",\n";
105             }
106             }
107             $create .= "\n)";
108              
109             ## Create target table using approximate data types and precision
110             ## WARNING: TARGET TABLE IS DROPPED IF IT ALREADY EXISTS!
111             $self->{TARGET}->do("DROP TABLE $table")
112             if(exists($self->{TARGET_TABLES}{$table}));
113             $self->{TARGET}->do($create);
114            
115             ## Create insertion fields
116             my $fields = join(',', @{ $source->{NAME} });
117             my $qmarks = join(',', (map { '?' } @{ $source->{NAME} }));
118             $source->finish();
119            
120             my $select = qq!
121             SELECT $fields
122             FROM $table
123             !;
124            
125             my $insert = qq!
126             INSERT INTO $table ($fields)
127             VALUES ($qmarks)
128             !;
129            
130             $source = $self->{SOURCE}->prepare($select);
131             $target = $self->{TARGET}->prepare($insert);
132            
133             $source->execute();
134            
135             while (my $rows = $source->fetchrow_arrayref) {
136             $target->execute(@{$rows});
137             }
138             $source->finish();
139             $target->finish();
140             $tbl_count++;
141             }
142             return $tbl_count;
143             }
144              
145             1;
146             __END__