X-Git-Url: https://git.decadent.org.uk/gitweb/?a=blobdiff_plain;f=dak%2Fdakdb%2Fupdate2.py;fp=dak%2Fdakdb%2Fupdate2.py;h=0cf747e923a3786f80306e9e44ce50be2b846a46;hb=f71ac27c75a8ab5185508491e97bc6f237772aa6;hp=ec9650b1e8987a557b908d1927fb74fe32a99267;hpb=2288ab34223700a1369905abe2c4c5593241c461;p=dak.git diff --git a/dak/dakdb/update2.py b/dak/dakdb/update2.py old mode 100644 new mode 100755 index ec9650b1..0cf747e9 --- a/dak/dakdb/update2.py +++ b/dak/dakdb/update2.py @@ -1,7 +1,9 @@ #!/usr/bin/env python +# coding=utf8 -# Debian Archive Kit Database Update Script 2 -# Copyright (C) 2009 Michael Casadevall +# Debian Archive Kit Database Update Script +# Copyright © 2008 Michael Casadevall +# Copyright © 2008 Roger Leigh # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -19,62 +21,378 @@ ################################################################################ -# really, if we want to screw ourselves, let's find a better way. -# rm -rf /srv/ftp.debian.org - -################################################################################ - import psycopg2, time ################################################################################ def do_update(self): - print "Adding content fields to database" +vvvvvvvvvvvvvvvvvvvv + print "Note: to be able to enable the the PL/Perl (plperl) procedural language, we do" + print "need postgresql-plperl-$postgres-version installed. Make sure that this is the" + print "case before you continue. Interrupt if it isn't, sleeping 5 seconds now." + print "(We need to be database superuser for this to work!)" + time.sleep (5) +^^^^^^^^^^^^^^^^^^^^ try: c = self.db.cursor() - c.execute("""CREATE TABLE content_file_paths ( - id serial primary key not null, - path text unique not null - )""") - - c.execute("""CREATE TABLE content_file_names ( - id serial primary key not null, - file text unique not null - )""") - - c.execute("""CREATE TABLE content_associations ( - id serial not null, - binary_pkg int4 not null references binaries(id) on delete cascade, - filepath int4 not null references content_file_paths(id) on delete cascade, - filename int4 not null references content_file_names(id) on delete cascade - );""") - - c.execute("""CREATE FUNCTION comma_concat(text, text) RETURNS text - AS $_$select case - WHEN $2 is null or $2 = '' THEN $1 - WHEN $1 is null or $1 = '' THEN $2 - ELSE $1 || ',' || $2 - END$_$ - LANGUAGE sql""") - - c.execute("""CREATE AGGREGATE comma_separated_list ( - BASETYPE = text, - SFUNC = comma_concat, - STYPE = text, - INITCOND = '' - );""") + + print "Enabling PL/Perl language" + c.execute("CREATE LANGUAGE plperl;") + c.execute("CREATE LANGUAGE plpgsql;") + + print "Adding debversion type to database." + +# Not present in all databases, maybe PL/Perl version-dependent? +# c.execute("SET SESSION plperl.use_strict TO 't';") + + c.execute("CREATE DOMAIN debversion AS TEXT;") + c.execute("COMMENT ON DOMAIN debversion IS 'Debian package version number';") + + c.execute("""ALTER DOMAIN debversion + ADD CONSTRAINT debversion_syntax + CHECK (VALUE !~ '[^-+:.0-9a-zA-Z~]');""") + + # From Dpkg::Version::parseversion + c.execute("""CREATE OR REPLACE FUNCTION debversion_split (debversion) + RETURNS text[] AS $$ + my $ver = shift; + my %verhash; + if ($ver =~ /:/) + { + $ver =~ /^(\d+):(.+)/ or die "bad version number '$ver'"; + $verhash{epoch} = $1; + $ver = $2; + } + else + { + $verhash{epoch} = 0; + } + if ($ver =~ /(.+)-(.*)$/) + { + $verhash{version} = $1; + $verhash{revision} = $2; + } + else + { + $verhash{version} = $ver; + $verhash{revision} = 0; + } + + return [$verhash{'epoch'}, $verhash{'version'}, $verhash{'revision'}]; +$$ + LANGUAGE plperl + IMMUTABLE STRICT;""") + c.execute("""COMMENT ON FUNCTION debversion_split (debversion) + IS 'Split debian version into epoch, upstream version and revision';""") + + c.execute("""CREATE OR REPLACE FUNCTION debversion_epoch (version debversion) + RETURNS text AS $$ +DECLARE + split text[]; +BEGIN + split := debversion_split(version); + RETURN split[1]; +END; +$$ + LANGUAGE plpgsql + IMMUTABLE STRICT; +COMMENT ON FUNCTION debversion_epoch (debversion) + IS 'Get debian version epoch'; + +CREATE OR REPLACE FUNCTION debversion_version (version debversion) + RETURNS text AS $$ +DECLARE + split text[]; +BEGIN + split := debversion_split(version); + RETURN split[2]; +END; +$$ + LANGUAGE plpgsql + IMMUTABLE STRICT;""") + c.execute("""COMMENT ON FUNCTION debversion_version (debversion) + IS 'Get debian version upstream version';""") + + c.execute("""CREATE OR REPLACE FUNCTION debversion_revision (version debversion) + RETURNS text AS $$ +DECLARE + split text[]; +BEGIN + split := debversion_split(version); + RETURN split[3]; +END; +$$ + LANGUAGE plpgsql + IMMUTABLE STRICT;""") + c.execute("""COMMENT ON FUNCTION debversion_revision (debversion) + IS 'Get debian version revision';""") + +# From Dpkg::Version::parseversion + c.execute("""CREATE OR REPLACE FUNCTION debversion_compare_single (version1 text, version2 text) + RETURNS integer AS $$ + sub order{ + my ($x) = @_; + ##define order(x) ((x) == '~' ? -1 \ + # : cisdigit((x)) ? 0 \ + # : !(x) ? 0 \ + # : cisalpha((x)) ? (x) \ + # : (x) + 256) + # This comparison is out of dpkg's order to avoid + # comparing things to undef and triggering warnings. + if (not defined $x or not length $x) { + return 0; + } + elsif ($x eq '~') { + return -1; + } + elsif ($x =~ /^\d$/) { + return 0; + } + elsif ($x =~ /^[A-Z]$/i) { + return ord($x); + } + else { + return ord($x) + 256; + } + } + + sub next_elem(\@){ + my $a = shift; + return @{$a} ? shift @{$a} : undef; + } + my ($val, $ref) = @_; + $val = "" if not defined $val; + $ref = "" if not defined $ref; + my @val = split //,$val; + my @ref = split //,$ref; + my $vc = next_elem @val; + my $rc = next_elem @ref; + while (defined $vc or defined $rc) { + my $first_diff = 0; + while ((defined $vc and $vc !~ /^\d$/) or + (defined $rc and $rc !~ /^\d$/)) { + my $vo = order($vc); my $ro = order($rc); + # Unlike dpkg's verrevcmp, we only return 1 or -1 here. + return (($vo - $ro > 0) ? 1 : -1) if $vo != $ro; + $vc = next_elem @val; $rc = next_elem @ref; + } + while (defined $vc and $vc eq '0') { + $vc = next_elem @val; + } + while (defined $rc and $rc eq '0') { + $rc = next_elem @ref; + } + while (defined $vc and $vc =~ /^\d$/ and + defined $rc and $rc =~ /^\d$/) { + $first_diff = ord($vc) - ord($rc) if !$first_diff; + $vc = next_elem @val; $rc = next_elem @ref; + } + return 1 if defined $vc and $vc =~ /^\d$/; + return -1 if defined $rc and $rc =~ /^\d$/; + return (($first_diff > 0) ? 1 : -1) if $first_diff; + } + return 0; +$$ + LANGUAGE plperl + IMMUTABLE STRICT;""") + c.execute("""COMMENT ON FUNCTION debversion_compare_single (text, text) + IS 'Compare upstream or revision parts of Debian versions';""") + +# Logic only derived from Dpkg::Version::parseversion + c.execute("""CREATE OR REPLACE FUNCTION debversion_compare (version1 debversion, version2 debversion) + RETURNS integer AS $$ +DECLARE + split1 text[]; + split2 text[]; + result integer; +BEGIN + result := 0; + split1 := debversion_split(version1); + split2 := debversion_split(version2); + + -- RAISE NOTICE 'Version 1: %', version1; + -- RAISE NOTICE 'Version 2: %', version2; + -- RAISE NOTICE 'Split 1: %', split1; + -- RAISE NOTICE 'Split 2: %', split2; + + IF split1[1] > split2[1] THEN + result := 1; + ELSIF split1[1] < split2[1] THEN + result := -1; + ELSE + result := debversion_compare_single(split1[2], split2[2]); + IF result = 0 THEN + result := debversion_compare_single(split1[3], split2[3]); + END IF; + END IF; + + RETURN result; +END; +$$ + LANGUAGE plpgsql + IMMUTABLE STRICT;""") + c.execute("""COMMENT ON FUNCTION debversion_compare (debversion, debversion) + IS 'Compare Debian versions';""") + + c.execute("""CREATE OR REPLACE FUNCTION debversion_eq (version1 debversion, version2 debversion) + RETURNS boolean AS $$ +DECLARE + comp integer; + result boolean; +BEGIN + comp := debversion_compare(version1, version2); + result := comp = 0; + RETURN result; +END; +$$ + LANGUAGE plpgsql + IMMUTABLE STRICT;""") + c.execute("""COMMENT ON FUNCTION debversion_eq (debversion, debversion) + IS 'debversion equal';""") + + c.execute("""CREATE OR REPLACE FUNCTION debversion_ne (version1 debversion, version2 debversion) + RETURNS boolean AS $$ +DECLARE + comp integer; + result boolean; +BEGIN + comp := debversion_compare(version1, version2); + result := comp <> 0; + RETURN result; +END; +$$ + LANGUAGE plpgsql + IMMUTABLE STRICT;""") + c.execute("""COMMENT ON FUNCTION debversion_ne (debversion, debversion) + IS 'debversion not equal';""") + + c.execute("""CREATE OR REPLACE FUNCTION debversion_lt (version1 debversion, version2 debversion) + RETURNS boolean AS $$ +DECLARE + comp integer; + result boolean; +BEGIN + comp := debversion_compare(version1, version2); + result := comp < 0; + RETURN result; +END; +$$ + LANGUAGE plpgsql + IMMUTABLE STRICT;""") + c.execute("""COMMENT ON FUNCTION debversion_lt (debversion, debversion) + IS 'debversion less-than';""") + + c.execute("""CREATE OR REPLACE FUNCTION debversion_gt (version1 debversion, version2 debversion) RETURNS boolean AS $$ +DECLARE + comp integer; + result boolean; +BEGIN + comp := debversion_compare(version1, version2); + result := comp > 0; + RETURN result; +END; +$$ + LANGUAGE plpgsql + IMMUTABLE STRICT;""") + c.execute("""COMMENT ON FUNCTION debversion_gt (debversion, debversion) + IS 'debversion greater-than';""") + + c.execute("""CREATE OR REPLACE FUNCTION debversion_le (version1 debversion, version2 debversion) + RETURNS boolean AS $$ +DECLARE + comp integer; + result boolean; +BEGIN + comp := debversion_compare(version1, version2); + result := comp <= 0; + RETURN result; +END; +$$ + LANGUAGE plpgsql + IMMUTABLE STRICT;""") + c.execute("""COMMENT ON FUNCTION debversion_le (debversion, debversion) + IS 'debversion less-than-or-equal';""") + + c.execute("""CREATE OR REPLACE FUNCTION debversion_ge (version1 debversion, version2 debversion) + RETURNS boolean AS $$ +DECLARE + comp integer; + result boolean; +BEGIN + comp := debversion_compare(version1, version2); + result := comp >= 0; + RETURN result; +END; +$$ + LANGUAGE plpgsql + IMMUTABLE STRICT;""") + c.execute("""COMMENT ON FUNCTION debversion_ge (debversion, debversion) + IS 'debversion greater-than-or-equal';""") + + c.execute("""CREATE OPERATOR = ( + PROCEDURE = debversion_eq, + LEFTARG = debversion, + RIGHTARG = debversion, + COMMUTATOR = =, + NEGATOR = !=);""") + c.execute("""COMMENT ON OPERATOR = (debversion, debversion) + IS 'debversion equal';""") + + c.execute("""CREATE OPERATOR != ( + PROCEDURE = debversion_eq, + LEFTARG = debversion, + RIGHTARG = debversion, + COMMUTATOR = !=, + NEGATOR = =);""") + c.execute("""COMMENT ON OPERATOR != (debversion, debversion) + IS 'debversion not equal';""") + + c.execute("""CREATE OPERATOR < ( + PROCEDURE = debversion_lt, + LEFTARG = debversion, + RIGHTARG = debversion, + COMMUTATOR = >, + NEGATOR = >=);""") + c.execute("""COMMENT ON OPERATOR < (debversion, debversion) + IS 'debversion less-than';""") + + c.execute("""CREATE OPERATOR > ( + PROCEDURE = debversion_gt, + LEFTARG = debversion, + RIGHTARG = debversion, + COMMUTATOR = <, + NEGATOR = >=);""") + c.execute("""COMMENT ON OPERATOR > (debversion, debversion) + IS 'debversion greater-than';""") + + c.execute("""CREATE OPERATOR <= ( + PROCEDURE = debversion_le, + LEFTARG = debversion, + RIGHTARG = debversion, + COMMUTATOR = >=, + NEGATOR = >);""") + c.execute("""COMMENT ON OPERATOR <= (debversion, debversion) + IS 'debversion less-than-or-equal';""") + + c.execute("""CREATE OPERATOR >= ( + PROCEDURE = debversion_ge, + LEFTARG = debversion, + RIGHTARG = debversion, + COMMUTATOR = <=, + NEGATOR = <);""") + c.execute("""COMMENT ON OPERATOR >= (debversion, debversion) + IS 'debversion greater-than-or-equal';""") + + c.execute("ALTER TABLE source ALTER COLUMN version TYPE debversion;") + c.execute("ALTER TABLE binaries ALTER COLUMN version TYPE debversion;") c.execute("UPDATE config SET value = '2' WHERE name = 'db_revision'") - self.db.commit() - print "REMINDER: Remember to fully regenerate the Contents files before running import-contents" - print "" - print "Pausing for five seconds ..." - time.sleep (5) + self.db.commit() except psycopg2.ProgrammingError, msg: self.db.rollback() - print "FATAL: Unable to apply content table update 2!" + print "FATAL: Unable to apply debversion table update 2!" print "Error Message: " + str(msg) print "Database changes have been rolled back."