]> git.decadent.org.uk Git - dak.git/blob - dak/dakdb/update2.py
update2
[dak.git] / dak / dakdb / update2.py
1 #!/usr/bin/env python
2 # coding=utf8
3
4 # Debian Archive Kit Database Update Script
5 # Copyright © 2008  Michael Casadevall <mcasadevall@debian.org>
6 # Copyright © 2008  Roger Leigh <rleigh@debian.org>
7
8 # This program is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 2 of the License, or
11 # (at your option) any later version.
12
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 # GNU General Public License for more details.
17
18 # You should have received a copy of the GNU General Public License
19 # along with this program; if not, write to the Free Software
20 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21
22 ################################################################################
23
24 import psycopg2, time
25
26 ################################################################################
27
28 def do_update(self):
29     print "Note: to be able to enable the the PL/Perl (plperl) procedural language, we do"
30     print "need postgresql-plperl-$postgres-version installed. Make sure that this is the"
31     print "case before you continue. Interrupt if it isn't, sleeping 5 seconds now."
32     print "(We need to be database superuser for this to work!)"
33     time.sleep (5)
34
35     try:
36         c = self.db.cursor()
37
38         print "Enabling PL/Perl language"
39         c.execute("CREATE LANGUAGE plpgsql;")
40
41         print "Adding debversion type to database."
42
43 # Not present in all databases, maybe PL/Perl version-dependent?
44 #        c.execute("SET SESSION plperl.use_strict TO 't';")
45
46         c.execute("CREATE DOMAIN debversion AS TEXT;")
47         c.execute("COMMENT ON DOMAIN debversion IS 'Debian package version number';")
48
49         c.execute("""ALTER DOMAIN debversion
50                      ADD CONSTRAINT debversion_syntax
51                      CHECK (VALUE !~ '[^-+:.0-9a-zA-Z~]');""")
52
53         # From Dpkg::Version::parseversion
54         c.execute("""CREATE OR REPLACE FUNCTION debversion_split (debversion)
55   RETURNS text[] AS $$
56     my $ver = shift;
57     my %verhash;
58     if ($ver =~ /:/)
59     {
60         $ver =~ /^(\d+):(.+)/ or die "bad version number '$ver'";
61         $verhash{epoch} = $1;
62         $ver = $2;
63     }
64     else
65     {
66         $verhash{epoch} = 0;
67     }
68     if ($ver =~ /(.+)-(.*)$/)
69     {
70         $verhash{version} = $1;
71         $verhash{revision} = $2;
72     }
73     else
74     {
75         $verhash{version} = $ver;
76         $verhash{revision} = 0;
77     }
78
79     return [$verhash{'epoch'}, $verhash{'version'}, $verhash{'revision'}];
80 $$
81   LANGUAGE plperl
82   IMMUTABLE STRICT;""")
83         c.execute("""COMMENT ON FUNCTION debversion_split (debversion)
84                    IS 'Split debian version into epoch, upstream version and revision';""")
85
86         c.execute("""CREATE OR REPLACE FUNCTION debversion_epoch (version debversion)
87   RETURNS text AS $$
88 DECLARE
89   split text[];
90 BEGIN
91   split := debversion_split(version);
92   RETURN split[1];
93 END;
94 $$
95   LANGUAGE plpgsql
96   IMMUTABLE STRICT;
97 COMMENT ON FUNCTION debversion_epoch (debversion)
98   IS 'Get debian version epoch';
99
100 CREATE OR REPLACE FUNCTION debversion_version (version debversion)
101   RETURNS text AS $$
102 DECLARE
103   split text[];
104 BEGIN
105   split := debversion_split(version);
106   RETURN split[2];
107 END;
108 $$
109   LANGUAGE plpgsql
110   IMMUTABLE STRICT;""")
111         c.execute("""COMMENT ON FUNCTION debversion_version (debversion)
112                    IS 'Get debian version upstream version';""")
113
114         c.execute("""CREATE OR REPLACE FUNCTION debversion_revision (version debversion)
115   RETURNS text AS $$
116 DECLARE
117   split text[];
118 BEGIN
119   split := debversion_split(version);
120   RETURN split[3];
121 END;
122 $$
123   LANGUAGE plpgsql
124   IMMUTABLE STRICT;""")
125         c.execute("""COMMENT ON FUNCTION debversion_revision (debversion)
126                    IS 'Get debian version revision';""")
127
128 # From Dpkg::Version::parseversion
129         c.execute("""CREATE OR REPLACE FUNCTION debversion_compare_single (version1 text, version2 text)
130   RETURNS integer AS $$
131      sub order{
132           my ($x) = @_;
133           ##define order(x) ((x) == '~' ? -1 \
134           #           : cisdigit((x)) ? 0 \
135           #           : !(x) ? 0 \
136           #           : cisalpha((x)) ? (x) \
137           #           : (x) + 256)
138           # This comparison is out of dpkg's order to avoid
139           # comparing things to undef and triggering warnings.
140           if (not defined $x or not length $x) {
141                return 0;
142           }
143           elsif ($x eq '~') {
144                return -1;
145           }
146           elsif ($x =~ /^\d$/) {
147                return 0;
148           }
149           elsif ($x =~ /^[A-Z]$/i) {
150                return ord($x);
151           }
152           else {
153                return ord($x) + 256;
154           }
155      }
156
157      sub next_elem(\@){
158           my $a = shift;
159           return @{$a} ? shift @{$a} : undef;
160      }
161      my ($val, $ref) = @_;
162      $val = "" if not defined $val;
163      $ref = "" if not defined $ref;
164      my @val = split //,$val;
165      my @ref = split //,$ref;
166      my $vc = next_elem @val;
167      my $rc = next_elem @ref;
168      while (defined $vc or defined $rc) {
169           my $first_diff = 0;
170           while ((defined $vc and $vc !~ /^\d$/) or
171                  (defined $rc and $rc !~ /^\d$/)) {
172                my $vo = order($vc); my $ro = order($rc);
173                # Unlike dpkg's verrevcmp, we only return 1 or -1 here.
174                return (($vo - $ro > 0) ? 1 : -1) if $vo != $ro;
175                $vc = next_elem @val; $rc = next_elem @ref;
176           }
177           while (defined $vc and $vc eq '0') {
178                $vc = next_elem @val;
179           }
180           while (defined $rc and $rc eq '0') {
181                $rc = next_elem @ref;
182           }
183           while (defined $vc and $vc =~ /^\d$/ and
184                  defined $rc and $rc =~ /^\d$/) {
185                $first_diff = ord($vc) - ord($rc) if !$first_diff;
186                $vc = next_elem @val; $rc = next_elem @ref;
187           }
188           return 1 if defined $vc and $vc =~ /^\d$/;
189           return -1 if defined $rc and $rc =~ /^\d$/;
190           return (($first_diff  > 0) ? 1 : -1) if $first_diff;
191      }
192      return 0;
193 $$
194   LANGUAGE plperl
195   IMMUTABLE STRICT;""")
196         c.execute("""COMMENT ON FUNCTION debversion_compare_single (text, text)
197                    IS 'Compare upstream or revision parts of Debian versions';""")
198
199 # Logic only derived from Dpkg::Version::parseversion
200         c.execute("""CREATE OR REPLACE FUNCTION debversion_compare (version1 debversion, version2 debversion)
201   RETURNS integer AS $$
202 DECLARE
203   split1 text[];
204   split2 text[];
205   result integer;
206 BEGIN
207   result := 0;
208   split1 := debversion_split(version1);
209   split2 := debversion_split(version2);
210
211   -- RAISE NOTICE 'Version 1: %', version1;
212   -- RAISE NOTICE 'Version 2: %', version2;
213   -- RAISE NOTICE 'Split 1: %', split1;
214   -- RAISE NOTICE 'Split 2: %', split2;
215
216   IF split1[1] > split2[1] THEN
217     result := 1;
218   ELSIF split1[1] < split2[1] THEN
219     result := -1;
220   ELSE
221     result := debversion_compare_single(split1[2], split2[2]);
222     IF result = 0 THEN
223       result := debversion_compare_single(split1[3], split2[3]);
224     END IF;
225   END IF;
226
227   RETURN result;
228 END;
229 $$
230   LANGUAGE plpgsql
231   IMMUTABLE STRICT;""")
232         c.execute("""COMMENT ON FUNCTION debversion_compare (debversion, debversion)
233   IS 'Compare Debian versions';""")
234
235         c.execute("""CREATE OR REPLACE FUNCTION debversion_eq (version1 debversion, version2 debversion)
236   RETURNS boolean AS $$
237 DECLARE
238   comp integer;
239   result boolean;
240 BEGIN
241   comp := debversion_compare(version1, version2);
242   result := comp = 0;
243   RETURN result;
244 END;
245 $$
246   LANGUAGE plpgsql
247   IMMUTABLE STRICT;""")
248         c.execute("""COMMENT ON FUNCTION debversion_eq (debversion, debversion)
249   IS 'debversion equal';""")
250
251         c.execute("""CREATE OR REPLACE FUNCTION debversion_ne (version1 debversion, version2 debversion)
252   RETURNS boolean AS $$
253 DECLARE
254   comp integer;
255   result boolean;
256 BEGIN
257   comp := debversion_compare(version1, version2);
258   result := comp <> 0;
259   RETURN result;
260 END;
261 $$
262   LANGUAGE plpgsql
263   IMMUTABLE STRICT;""")
264         c.execute("""COMMENT ON FUNCTION debversion_ne (debversion, debversion)
265   IS 'debversion not equal';""")
266
267         c.execute("""CREATE OR REPLACE FUNCTION debversion_lt (version1 debversion, version2 debversion)
268   RETURNS boolean AS $$
269 DECLARE
270   comp integer;
271   result boolean;
272 BEGIN
273   comp := debversion_compare(version1, version2);
274   result := comp < 0;
275   RETURN result;
276 END;
277 $$
278   LANGUAGE plpgsql
279   IMMUTABLE STRICT;""")
280         c.execute("""COMMENT ON FUNCTION debversion_lt (debversion, debversion)
281                    IS 'debversion less-than';""")
282
283         c.execute("""CREATE OR REPLACE FUNCTION debversion_gt (version1 debversion, version2 debversion) RETURNS boolean AS $$
284 DECLARE
285   comp integer;
286   result boolean;
287 BEGIN
288   comp := debversion_compare(version1, version2);
289   result := comp > 0;
290   RETURN result;
291 END;
292 $$
293   LANGUAGE plpgsql
294   IMMUTABLE STRICT;""")
295         c.execute("""COMMENT ON FUNCTION debversion_gt (debversion, debversion)
296                    IS 'debversion greater-than';""")
297
298         c.execute("""CREATE OR REPLACE FUNCTION debversion_le (version1 debversion, version2 debversion)
299   RETURNS boolean AS $$
300 DECLARE
301   comp integer;
302   result boolean;
303 BEGIN
304   comp := debversion_compare(version1, version2);
305   result := comp <= 0;
306   RETURN result;
307 END;
308 $$
309   LANGUAGE plpgsql
310   IMMUTABLE STRICT;""")
311         c.execute("""COMMENT ON FUNCTION debversion_le (debversion, debversion)
312                    IS 'debversion less-than-or-equal';""")
313
314         c.execute("""CREATE OR REPLACE FUNCTION debversion_ge (version1 debversion, version2 debversion)
315   RETURNS boolean AS $$
316 DECLARE
317   comp integer;
318   result boolean;
319 BEGIN
320   comp := debversion_compare(version1, version2);
321   result := comp >= 0;
322   RETURN result;
323 END;
324 $$
325   LANGUAGE plpgsql
326   IMMUTABLE STRICT;""")
327         c.execute("""COMMENT ON FUNCTION debversion_ge (debversion, debversion)
328                    IS 'debversion greater-than-or-equal';""")
329
330         c.execute("""CREATE OPERATOR = (
331                    PROCEDURE = debversion_eq,
332                    LEFTARG = debversion,
333                    RIGHTARG = debversion,
334                    COMMUTATOR = =,
335                    NEGATOR = !=);""")
336         c.execute("""COMMENT ON OPERATOR = (debversion, debversion)
337                    IS 'debversion equal';""")
338
339         c.execute("""CREATE OPERATOR != (
340                    PROCEDURE = debversion_eq,
341                    LEFTARG = debversion,
342                    RIGHTARG = debversion,
343                    COMMUTATOR = !=,
344                    NEGATOR = =);""")
345         c.execute("""COMMENT ON OPERATOR != (debversion, debversion)
346                    IS 'debversion not equal';""")
347
348         c.execute("""CREATE OPERATOR < (
349                    PROCEDURE = debversion_lt,
350                    LEFTARG = debversion,
351                    RIGHTARG = debversion,
352                    COMMUTATOR = >,
353                    NEGATOR = >=);""")
354         c.execute("""COMMENT ON OPERATOR < (debversion, debversion)
355                    IS 'debversion less-than';""")
356
357         c.execute("""CREATE OPERATOR > (
358                    PROCEDURE = debversion_gt,
359                    LEFTARG = debversion,
360                    RIGHTARG = debversion,
361                    COMMUTATOR = <,
362                    NEGATOR = >=);""")
363         c.execute("""COMMENT ON OPERATOR > (debversion, debversion)
364                    IS 'debversion greater-than';""")
365
366         c.execute("""CREATE OPERATOR <= (
367                    PROCEDURE = debversion_le,
368                    LEFTARG = debversion,
369                    RIGHTARG = debversion,
370                    COMMUTATOR = >=,
371                    NEGATOR = >);""")
372         c.execute("""COMMENT ON OPERATOR <= (debversion, debversion)
373                    IS 'debversion less-than-or-equal';""")
374
375         c.execute("""CREATE OPERATOR >= (
376                    PROCEDURE = debversion_ge,
377                    LEFTARG = debversion,
378                    RIGHTARG = debversion,
379                    COMMUTATOR = <=,
380                    NEGATOR = <);""")
381         c.execute("""COMMENT ON OPERATOR >= (debversion, debversion)
382                    IS 'debversion greater-than-or-equal';""")
383
384         c.execute("ALTER TABLE source ALTER COLUMN version TYPE debversion;")
385         c.execute("ALTER TABLE binaries ALTER COLUMN version TYPE debversion;")
386
387         c.execute("UPDATE config SET value = '2' WHERE name = 'db_revision'")
388
389         self.db.commit()
390
391     except psycopg2.ProgrammingError, msg:
392         self.db.rollback()
393         print "FATAL: Unable to apply debversion table update 2!"
394         print "Error Message: " + str(msg)
395         print "Database changes have been rolled back."