#!/usr/bin/perl # # # lib: cgi-bin/ljlib.pl # use strict; require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; require "$ENV{'LJHOME'}/cgi-bin/ljviews.pl"; my $dbh = LJ::get_db_writer(); sub header_text { return <<"HEADER"; # This file is automatically generated from MySQL by \$LJHOME/bin/dumpsql.pl # Don't submit a diff against a hand-modified file - dump and diff instead. HEADER } # what tables don't we want to export the auto_increment columns from # because they already have their own unique string, which is what matters my %skip_auto = ("userproplist" => "name", "talkproplist" => "name", "logproplist" => "name", "priv_list" => "privcode", "supportcat" => "catkey", "ratelist" => "rlid", ); # get tables to export my %tables = (); my $sth = $dbh->prepare("SELECT tablename, redist_mode, redist_where ". "FROM schematables WHERE redist_mode NOT IN ('off')"); $sth->execute; while (my ($table, $mode, $where) = $sth->fetchrow_array) { $tables{$table}->{'mode'} = $mode; $tables{$table}->{'where'} = $where; } my %output; # {general|local} -> [ [ $alphasortkey, $SQL ]+ ] # dump each table. foreach my $table (sort keys %tables) { my $where; if ($tables{$table}->{'where'}) { $where = "WHERE $tables{$table}->{'where'}"; } my $sth = $dbh->prepare("DESCRIBE $table"); $sth->execute; my @cols = (); my $skip_auto = 0; while (my $c = $sth->fetchrow_hashref) { if ($c->{'Extra'} =~ /auto_increment/ && $skip_auto{$table}) { $skip_auto = 1; } else { push @cols, $c; } } # DESCRIBE table can be different between developers @cols = sort { $a->{'Field'} cmp $b->{'Field'} } @cols; my $cols = join(", ", map { $_->{'Field'} } @cols); my $sth = $dbh->prepare("SELECT $cols FROM $table $where"); $sth->execute; my $sql; while (my @r = $sth->fetchrow_array) { my %vals; my $i = 0; foreach (map { $_->{'Field'} } @cols) { $vals{$_} = $r[$i++]; } my $scope = "general"; $scope = "local" if (defined $vals{'scope'} && $vals{'scope'} eq "local"); my $verb = "INSERT IGNORE"; $verb = "REPLACE" if ($tables{$table}->{'mode'} eq "replace" && ! $skip_auto); $sql = "$verb INTO $table "; $sql .= "($cols) "; $sql .= "VALUES (" . join(", ", map { db_quote($_) } @r) . ");\n"; my $uniqc = $skip_auto{$table}; my $skey = $uniqc ? $vals{$uniqc} : $sql; push @{$output{$scope}}, [ "$table.$skey.1", $sql ]; if ($skip_auto) { # for all the *proplist tables, there might be new descriptions # or columns, but we can't do a REPLACE, because that'd mess # with their auto_increment ids, so we do insert ignore + update my $where = "$uniqc=" . db_quote($vals{$uniqc}); delete $vals{$uniqc}; $sql = "UPDATE $table SET "; $sql .= join(",", map { "$_=" . db_quote($vals{$_}) } sort keys %vals); $sql .= " WHERE $where;\n"; push @{$output{$scope}}, [ "$table.$skey.2", $sql ]; } } } # don't use $dbh->quote because it's changed between versions # and developers sending patches can't generate concise patches # it used to not quote " in a single quoted string, but later it does. # so we'll implement the new way here. sub db_quote { my $s = shift; return "NULL" unless defined $s; $s =~ s/\\/\\\\/g; $s =~ s/\"/\\\"/g; $s =~ s/\'/\\\'/g; $s =~ s/\n/\\n/g; $s =~ s/\r/\\r/g; return "'$s'"; } foreach my $k (keys %output) { my $file = $k eq "general" ? "base-data.sql" : "base-data-local.sql"; print "Dumping $file\n"; my $ffile = "$ENV{'LJHOME'}/bin/upgrading/$file"; open (F, ">$ffile") or die "Can't write to $ffile\n"; print F header_text(); foreach (sort { $a->[0] cmp $b->[0] } @{$output{$k}}) { print F $_->[1]; } close F; } # and do S1 styles (ugly schema) print "Dumping s1styles.dat\n"; require "$ENV{'LJHOME'}/bin/upgrading/s1style-rw.pl"; my $ss = {}; my $pubstyles = LJ::S1::get_public_styles({ 'formatdata' => 1}); foreach my $s (values %$pubstyles) { my $uniq = "$s->{'type'}/$s->{'styledes'}"; $ss->{$uniq}->{$_} = $s->{$_} foreach keys %$s; } s1styles_write($ss); # and dump mood info print "Dumping moods.dat\n"; open (F, ">$ENV{'LJHOME'}/bin/upgrading/moods.dat") or die; $sth = $dbh->prepare("SELECT moodid, mood, parentmood FROM moods ORDER BY moodid"); $sth->execute; while (@_ = $sth->fetchrow_array) { print F "MOOD @_\n"; } $sth = $dbh->prepare("SELECT moodthemeid, name, des FROM moodthemes WHERE is_public='Y' ORDER BY name"); $sth->execute; while (my ($id, $name, $des) = $sth->fetchrow_array) { $name =~ s/://; print F "MOODTHEME $name : $des\n"; my $std = $dbh->prepare("SELECT moodid, picurl, width, height FROM moodthemedata ". "WHERE moodthemeid=$id ORDER BY moodid"); $std->execute; while (@_ = $std->fetchrow_array) { print F "@_\n"; } } close F; print "Done.\n";