root/mt-db-convert/tags/0.11/mt-db-convert.cgi

Revision 109, 9.2 kB (checked in by ogawa, 3 years ago)

Fix for subcategory bug.
Fix for stopping warnings for saving MT::Blog objects.

Line 
1#!/usr/bin/perl -w
2# mt-db-convert.cgi: converting your MT data between multiple db engines
3# This is a derived work from the following:
4#
5# Copyright 2001-2005 Six Apart. This code cannot be redistributed without
6# permission from www.movabletype.org.
7#
8# $Id: mt-db2sql.cgi 12446 2005-05-25 21:32:39Z bchoate $
9use strict;
10
11my $VERSION = '0.11';
12
13my($MT_DIR);
14BEGIN {
15    if ($0 =~ m!(.*[/\\])!) {
16        $MT_DIR = $1;
17    } else {
18        $MT_DIR = './';
19    }
20    unshift @INC, $MT_DIR . 'lib';
21    unshift @INC, $MT_DIR . 'extlib';
22}
23
24local $| = 1;
25print "Content-Type: text/html\n\n";
26print <<HTML;
27<html>
28<head><title>mt-db-convert $VERSION: Converting your MT data</title></head>
29<body>
30<p><strong>mt-db-convert $VERSION: Coverting your MT data between DB engines</strong></p>
31HTML
32
33my @CLASSES = qw( MT::Author MT::Blog MT::Category MT::Comment MT::Entry
34                  MT::IPBanList MT::Log MT::Notification MT::Permission
35                  MT::Placement MT::Template MT::TemplateMap MT::Trackback
36                  MT::TBPing );
37
38use File::Spec;
39
40my @DBSPECS = qw( DataSource ObjectDriver Database DBUser DBHost DBPassword );
41
42require MT;
43my $mt = MT->new(Config => $MT_DIR . 'mt.cfg', Directory => $MT_DIR)
44    or die MT->errstr;
45my $cfg = $mt->{cfg};
46
47use CGI;
48my $q = CGI->new;
49
50my (%src, %dst);
51foreach (@DBSPECS) {
52    $src{$_} = $q->param('src_' . $_) || '';
53    $dst{$_} = $q->param('dst_' . $_) || '';
54}
55
56# If src and dst dbspecs not given
57if (!$src{ObjectDriver} || ($src{ObjectDriver} eq 'DBM' && $src{DataSource}) ||
58    !$dst{ObjectDriver} || ($dst{ObjectDriver} eq 'DBM' && $dst{DataSource})) {
59
60    $src{$_} ||= $cfg->$_() foreach (@DBSPECS);
61
62    my %src_selected = ('DBM' => '', 'DBI::mysql' => '', 'DBI::postgres' => '', 'DBI::sqlite' => '');
63    my %dst_selected = ('DBM' => '', 'DBI::mysql' => '', 'DBI::postgres' => '', 'DBI::sqlite' => '');
64    $src_selected{$src{ObjectDriver}} = 'selected' if $src{ObjectDriver};
65    $dst_selected{$dst{ObjectDriver}} = 'selected' if $dst{ObjectDriver};
66
67    my $script_name = ($0 =~ m![/\\]([^/\\]+)$!) ? $1 : 'mt-db-convert.cgi';
68
69    print <<HTML;
70<p>Please fill the following:</p>
71
72<form method="post" action="$script_name">
73<style>fieldset { width: 40%; float: left; }</style>
74<fieldset>
75<legend>Source DB Configuration</legend>
76<dl>
77<dt>DataSource: (Required for BerkeleyDB)</dt>
78<dd><input name="src_DataSource" type="text" value="$src{DataSource}" /></dd>
79<dt>ObjectDriver:</dt>
80<dd><select name="src_ObjectDriver">
81<option value="">Select a driver</option>
82<option value="DBM" $src_selected{'DBM'}>BerkeleyDB</option>
83<option value="DBI::mysql" $src_selected{'DBI::mysql'}>MySQL</option>
84<option value="DBI::postgres" $src_selected{'DBI::postgres'}>PostgreSQL</option>
85<option value="DBI::sqlite" $src_selected{'DBI::sqlite'}>SQLite</option>
86</select></dd>
87<dt>Database:</dt>
88<dd><input name="src_Database" type="text" value="$src{Database}" /></dd>
89<dt>DBUser:</dt>
90<dd><input name="src_DBUser" type="text" value="$src{DBUser}" /></dd>
91<dt>DBHost:</dt>
92<dd><input name="src_DBHost" type="text" value="$src{DBHost}" /></dd>
93<dt>DBPassword:</dt>
94<dd><input name="src_DBPassword" type="password" value="" /></dd>
95</dl>
96</fieldset>
97
98<fieldset>
99<legend>Destination DB Configuration</legend>
100<dl>
101<dt>DataSource: (Required for BerkeleyDB)</dt>
102<dd><input name="dst_DataSource" type="text" value="$dst{DataSource}" /></dd>
103<dt>ObjectDriver:</dt>
104<dd><select name="dst_ObjectDriver">
105<option value="">Select a driver</option>
106<option value="DBM" $dst_selected{'DBM'}>BerkeleyDB</option>
107<option value="DBI::mysql" $dst_selected{'DBI::mysql'}>MySQL</option>
108<option value="DBI::postgres" $dst_selected{'DBI::postgres'}>PostgreSQL</option>
109<option value="DBI::sqlite" $dst_selected{'DBI::sqlite'}>SQLite</option>
110</select></dd>
111<dt>Database:</dt>
112<dd><input name="dst_Database" type="text" value="$dst{Database}" /></dd>
113<dt>DBUser:</dt>
114<dd><input name="dst_DBUser" type="text" value="$dst{DBUser}" /></dd>
115<dt>DBHost:</dt>
116<dd><input name="dst_DBHost" type="text" value="$dst{DBHost}" /></dd>
117<dt>DBPassword:</dt>
118<dd><input name="dst_DBPassword" type="password" value="$dst{DBPassword}" /></dd>
119</dl>
120</fieldset>
121
122<p style="clear:both;"><input type="submit" value="Convert" /></p>
123</form>
124HTML
125
126} else {
127
128eval {
129    local $SIG{__WARN__} = sub { print "**** WARNING: $_[0]\n" };
130
131    require MT::Object;
132    my ($type) = $dst{ObjectDriver} =~ /^DBI::(.*)$/;
133    if ($type) {
134    # set dst driver
135    $cfg->set($_, $dst{$_}) foreach (@DBSPECS);
136    MT::Object->set_driver($dst{ObjectDriver})
137        or die MT::ObjectDriver->errstr;
138    my $dbh = MT::Object->driver->{dbh};
139    $dbh->begin_work if $type eq 'sqlite';
140    my $schema = File::Spec->catfile($MT_DIR, 'schemas', $type . '.dump');
141    open FH, $schema or die "Can't open schema file '$schema': $!";
142    my $ddl;
143    { local $/; $ddl = <FH> }
144    close FH;
145    my @stmts = split /;/, $ddl;
146    print "<p>Loading database schema...</p>\n\n";
147    for my $stmt (@stmts) {
148        $stmt =~ s!^\s*!!;
149        $stmt =~ s!\s*$!!;
150        next unless $stmt =~ /\S/;
151        $dbh->do($stmt) or die $dbh->errstr;
152    }
153    $dbh->commit if $type eq 'sqlite';
154    }
155
156    ## %ids will hold the highest IDs of each class.
157    my %ids;
158
159    for my $class (@CLASSES) {
160        print "<p>Dumping $class:<br />\n";
161
162        # set source driver
163        $cfg->set($_, $src{$_}) foreach (@DBSPECS);
164        MT::Object->set_driver($src{ObjectDriver});
165
166        eval "use $class";
167        my $iter = $class->load_iter;
168
169        my %names;
170        my %cat_parent;
171
172        # set dst driver
173        $cfg->set($_, $dst{$_}) foreach (@DBSPECS);
174        MT::Object->set_driver($dst{ObjectDriver});
175        MT::Object->driver->{dbh}->begin_work if $type eq 'sqlite';
176
177        my $i = 0;
178        while (my $obj = $iter->()) {
179            $ids{$class} = $obj->id
180                if !$ids{$class} || $obj->id > $ids{$class};
181            ## Look for duplicate template, category, and author names,
182            ## because we have uniqueness constraints in the DB.
183            if ($class eq 'MT::Template') {
184                my $key = lc($obj->name) . $obj->blog_id;
185                if ($names{$class}{$key}++) {
186                    print "        Found duplicate template name '" .
187                          $obj->name;
188                    $obj->name($obj->name . ' ' . $names{$class}{$key});
189                    print "'; renaming to '" . $obj->name . "'\n";
190                }
191                ## Touch the text column to make sure we read in
192                ## any linked templates.
193                my $text = $obj->text;
194            } elsif ($class eq 'MT::Author') {
195                my $key = lc($obj->name);
196                if ($names{$class . $obj->type}{$key}++) {
197                    print "        Found duplicate author name '" .
198                          $obj->name;
199                    $obj->name($obj->name . ' ' . $names{$class}{$key});
200                    print "'; renaming to '" . $obj->name . "'\n";
201                }
202                $obj->email('') unless defined $obj->email;
203                $obj->set_password('') unless defined $obj->password;
204            } elsif ($class eq 'MT::Category') {
205                my $key = lc($obj->label) . $obj->blog_id;
206                if ($names{$class}{$key}++) {
207                    print "        Found duplicate category label '" .
208                          $obj->label;
209                    $obj->label($obj->label . ' ' . $names{$class}{$key});
210                    print "'; renaming to '" . $obj->label . "'\n";
211                }
212                # save the parent value for assignment at the end
213                if ($obj->parent) {
214                    $cat_parent{$obj->id} = $obj->parent;
215                    $obj->parent(0);
216                }
217            } elsif ($class eq 'MT::Trackback') {
218                $obj->entry_id(0) unless defined $obj->entry_id;
219                $obj->category_id(0) unless defined $obj->category_id;
220            } elsif ($class eq 'MT::Entry') {
221                $obj->allow_pings(0)
222                    if defined $obj->allow_pings && $obj->allow_pings eq '';
223                $obj->allow_comments(0)
224                    if defined $obj->allow_comments && $obj->allow_comments eq '';
225            } elsif ($class eq 'MT::Blog') {
226                $obj->touch(); # for updating children_modified_on field
227            }
228
229            $i++;
230            $obj->save
231                or die $obj->errstr;
232            print ".";
233            $i % 10 or print " ";
234            $i % 100 or print "<br />\n";
235        }
236
237        # fix up the category parents
238        foreach my $id (keys %cat_parent) {
239            my $cat = MT::Category->load($id);
240            $cat->parent( $cat_parent{$id} );
241            $cat->save;
242        }
243
244        print "</p>\n\n";
245        MT::Object->driver->{dbh}->commit if $type eq 'sqlite';
246    }
247
248    if ($type eq 'postgres') {
249        print "Updating sequences\n";
250        my $dbh = MT::Object->driver->{dbh};
251        for my $class (keys %ids) {
252            print "    $class => $ids{$class}\n";
253            my $seq = 'mt_' . $class->datasource . '_' .
254                      $class->properties->{primary_key};
255            $dbh->do("select setval('$seq', $ids{$class})")
256                or die $dbh->errstr;
257        }
258    }
259};
260if ($@) {
261    print <<HTML;
262<p>An error occurred while loading data: <br />
263$@</p>
264HTML
265} else {
266    print <<HTML;
267<p>Done copying data from $src{ObjectDriver} to $dst{ObjectDriver}! All went well.</p>
268HTML
269}
270
271}
272
273print "</body>\n</html>\n";
Note: See TracBrowser for help on using the browser.