]> git.decadent.org.uk Git - dak.git/blob - dak/dakdb/update28.py
unify buildd queues, no matter which suite
[dak.git] / dak / dakdb / update28.py
1 #!/usr/bin/env python
2 # coding=utf8
3
4 """
5 keep contents of binary packages in tables so we can generate contents.gz files from dak
6
7 @contact: Debian FTP Master <ftpmaster@debian.org>
8 @copyright: 2009  Mike O'Connor <stew@debian.org>
9 @license: GNU General Public License version 2 or later
10 """
11
12 # This program is free software; you can redistribute it and/or modify
13 # it under the terms of the GNU General Public License as published by
14 # the Free Software Foundation; either version 2 of the License, or
15 # (at your option) any later version.
16
17 # This program is distributed in the hope that it will be useful,
18 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 # GNU General Public License for more details.
21
22 # You should have received a copy of the GNU General Public License
23 # along with this program; if not, write to the Free Software
24 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25
26 ################################################################################
27
28
29 ################################################################################
30
31 import psycopg2
32 import time
33 from daklib.dak_exceptions import DBUpdateError
34 from daklib.config import Config
35 import string
36
37 ################################################################################
38
39 def _suites():
40     """
41     return a list of suites to operate on
42     """
43     suites = Config().SubTree("Suite").List()
44     return suites
45
46 def arches(cursor, suite):
47     """
48     return a list of archs to operate on
49     """
50     arch_list = []
51     cursor.execute("""SELECT s.architecture, a.arch_string
52     FROM suite_architectures s
53     JOIN architecture a ON (s.architecture=a.id)
54     WHERE suite = '%s'""" % suite)
55
56     while True:
57         r = cursor.fetchone()
58         if not r:
59             break
60
61         if r[1] != "source" and r[1] != "all":
62             arch_list.append((r[0], r[1]))
63
64     return arch_list
65
66 def do_update(self):
67     """
68     Adding contents table as first step to maybe, finally getting rid
69     of apt-ftparchive
70     """
71
72     print __doc__
73
74     try:
75         c = self.db.cursor()
76
77         c.execute("""CREATE TABLE pending_bin_contents (
78         id serial NOT NULL,
79         package text NOT NULL,
80         version debversion NOT NULL,
81         arch int NOT NULL,
82         filename text NOT NULL,
83         type int NOT NULL,
84         PRIMARY KEY(id))""" );
85
86         c.execute("""CREATE TABLE deb_contents (
87         filename text,
88         section text,
89         package text,
90         binary_id integer,
91         arch integer,
92         suite integer)""" )
93
94         c.execute("""CREATE TABLE udeb_contents (
95         filename text,
96         section text,
97         package text,
98         binary_id integer,
99         suite integer,
100         arch integer)""" )
101
102         c.execute("""ALTER TABLE ONLY deb_contents
103         ADD CONSTRAINT deb_contents_arch_fkey
104         FOREIGN KEY (arch) REFERENCES architecture(id)
105         ON DELETE CASCADE;""")
106
107         c.execute("""ALTER TABLE ONLY udeb_contents
108         ADD CONSTRAINT udeb_contents_arch_fkey
109         FOREIGN KEY (arch) REFERENCES architecture(id)
110         ON DELETE CASCADE;""")
111
112         c.execute("""ALTER TABLE ONLY deb_contents
113         ADD CONSTRAINT deb_contents_pkey
114         PRIMARY KEY (filename,package,arch,suite);""")
115
116         c.execute("""ALTER TABLE ONLY udeb_contents
117         ADD CONSTRAINT udeb_contents_pkey
118         PRIMARY KEY (filename,package,arch,suite);""")
119
120         c.execute("""ALTER TABLE ONLY deb_contents
121         ADD CONSTRAINT deb_contents_suite_fkey
122         FOREIGN KEY (suite) REFERENCES suite(id)
123         ON DELETE CASCADE;""")
124
125         c.execute("""ALTER TABLE ONLY udeb_contents
126         ADD CONSTRAINT udeb_contents_suite_fkey
127         FOREIGN KEY (suite) REFERENCES suite(id)
128         ON DELETE CASCADE;""")
129
130         c.execute("""ALTER TABLE ONLY deb_contents
131         ADD CONSTRAINT deb_contents_binary_fkey
132         FOREIGN KEY (binary_id) REFERENCES binaries(id)
133         ON DELETE CASCADE;""")
134
135         c.execute("""ALTER TABLE ONLY udeb_contents
136         ADD CONSTRAINT udeb_contents_binary_fkey
137         FOREIGN KEY (binary_id) REFERENCES binaries(id)
138         ON DELETE CASCADE;""")
139
140         c.execute("""CREATE INDEX ind_deb_contents_binary ON deb_contents(binary_id);""" )
141
142         suites = _suites()
143
144         for suite in [i.lower() for i in suites]:
145
146             c.execute("SELECT id FROM suite WHERE suite_name ='%s'" % suite )
147             suiterow = c.fetchone()
148             suite_id = suiterow[0]
149             arch_list = arches(c, suite_id)
150             arch_list = arches(c, suite_id)
151             suitestr=string.replace(suite,'-','_');
152
153             for (arch_id,arch_str) in arch_list:
154                 arch_str = string.replace(arch_str,"-", "_")
155                 c.execute( "CREATE INDEX ind_deb_contents_%s_%s ON deb_contents (arch,suite) WHERE (arch=2 OR arch=%s) AND suite='%s'"%(arch_str,suitestr,arch_id,suite_id) )
156
157             for section, sname in [("debian-installer","main"),
158                                   ("non-free/debian-installer", "nonfree")]:
159                 c.execute( "CREATE INDEX ind_udeb_contents_%s_%s ON udeb_contents (section,suite) WHERE section='%s' AND suite='%s'"%(sname,suitestr,section,suite_id) )
160
161
162         c.execute( """CREATE OR REPLACE FUNCTION update_contents_for_bin_a() RETURNS trigger AS  $$
163     event = TD["event"]
164     if event == "DELETE" or event == "UPDATE":
165
166         plpy.execute(plpy.prepare("DELETE FROM deb_contents WHERE binary_id=$1 and suite=$2",
167                                   ["int","int"]),
168                                   [TD["old"]["bin"], TD["old"]["suite"]])
169
170     if event == "INSERT" or event == "UPDATE":
171
172        content_data = plpy.execute(plpy.prepare(
173             \"\"\"SELECT s.section, b.package, b.architecture, ot.type
174             FROM override o
175             JOIN override_type ot on o.type=ot.id
176             JOIN binaries b on b.package=o.package
177             JOIN files f on b.file=f.id
178             JOIN location l on l.id=f.location
179             JOIN section s on s.id=o.section
180             WHERE b.id=$1
181             AND o.suite=$2
182             \"\"\",
183             ["int", "int"]),
184             [TD["new"]["bin"], TD["new"]["suite"]])[0]
185
186        tablename="%s_contents" % content_data['type']
187
188        plpy.execute(plpy.prepare(\"\"\"DELETE FROM %s
189                    WHERE package=$1 and arch=$2 and suite=$3\"\"\" % tablename,
190                    ['text','int','int']),
191                    [content_data['package'],
192                    content_data['architecture'],
193                    TD["new"]["suite"]])
194
195        filenames = plpy.execute(plpy.prepare(
196            "SELECT bc.file FROM bin_contents bc where bc.binary_id=$1",
197            ["int"]),
198            [TD["new"]["bin"]])
199
200        for filename in filenames:
201            plpy.execute(plpy.prepare(
202                \"\"\"INSERT INTO %s
203                    (filename,section,package,binary_id,arch,suite)
204                    VALUES($1,$2,$3,$4,$5,$6)\"\"\" % tablename,
205                ["text","text","text","int","int","int"]),
206                [filename["file"],
207                 content_data["section"],
208                 content_data["package"],
209                 TD["new"]["bin"],
210                 content_data["architecture"],
211                 TD["new"]["suite"]] )
212 $$ LANGUAGE plpythonu VOLATILE SECURITY DEFINER;
213 """)
214
215
216         c.execute( """CREATE OR REPLACE FUNCTION update_contents_for_override() RETURNS trigger AS  $$
217     event = TD["event"]
218     if event == "UPDATE":
219
220         otype = plpy.execute(plpy.prepare("SELECT type from override_type where id=$1",["int"]),[TD["new"]["type"]] )[0];
221         if otype["type"].endswith("deb"):
222             section = plpy.execute(plpy.prepare("SELECT section from section where id=$1",["int"]),[TD["new"]["section"]] )[0];
223
224             table_name = "%s_contents" % otype["type"]
225             plpy.execute(plpy.prepare("UPDATE %s set section=$1 where package=$2 and suite=$3" % table_name,
226                                       ["text","text","int"]),
227                                       [section["section"],
228                                       TD["new"]["package"],
229                                       TD["new"]["suite"]])
230
231 $$ LANGUAGE plpythonu VOLATILE SECURITY DEFINER;
232 """)
233
234         c.execute("""CREATE OR REPLACE FUNCTION update_contents_for_override()
235                       RETURNS trigger AS  $$
236     event = TD["event"]
237     if event == "UPDATE" or event == "INSERT":
238         row = TD["new"]
239         r = plpy.execute(plpy.prepare( \"\"\"SELECT 1 from suite_architectures sa
240                   JOIN binaries b ON b.architecture = sa.architecture
241                   WHERE b.id = $1 and sa.suite = $2\"\"\",
242                 ["int", "int"]),
243                 [row["bin"], row["suite"]])
244         if not len(r):
245             plpy.error("Illegal architecture for this suite")
246
247 $$ LANGUAGE plpythonu VOLATILE;""")
248
249         c.execute( """CREATE TRIGGER illegal_suite_arch_bin_associations_trigger
250                       BEFORE INSERT OR UPDATE ON bin_associations
251                       FOR EACH ROW EXECUTE PROCEDURE update_contents_for_override();""")
252
253         c.execute( """CREATE TRIGGER bin_associations_contents_trigger
254                       AFTER INSERT OR UPDATE OR DELETE ON bin_associations
255                       FOR EACH ROW EXECUTE PROCEDURE update_contents_for_bin_a();""")
256         c.execute("""CREATE TRIGGER override_contents_trigger
257                       AFTER UPDATE ON override
258                       FOR EACH ROW EXECUTE PROCEDURE update_contents_for_override();""")
259
260
261         c.execute( "CREATE INDEX ind_deb_contents_name ON deb_contents(package);");
262         c.execute( "CREATE INDEX ind_udeb_contents_name ON udeb_contents(package);");
263
264         c.execute("UPDATE config SET value = '28' WHERE name = 'db_revision'")
265
266         self.db.commit()
267
268     except psycopg2.ProgrammingError, msg:
269         self.db.rollback()
270         raise DBUpdateError, "Unable to apply process-new update 28, rollback issued. Error message : %s" % (str(msg))
271