X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~yarrgweb/git?p=ypp-sc-tools.db-live.git;a=blobdiff_plain;f=yarrg%2Fdb-idempotent-populate;h=eb1a30b43a581047e330b4f226670083366e3fb0;hp=aa8026272f3727f77ccd7c740eb7da43040fe110;hb=4dbb6c3acfdb73f76c221ab016a4406a7b4daacb;hpb=ee1e57fa0fab5d840206d73a3968fd59d7fa7127 diff --git a/yarrg/db-idempotent-populate b/yarrg/db-idempotent-populate index aa80262..eb1a30b 100755 --- a/yarrg/db-idempotent-populate +++ b/yarrg/db-idempotent-populate @@ -36,9 +36,9 @@ use DBI; use Commods; use CommodsDatabase; -my $trace; -if (@ARGV and $ARGV[0] eq '-D') { - $trace=1; +my $trace=0; +while (@ARGV and $ARGV[0] eq '-D') { + $trace++; shift @ARGV; } @@ -61,6 +61,9 @@ $dbh->trace(1) if $trace; #---------- schema update code ---------- our @need_compact; +our @need_transfer_back; + +our %table; sub table ($$) { my ($table, $fields) = @_; @@ -126,44 +129,66 @@ END $check->finish(); my @have_fields; + my @aside_fields; my @have_field_specs; + my @aside_field_specs; foreach my $f (@want_fields) { if ($have_fields{$f}) { push @have_fields, $f; push @have_field_specs, $want_field_specs{$f}; } else { + my $aside= $want_field_specs{$f}; + $aside =~ s/\bUNIQUE\b//i; + $aside =~ s/\bNOT\s*NULL\b//i; + $aside =~ s/\bPRIMARY\s*KEY\b//i; + $aside =~ s/\s+$//; + push @aside_fields, $f; + push @aside_field_specs, $aside; push @need_recreate, "field $f"; } } #----- Do we need to recreate ? ----- - return unless @need_recreate; - # yes: + if (!@need_recreate) { + $table{$table}= $table; + return; + } + #----- Yes, recreate: ----- print " Recreating $table: ", join('; ',@need_recreate); + $table{$table}= "aside_$table"; my $have_fields= join ',', @have_fields; + my $aside_fields= join ',', @have_fields, @aside_fields; my $have_field_specs= join ",\n", @have_field_specs; + my $aside_field_specs= join ",\n", @have_field_specs, @aside_field_specs; db_doall(< $table, + Sql => < commodsortkey($b); + } keys %commods; } +our %posincl; + { - my $insert= $dbh->prepare(<<'END'); - INSERT OR IGNORE INTO commods - (unitmass, - unitvolume, - commodname) - VALUES (?,?,?); -END - my $setsizes= $dbh->prepare(<<'END'); - UPDATE commods - SET unitmass = ?, - unitvolume = ? - WHERE commodname = ? -END - my $setordval= $dbh->prepare(<<'END'); - UPDATE commods - SET ordval = ? - WHERE commodname = ? + my %classorderedcount; + + foreach my $cl (keys %commodclasses) { + $classorderedcount{$cl}= 0; + } + foreach my $commod (commods_ordered()) { + my $cl= $commods{$commod}{Class}; + die "no class for commodity $commod" unless defined $cl; + + my $clid= $commodclasses{$cl}; + die "unknown class $cl for $commod ".(join '|', sort keys %commodclasses) unless defined $clid; + + if (defined $commods{$commod}{Ordval}) { + $posincl{$commod}= ++$classorderedcount{$cl}; + } else { + $posincl{$commod}= 0; + } + } + + db_doall(<prepare(<<'END'); - UPDATE commods - SET commodclass = ? - WHERE commodname = ? + my $addclass= $dbh->prepare(<prepare(<<'END'); - UPDATE commods - SET inclass = ? + foreach my $cl (sort keys %commodclasses) { + my $clname= $cl; + $clname =~ s/_/ /g; + $addclass->execute($commodclasses{$cl}+1, + ucfirst $clname, + $classorderedcount{$cl}); + } +} + +{ + my @valuefields= qw( + unitmass + unitvolume + commodclassid + ordval + posinclass + flags + ); + my $insert= $dbh->prepare(" + INSERT OR IGNORE INTO $table{commods} + ( commodname, + ".join(", + ", @valuefields)." ) + VALUES (?,".join(',', map {'?'} @valuefields).") +"); + my $update= $dbh->prepare(" + UPDATE $table{commods} + SET ".join(", + ", map { "$_ = ?" } @valuefields)." WHERE commodname = ? -END - my %incl; - foreach my $commod (sort { - commodsortkey($a) cmp commodsortkey($b) - } keys %commods) { +"); + foreach my $commod (commods_ordered()) { my $c= $commods{$commod}; die "no mass for $commod" unless defined $c->{Mass}; die "no volume for $commod" unless defined $c->{Volume}; - my @qa= ($c->{Mass}, $c->{Volume}, $commod); - $insert->execute(@qa); - $setsizes->execute(@qa); - $setordval->execute($c->{Ordval} || 0, $commod); my $cl= $c->{Class}; - $setclass->execute($cl, $commod); - - if (defined $c->{Ordval} and defined $cl) { - $incl{$cl}++; - $setinclass->execute($incl{$cl}, $commod); - } elsif (defined $cl) { - $incl{$cl} += 0; - } - } - db_doall(<prepare(<<'END'); - INSERT INTO commodclasses - (commodclass, size) - VALUES (?,?) -END - foreach my $cl (sort keys %incl) { - $addclass->execute($cl, $incl{$cl}); + my $clid= $commodclasses{$cl}+1; + + my @valuevalues= ( + $c->{Mass}, + $c->{Volume}, + $clid, + commodsortkey($commod), + $posincl{$commod}, + $c->{Flags} + ); + $insert->execute($commod, @valuevalues); + $update->execute(@valuevalues, $commod); } - my $search= $dbh->prepare(<<'END'); - SELECT commodname,commodid FROM commods; + my $search= $dbh->prepare(<prepare(<prepare(<<'END'); - DELETE FROM commods WHERE commodid = ? + my $delete= $dbh->prepare(<execute(); my $any=0; @@ -379,15 +423,14 @@ END $delete->execute($row->{'commodid'}); } print ".\n" if $any; - db_check_referential_integrity(); } - #---------- vessel types ---------- { - my $idempotent= $dbh->prepare(<<'END') - INSERT OR REPLACE INTO vessels (name, shot, mass, volume) - VALUES (?,?,?,?) + my $idempotent= $dbh->prepare(<{Table}; + print " Retransferring $tab..."; + + if (!eval { + db_doall($tb->{Sql}); + 1; + }) { + my $emsg= $@; + my $w=20; + print STDERR "\n=== $tab retransfer failed, dumping:\n"; + my $dumph= $dbh->prepare("SELECT * FROM aside_$tab"); + $dumph->execute(); + my @cols= @{ $dumph->{NAME_lc} }; + dumptab_head(\*STDERR,$w,\@cols); + my $row; + while ($row= $dumph->fetchrow_hashref()) { + dumptab_row_hashref(\*STDERR,$w,\@cols,$row); + } + die "\n$emsg"; + } + print "\n"; + $table{$tab}= $tab; +} + +#---------- create indices ---------- + +foreach my $bs (qw(buy sell)) { + db_doall(<{Id}, getminmax($tab,'min',$id), $oldmax, - getminmax("aside_$tab",'max',"new_$id")); + getminmax("idlookup_$tab",'max',"new_$id")); my @updates= @{ $cp->{Updates} }; while (@updates) { my $utabs= shift @updates; @@ -448,8 +529,8 @@ END db_doall(<{AutoCommit} = 1;