]> git.decadent.org.uk Git - dak.git/blob - dak/dakdb/update2.py
Add update2 to create debversion type
[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 the PL/Perl (plperl) procedural language must be enabled first."
30     print "Run 'createlang plpgsql projectb' to add it."
31
32     try:
33         c = self.db.cursor()
34
35         print "Adding debversion type to database."
36
37 # Not present in all databases, maybe PL/Perl version-dependent?
38 #        c.execute("SET SESSION plperl.use_strict TO 't';")
39
40         c.execute("CREATE DOMAIN debversion AS TEXT;")
41         c.execute("COMMENT ON DOMAIN debversion IS 'Debian package version number';")
42
43         c.execute("""ALTER DOMAIN debversion
44                      ADD CONSTRAINT debversion_syntax
45                      CHECK (VALUE !~ '[^-+:.0-9a-zA-Z~]');""")
46
47         # From Dpkg::Version::parseversion
48         c.execute("""CREATE OR REPLACE FUNCTION debversion_split (debversion)
49   RETURNS text[] AS $$
50     my $ver = shift;
51     my %verhash;
52     if ($ver =~ /:/)
53     {
54         $ver =~ /^(\d+):(.+)/ or die "bad version number '$ver'";
55         $verhash{epoch} = $1;
56         $ver = $2;
57     }
58     else
59     {
60         $verhash{epoch} = 0;
61     }
62     if ($ver =~ /(.+)-(.*)$/)
63     {
64         $verhash{version} = $1;
65         $verhash{revision} = $2;
66     }
67     else
68     {
69         $verhash{version} = $ver;
70         $verhash{revision} = 0;
71     }
72
73     return [$verhash{'epoch'}, $verhash{'version'}, $verhash{'revision'}];
74 $$
75   LANGUAGE plperl
76   IMMUTABLE STRICT;""")
77         c.execute("""COMMENT ON FUNCTION debversion_split (debversion)
78                    IS 'Split debian version into epoch, upstream version and revision';""")
79
80         c.execute("""CREATE OR REPLACE FUNCTION debversion_epoch (version debversion)
81   RETURNS text AS $$
82 DECLARE
83   split text[];
84 BEGIN
85   split := debversion_split(version);
86   RETURN split[1];
87 END;
88 $$
89   LANGUAGE plpgsql
90   IMMUTABLE STRICT;
91 COMMENT ON FUNCTION debversion_epoch (debversion)
92   IS 'Get debian version epoch';
93
94 CREATE OR REPLACE FUNCTION debversion_version (version debversion)
95   RETURNS text AS $$
96 DECLARE
97   split text[];
98 BEGIN
99   split := debversion_split(version);
100   RETURN split[2];
101 END;
102 $$
103   LANGUAGE plpgsql
104   IMMUTABLE STRICT;""")
105         c.execute("""COMMENT ON FUNCTION debversion_version (debversion)
106                    IS 'Get debian version upstream version';""")
107
108         c.execute("""CREATE OR REPLACE FUNCTION debversion_revision (version debversion)
109   RETURNS text AS $$
110 DECLARE
111   split text[];
112 BEGIN
113   split := debversion_split(version);
114   RETURN split[3];
115 END;
116 $$
117   LANGUAGE plpgsql
118   IMMUTABLE STRICT;""")
119         c.execute("""COMMENT ON FUNCTION debversion_revision (debversion)
120                    IS 'Get debian version revision';""")
121
122 # From Dpkg::Version::parseversion
123         c.execute("""CREATE OR REPLACE FUNCTION debversion_compare_single (version1 text, version2 text)
124   RETURNS integer AS $$
125      sub order{
126           my ($x) = @_;
127           ##define order(x) ((x) == '~' ? -1 \
128           #           : cisdigit((x)) ? 0 \
129           #           : !(x) ? 0 \
130           #           : cisalpha((x)) ? (x) \
131           #           : (x) + 256)
132           # This comparison is out of dpkg's order to avoid
133           # comparing things to undef and triggering warnings.
134           if (not defined $x or not length $x) {
135                return 0;
136           }
137           elsif ($x eq '~') {
138                return -1;
139           }
140           elsif ($x =~ /^\d$/) {
141                return 0;
142           }
143           elsif ($x =~ /^[A-Z]$/i) {
144                return ord($x);
145           }
146           else {
147                return ord($x) + 256;
148           }
149      }
150
151      sub next_elem(\@){
152           my $a = shift;
153           return @{$a} ? shift @{$a} : undef;
154      }
155      my ($val, $ref) = @_;
156      $val = "" if not defined $val;
157      $ref = "" if not defined $ref;
158      my @val = split //,$val;
159      my @ref = split //,$ref;
160      my $vc = next_elem @val;
161      my $rc = next_elem @ref;
162      while (defined $vc or defined $rc) {
163           my $first_diff = 0;
164           while ((defined $vc and $vc !~ /^\d$/) or
165                  (defined $rc and $rc !~ /^\d$/)) {
166                my $vo = order($vc); my $ro = order($rc);
167                # Unlike dpkg's verrevcmp, we only return 1 or -1 here.
168                return (($vo - $ro > 0) ? 1 : -1) if $vo != $ro;
169                $vc = next_elem @val; $rc = next_elem @ref;
170           }
171           while (defined $vc and $vc eq '0') {
172                $vc = next_elem @val;
173           }
174           while (defined $rc and $rc eq '0') {
175                $rc = next_elem @ref;
176           }
177           while (defined $vc and $vc =~ /^\d$/ and
178                  defined $rc and $rc =~ /^\d$/) {
179                $first_diff = ord($vc) - ord($rc) if !$first_diff;
180                $vc = next_elem @val; $rc = next_elem @ref;
181           }
182           return 1 if defined $vc and $vc =~ /^\d$/;
183           return -1 if defined $rc and $rc =~ /^\d$/;
184           return (($first_diff  > 0) ? 1 : -1) if $first_diff;
185      }
186      return 0;
187 $$
188   LANGUAGE plperl
189   IMMUTABLE STRICT;""")
190         c.execute("""COMMENT ON FUNCTION debversion_compare_single (text, text)
191                    IS 'Compare upstream or revision parts of Debian versions';""")
192
193 # Logic only derived from Dpkg::Version::parseversion
194         c.execute("""CREATE OR REPLACE FUNCTION debversion_compare (version1 debversion, version2 debversion)
195   RETURNS integer AS $$
196 DECLARE
197   split1 text[];
198   split2 text[];
199   result integer;
200 BEGIN
201   result := 0;
202   split1 := debversion_split(version1);
203   split2 := debversion_split(version2);
204
205   -- RAISE NOTICE 'Version 1: %', version1;
206   -- RAISE NOTICE 'Version 2: %', version2;
207   -- RAISE NOTICE 'Split 1: %', split1;
208   -- RAISE NOTICE 'Split 2: %', split2;
209
210   IF split1[1] > split2[1] THEN
211     result := 1;
212   ELSIF split1[1] < split2[1] THEN
213     result := -1;
214   ELSE
215     result := debversion_compare_single(split1[2], split2[2]);
216     IF result = 0 THEN
217       result := debversion_compare_single(split1[3], split2[3]);
218     END IF;
219   END IF;
220
221   RETURN result;
222 END;
223 $$
224   LANGUAGE plpgsql
225   IMMUTABLE STRICT;""")
226         c.execute("""COMMENT ON FUNCTION debversion_compare (debversion, debversion)
227   IS 'Compare Debian versions';""")
228
229         c.execute("""CREATE OR REPLACE FUNCTION debversion_eq (version1 debversion, version2 debversion)
230   RETURNS boolean AS $$
231 DECLARE
232   comp integer;
233   result boolean;
234 BEGIN
235   comp := debversion_compare(version1, version2);
236   result := comp = 0;
237   RETURN result;
238 END;
239 $$
240   LANGUAGE plpgsql
241   IMMUTABLE STRICT;""")
242         c.execute("""COMMENT ON FUNCTION debversion_eq (debversion, debversion)
243   IS 'debversion equal';""")
244
245         c.execute("""CREATE OR REPLACE FUNCTION debversion_ne (version1 debversion, version2 debversion)
246   RETURNS boolean AS $$
247 DECLARE
248   comp integer;
249   result boolean;
250 BEGIN
251   comp := debversion_compare(version1, version2);
252   result := comp <> 0;
253   RETURN result;
254 END;
255 $$
256   LANGUAGE plpgsql
257   IMMUTABLE STRICT;""")
258         c.execute("""COMMENT ON FUNCTION debversion_ne (debversion, debversion)
259   IS 'debversion not equal';""")
260
261         c.execute("""CREATE OR REPLACE FUNCTION debversion_lt (version1 debversion, version2 debversion)
262   RETURNS boolean AS $$
263 DECLARE
264   comp integer;
265   result boolean;
266 BEGIN
267   comp := debversion_compare(version1, version2);
268   result := comp < 0;
269   RETURN result;
270 END;
271 $$
272   LANGUAGE plpgsql
273   IMMUTABLE STRICT;""")
274         c.execute("""COMMENT ON FUNCTION debversion_lt (debversion, debversion)
275                    IS 'debversion less-than';""")
276
277         c.execute("""CREATE OR REPLACE FUNCTION debversion_gt (version1 debversion, version2 debversion) RETURNS boolean AS $$
278 DECLARE
279   comp integer;
280   result boolean;
281 BEGIN
282   comp := debversion_compare(version1, version2);
283   result := comp > 0;
284   RETURN result;
285 END;
286 $$
287   LANGUAGE plpgsql
288   IMMUTABLE STRICT;""")
289         c.execute("""COMMENT ON FUNCTION debversion_gt (debversion, debversion)
290                    IS 'debversion greater-than';""")
291
292         c.execute("""CREATE OR REPLACE FUNCTION debversion_le (version1 debversion, version2 debversion)
293   RETURNS boolean AS $$
294 DECLARE
295   comp integer;
296   result boolean;
297 BEGIN
298   comp := debversion_compare(version1, version2);
299   result := comp <= 0;
300   RETURN result;
301 END;
302 $$
303   LANGUAGE plpgsql
304   IMMUTABLE STRICT;""")
305         c.execute("""COMMENT ON FUNCTION debversion_le (debversion, debversion)
306                    IS 'debversion less-than-or-equal';""")
307
308         c.execute("""CREATE OR REPLACE FUNCTION debversion_ge (version1 debversion, version2 debversion)
309   RETURNS boolean AS $$
310 DECLARE
311   comp integer;
312   result boolean;
313 BEGIN
314   comp := debversion_compare(version1, version2);
315   result := comp >= 0;
316   RETURN result;
317 END;
318 $$
319   LANGUAGE plpgsql
320   IMMUTABLE STRICT;""")
321         c.execute("""COMMENT ON FUNCTION debversion_ge (debversion, debversion)
322                    IS 'debversion greater-than-or-equal';""")
323
324         c.execute("""CREATE OPERATOR = (
325                    PROCEDURE = debversion_eq,
326                    LEFTARG = debversion,
327                    RIGHTARG = debversion,
328                    COMMUTATOR = =,
329                    NEGATOR = !=);""")
330         c.execute("""COMMENT ON OPERATOR = (debversion, debversion)
331                    IS 'debversion equal';""")
332
333         c.execute("""CREATE OPERATOR != (
334                    PROCEDURE = debversion_eq,
335                    LEFTARG = debversion,
336                    RIGHTARG = debversion,
337                    COMMUTATOR = !=,
338                    NEGATOR = =);""")
339         c.execute("""COMMENT ON OPERATOR != (debversion, debversion)
340                    IS 'debversion not equal';""")
341
342         c.execute("""CREATE OPERATOR < (
343                    PROCEDURE = debversion_lt,
344                    LEFTARG = debversion,
345                    RIGHTARG = debversion,
346                    COMMUTATOR = >,
347                    NEGATOR = >=);""")
348         c.execute("""COMMENT ON OPERATOR < (debversion, debversion)
349                    IS 'debversion less-than';""")
350
351         c.execute("""CREATE OPERATOR > (
352                    PROCEDURE = debversion_gt,
353                    LEFTARG = debversion,
354                    RIGHTARG = debversion,
355                    COMMUTATOR = <,
356                    NEGATOR = >=);""")
357         c.execute("""COMMENT ON OPERATOR > (debversion, debversion)
358                    IS 'debversion greater-than';""")
359
360         c.execute("""CREATE OPERATOR <= (
361                    PROCEDURE = debversion_le,
362                    LEFTARG = debversion,
363                    RIGHTARG = debversion,
364                    COMMUTATOR = >=,
365                    NEGATOR = >);""")
366         c.execute("""COMMENT ON OPERATOR <= (debversion, debversion)
367                    IS 'debversion less-than-or-equal';""")
368
369         c.execute("""CREATE OPERATOR >= (
370                    PROCEDURE = debversion_ge,
371                    LEFTARG = debversion,
372                    RIGHTARG = debversion,
373                    COMMUTATOR = <=,
374                    NEGATOR = <);""")
375         c.execute("""COMMENT ON OPERATOR >= (debversion, debversion)
376                    IS 'debversion greater-than-or-equal';""")
377
378         c.execute("ALTER TABLE source ALTER COLUMN version TYPE debversion;")
379         c.execute("ALTER TABLE binaries ALTER COLUMN version TYPE debversion;")
380
381         c.execute("UPDATE config SET value = '1' WHERE name = 'db_revision'")
382
383         self.db.commit()
384
385     except psycopg2.ProgrammingError, msg:
386         self.db.rollback()
387         print "FATAL: Unable to apply debversion table update 2!"
388         print "Error Message: " + str(msg)
389         print "Database changes have been rolled back."