root/trunk/tools/convert-db

Revision 4196, 7.3 kB (checked in by takayama, 3 months ago)

* Set svn keywords

  • Property svn:keywords set to Author Date Id Revision
Line 
1#!/usr/bin/perl -w
2
3# Movable Type (r) Open Source (C) 2001-2009 Six Apart, Ltd.
4# This program is distributed under the terms of the
5# GNU General Public License, version 2.
6#
7# $Id$
8
9use strict;
10
11use Getopt::Long;
12GetOptions( "old:s" => \my($old_config),
13            "new:s" => \my($new_config));
14
15use lib 'extlib';
16use lib 'lib';
17
18unless ($new_config) {
19    print "Need configuration file location. cf: convert-db --new==mt-config.cgi.new";
20    exit;
21}
22
23$old_config ||= '.';
24
25my @CLASSES = qw( MT::Author MT::Blog MT::Category MT::Comment MT::Entry
26                  MT::IPBanList MT::Log MT::Notification MT::Permission
27                  MT::Placement MT::Template MT::TemplateMap MT::Trackback
28                  MT::TBPing MT::Session MT::PluginData MT::Config MT::FileInfo
29                  MT::Tag MT::ObjectTag MT::Group MT::Role MT::Association
30                  MT::Asset
31                  );
32
33use File::Spec;
34
35eval {
36    local $SIG{__WARN__} = sub { print "**** WARNING: $_[0]\n" };
37
38    require MT;
39    my $mt = MT->new(Config => $old_config) or die MT->errstr;
40    my $cfg = $mt->{cfg};
41
42    my $cfg_file_orig = $mt->{cfg_file};
43    my $cfg_file_new = $mt->find_config({Config=>$new_config});
44
45    $cfg->read_config($cfg_file_new);
46
47    warn $cfg_file_orig;
48    warn $cfg_file_new;
49
50    require MT::Object;
51    MT::Object->set_driver($cfg->ObjectDriver)
52        or die MT::ObjectDriver->errstr;
53
54    use MT::Upgrade;
55    my @stmts;
56    foreach (@CLASSES) {
57        push @stmts, MT::Upgrade->check_class($_);
58    }
59
60    print "Loading database schema...\n\n";
61    MT::Upgrade->do_upgrade(Install => 1);
62
63    ## %ids will hold the highest IDs of each class.
64    my %ids;
65
66    print "Loading data...\n";
67    for my $class (@CLASSES ) {
68        print $class, "\n";
69        $cfg->read_config($cfg_file_orig);
70        MT::Object->set_driver($cfg->ObjectDriver);
71        eval "use $class";
72        my $iter = $class->load_iter;
73
74        my %names;
75        my %cat_parent;
76
77        $cfg->read_config($cfg_file_new);
78        MT::Object->set_driver($cfg->ObjectDriver);
79        while (my $obj = $iter->()) {
80            print "    ", $obj->id, "\n";
81            $obj = clean_object($obj);
82            # Update IDs only auto_increment.
83            $ids{$class} = $obj->id
84                if $obj->column_defs->{id}->{auto} &&
85                   (!$ids{$class} || $obj->id > $ids{$class});
86            ## Look for duplicate template, category, and author names,
87            ## because we have uniqueness constraints in the DB.
88            if ($class eq 'MT::Template') {
89                my $key = $obj->blog_id . ':' . lc($obj->name);
90                if ($names{$class}{$key}++) {
91                    print "        Found duplicate template name '" .
92                          $obj->name;
93                    $obj->name($obj->name . ' ' . $names{$class}{$key});
94                    print "'; renaming to '" . $obj->name . "'\n";
95                }
96                ## Touch the text column to make sure we read in
97                ## any linked templates.
98                my $text = $obj->text;
99            } elsif ($class eq 'MT::Author') {
100                my $key = lc($obj->name);
101                if ($names{$class . $obj->type}{$key}++) {
102                    print "        Found duplicate author name '" .
103                          $obj->name;
104                    $obj->name($obj->name . ' ' . $names{$class}{$key});
105                    print "'; renaming to '" . $obj->name . "'\n";
106                }
107                $obj->email('') unless defined $obj->email;
108                $obj->set_password('') unless defined $obj->password;
109            } elsif ($class eq 'MT::Comment') {
110                $obj->visible(1) unless defined $obj->visible;
111            } elsif ($class eq 'MT::TBPing') {
112                $obj->visible(1) unless defined $obj->visible;
113            } elsif ($class eq 'MT::Category') {
114                my $key = lc($obj->label) . $obj->blog_id;
115                if ($names{$class}{$key}++) {
116                    print "        Found duplicate category label '" .
117                          $obj->label;
118                    $obj->label($obj->label . ' ' . $names{$class}{$key});
119                    print "'; renaming to '" . $obj->label . "'\n";
120                }
121                # save the parent value for assignment at the end
122                if ($obj->parent) {
123                    $cat_parent{$obj->id} = $obj->parent;
124                    $obj->parent(0);
125                }
126            } elsif ($class eq 'MT::Trackback') {
127                $obj->entry_id(0) unless defined $obj->entry_id;
128                $obj->category_id(0) unless defined $obj->category_id;
129            } elsif ($class eq 'MT::Entry') {
130                $obj->allow_pings(0)
131                    if defined $obj->allow_pings && $obj->allow_pings eq '';
132                $obj->allow_comments(0)
133                    if defined $obj->allow_comments && $obj->allow_comments eq '';
134            }
135            $obj->save
136                or die $obj->errstr;
137        }
138
139        # fix up the category parents
140        foreach my $id (keys %cat_parent) {
141            my $cat = MT::Category->load($id);
142            $cat->parent( $cat_parent{$id} );
143            $cat->save;
144        }
145
146        print "\n";
147    }
148
149    if ($cfg->ObjectDriver =~ /postgres/) {
150        print "Updating sequences\n";
151        my $dbh = MT::Object->driver->{dbh};
152        for my $class (keys %ids) {
153            print "    $class => $ids{$class}\n";
154            my $seq = 'mt_' . $class->datasource . '_' .
155                      $class->properties->{primary_key};
156            $dbh->do("select setval('$seq', $ids{$class})")
157                or die $dbh->errstr;
158        }
159    } elsif ($cfg->ObjectDriver =~ /oracle/) {
160        print "Updating sequences\n";
161        for my $class (keys %ids) {
162            print "    $class => $ids{$class}\n";
163            MT::Object->driver->drop_sequence($class);
164            MT::Object->driver->create_sequence($class);
165        }
166    }
167
168    $cfg->SchemaVersion(MT->schema_version(), 1);
169    $cfg->save_config();
170};
171if ($@) {
172    print "An error occurred while loading data: $@\n";
173} else {
174    print "Done copying data! All went well.\n";
175}
176
177
178sub clean_object {
179    my $obj = shift;
180    my $defs = $obj->column_defs;
181
182    foreach my $col (keys %{$defs}) {
183        my $def = $defs->{$col};
184        if ($def->{type} =~ /(?:integer|smallint)/ && $obj->$col) {
185            my $val = $obj->$col;
186            if ($val =~ /\D/) {
187                $val =~ s/\D//g;
188                $obj->$col($val);
189            }
190        }
191        if ($def->{type} =~ /(?:string)/ && $obj->$col) {
192            require MT::I18N;
193            my $val = $obj->$col;
194            if (MT::I18N::length_text($val) > $def->{size}) {
195                $obj->$col(MT::I18N::substr_text($val,0,$def->{size}));
196            }
197        }
198    }
199    return $obj;
200}
2011;
202
203__END__
204
205=head1 NAME
206
207convert-db - A tool to convert backend database of Movable Type
208
209=head1 SYNOPSIS
210
211convert-db --new=mt-config.cgi.new [--old=mt-config.cgi.current]
212
213=head1 DESCRIPTION
214
215I<convert-db> is a tool to convert database of Movable Type to
216others.  It is useful when it is necessary to switch like from
217MySQL to PostgreSQL.
218
219The following options are available:
220
221  --new       mt-config.cgi file of destination
222  --old       mt-config.cgi file of source (optional)
223
224It is also useful to replicate Movable Type database.
225
226=cut
Note: See TracBrowser for help on using the browser.