update: Leave checking file existence to the report script.
[dvddb] / update
CommitLineData
14acb11f
MW
1#! /usr/bin/perl -w
2
3use open ":utf8";
4use strict;
5
6use DBI;
7
8BEGIN {
9 binmode STDIN, ":utf8";
10 binmode STDOUT, ":utf8";
11 binmode STDERR, ":utf8";
12}
13
14my $ROOT = "/mnt/dvd/archive";
15my $DB = DBI->connect("dbi:Pg:host=roadstar", "", "",
16 { AutoCommit => 0,
17 RaiseError => 1 });
18
19my $st_get_set = $DB->prepare("SELECT name, ndisc FROM dvd_set
20 WHERE id = ?");
21my $st_add_set = $DB->prepare("INSERT INTO dvd_set (name, ndisc)
22 VALUES (?, ?)
23 RETURNING id");
24my $st_update_set = $DB->prepare("UPDATE dvd_set
25 SET name = ?, ndisc = ?
26 WHERE id = ?");
27my $st_delete_set = $DB->prepare("DELETE FROM dvd_set WHERE id = ?");
28
29my $st_get_discs = $DB->prepare("SELECT disc, path FROM dvd_disc
30 WHERE set_id = ? AND ? <= disc AND disc < ?
31 ORDER BY disc");
32my $st_add_disc = $DB->prepare("INSERT INTO dvd_disc (set_id, disc, path)
33 VALUES (?, ?, ?)");
34my $st_update_disc = $DB->prepare("UPDATE dvd_disc SET path = ?
35 WHERE set_id = ? AND disc = ?");
36my $st_delete_disc_range = $DB->prepare("DELETE FROM dvd_disc
37 WHERE set_id = ? AND
38 ? <= disc AND disc < ?");
39my $st_delete_discs = $DB->prepare("DELETE FROM dvd_disc WHERE set_id = ?");
40
41my ($id, $name, $ndisc) = (undef, undef, -1);
42my @path;
43
44sub flush_set () {
45 defined $id or return;
46
47 ##print ";; flush set: #$id: $ndisc\n";
48 ##for my $p (@path) { print ";;\t$p\n"; }
49
50 if ($ndisc eq "*") { $ndisc = @path; }
51 elsif (@path != $ndisc)
52 { die sprintf "wrong number of discs %d /= %d", scalar @path, $ndisc; }
53
54 my $min_ndisc;
55 if ($id eq "UNK") {
56 $id = undef; @path = ();
57 return;
58 } elsif ($id eq "NEW") {
59 $st_add_set->execute($name, $ndisc);
60 ($id) = $st_add_set->fetchrow_array; $st_add_set->finish;
61 $min_ndisc = 0;
62 } else {
63 $st_get_set->execute($id);
64 my ($old_name, $old_ndisc) = $st_get_set->fetchrow_array;
65 $st_get_set->finish;
66 $name ne $old_name || $ndisc ne $old_ndisc and
67 $st_update_set->execute($name, $ndisc, $id);
68
69 $min_ndisc = $ndisc < $old_ndisc ? $ndisc : $old_ndisc;
70 $st_get_discs->execute($id, 0, $min_ndisc);
71 my $i = 0;
72 DISC: for (;;) {
73 my @r = $st_get_discs->fetchrow_array; last DISC unless @r;
74 my ($disc, $old_path) = @r;
75 $disc == $i or die "unexpected disc number";
76 my $path = $path[$i++];
77 if (defined $path && (!defined $old_path || $path ne $old_path))
78 { $st_update_disc->execute($path, $id, $disc); }
79 }
80 $i == $min_ndisc or die "missing disc records";
81
82 $min_ndisc < $old_ndisc and
83 $st_delete_disc_range->execute($id, $min_ndisc, $old_ndisc);
84 }
85
86 for (my $i = $min_ndisc; $i < $ndisc; $i++)
87 { $st_add_disc->execute($id, $i, $path[$i]); }
88
89 $id = undef; @path = ();
90}
91
92LINE: while (<>) {
93 chomp;
94
95 if (/^ \[ \# (\d+ | NEW | UNK) \s* : \s* (\d+ | \* | DEL) ]
96 \s* (\S .*)? $/x) {
97 flush_set;
98
99 ($id, $ndisc, $name) = ($1, $2, $3);
100 if ($ndisc eq "DEL") {
101 $id eq "NEW" || $id eq "UNK" and die "can't delete virtual records";
102 defined $name and die "name `$name' supplied with deletion request";
103 $st_delete_discs->execute($id);
104 $st_delete_set->execute($id);
105 $id = undef;
106 } elsif ($id eq "UNK") {
107 defined $name and die "can't name unknown records";
108 } else {
109 defined $name or die "missing name";
110 }
75a5b924 111 } elsif (/^ \s+ (?: !! \s*)? (\S .*) $/x) {
14acb11f
MW
112 my $path = $1;
113 defined $id or die "no active set";
14acb11f
MW
114 push @path, $path;
115 } elsif (/^ .* \S .* $/) {
116 die "unrecognized line `$_'";
117 }
118}
119
120$DB->commit; $DB->disconnect;