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