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