]> git.decadent.org.uk Git - dak.git/blob - dak/dakdb/update28.py
0ff0151e4779e7a3845885cb783113527838832b
[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
36 ################################################################################
37
38 def _suites():
39     """
40     return a list of suites to operate on
41     """
42     suites = Config().SubTree("Suite").List()
43     return suites
44
45 def arches(cursor, suite):
46     """
47     return a list of archs to operate on
48     """
49     arch_list = []
50     cursor.execute("""SELECT s.architecture, a.arch_string
51     FROM suite_architectures s
52     JOIN architecture a ON (s.architecture=a.id)
53     WHERE suite = '%s'""" % suite)
54
55     while True:
56         r = cursor.fetchone()
57         if not r:
58             break
59
60         if r[1] != "source" and r[1] != "all":
61             arch_list.append((r[0], r[1]))
62
63     return arch_list
64
65 def do_update(self):
66     """
67     Adding contents table as first step to maybe, finally getting rid
68     of apt-ftparchive
69     """
70
71     print __doc__
72
73     try:
74         c = self.db.cursor()
75
76         c.execute("""CREATE TABLE pending_bin_contents (
77         id serial NOT NULL,
78         package text NOT NULL,
79         version debversion NOT NULL,
80         arch int NOT NULL,
81         filename text NOT NULL,
82         type int NOT NULL,
83         PRIMARY KEY(id))""" );
84
85         c.execute("""CREATE TABLE deb_contents (
86         filename text,
87         section text,
88         package text,
89         binary_id integer,
90         arch integer,
91         suite integer)""" )
92
93         c.execute("""CREATE TABLE udeb_contents (
94         filename text,
95         section text,
96         package text,
97         binary_id integer,
98         suite integer,
99         arch integer)""" )
100
101         c.execute("""ALTER TABLE ONLY deb_contents
102         ADD CONSTRAINT deb_contents_arch_fkey
103         FOREIGN KEY (arch) REFERENCES architecture(id)
104         ON DELETE CASCADE;""")
105
106         c.execute("""ALTER TABLE ONLY udeb_contents
107         ADD CONSTRAINT udeb_contents_arch_fkey
108         FOREIGN KEY (arch) REFERENCES architecture(id)
109         ON DELETE CASCADE;""")
110
111         c.execute("""ALTER TABLE ONLY deb_contents
112         ADD CONSTRAINT deb_contents_pkey
113         PRIMARY KEY (filename,package,arch,suite);""")
114
115         c.execute("""ALTER TABLE ONLY udeb_contents
116         ADD CONSTRAINT udeb_contents_pkey
117         PRIMARY KEY (filename,package,arch,suite);""")
118
119         c.execute("""ALTER TABLE ONLY deb_contents
120         ADD CONSTRAINT deb_contents_suite_fkey
121         FOREIGN KEY (suite) REFERENCES suite(id)
122         ON DELETE CASCADE;""")
123
124         c.execute("""ALTER TABLE ONLY udeb_contents
125         ADD CONSTRAINT udeb_contents_suite_fkey
126         FOREIGN KEY (suite) REFERENCES suite(id)
127         ON DELETE CASCADE;""")
128
129         c.execute("""ALTER TABLE ONLY deb_contents
130         ADD CONSTRAINT deb_contents_binary_fkey
131         FOREIGN KEY (binary_id) REFERENCES binaries(id)
132         ON DELETE CASCADE;""")
133
134         c.execute("""ALTER TABLE ONLY udeb_contents
135         ADD CONSTRAINT udeb_contents_binary_fkey
136         FOREIGN KEY (binary_id) REFERENCES binaries(id)
137         ON DELETE CASCADE;""")
138
139         c.execute("""CREATE INDEX ind_deb_contents_binary ON deb_contents(binary_id);""" )
140
141         suites = _suites()
142
143         for suite in [i.lower() for i in suites]:
144
145             c.execute("SELECT id FROM suite WHERE suite_name ='%s'" % suite )
146             suiterow = c.fetchall()
147             suite_id=suiterow[0]
148             arch_list = arches(c, suite_id)
149             arch_list = arches(c, suite_id)
150
151             for (arch_id,arch_str) in arch_list:
152                 c.execute( "CREATE INDEX ind_deb_contents_%s_%s ON deb_contents (arch,suite) WHERE (arch=2 OR arch=%d) AND suite=$d"%(arch_str,suite,arch_id,suite_id) )
153
154             for section, sname in [("debian-installer","main"),
155                                   ("non-free/debian-installer", "nonfree")]:
156                 c.execute( "CREATE INDEX ind_udeb_contents_%s_%s ON udeb_contents (section,suite) WHERE section=%s AND suite=$d"%(sname,suite,section,suite_id) )
157
158
159         c.execute( """CREATE OR REPLACE FUNCTION update_contents_for_bin_a() RETURNS trigger AS  $$
160     event = TD["event"]
161     if event == "DELETE" or event == "UPDATE":
162
163         plpy.execute(plpy.prepare("DELETE FROM deb_contents WHERE binary_id=$1 and suite=$2",
164                                   ["int","int"]),
165                                   [TD["old"]["bin"], TD["old"]["suite"]])
166
167     if event == "INSERT" or event == "UPDATE":
168
169        content_data = plpy.execute(plpy.prepare(
170             \"\"\"SELECT s.section, b.package, b.architecture, ot.type
171             FROM override o
172             JOIN override_type ot on o.type=ot.id
173             JOIN binaries b on b.package=o.package
174             JOIN files f on b.file=f.id
175             JOIN location l on l.id=f.location
176             JOIN section s on s.id=o.section
177             WHERE b.id=$1
178             AND o.suite=$2
179             \"\"\",
180             ["int", "int"]),
181             [TD["new"]["bin"], TD["new"]["suite"]])[0]
182
183        tablename="%s_contents" % content_data['type']
184
185        plpy.execute(plpy.prepare(\"\"\"DELETE FROM %s
186                    WHERE package=$1 and arch=$2 and suite=$3\"\"\" % tablename,
187                    ['text','int','int']),
188                    [content_data['package'],
189                    content_data['architecture'],
190                    TD["new"]["suite"]])
191
192        filenames = plpy.execute(plpy.prepare(
193            "SELECT bc.file FROM bin_contents bc where bc.binary_id=$1",
194            ["int"]),
195            [TD["new"]["bin"]])
196
197        for filename in filenames:
198            plpy.execute(plpy.prepare(
199                \"\"\"INSERT INTO %s
200                    (filename,section,package,binary_id,arch,suite)
201                    VALUES($1,$2,$3,$4,$5,$6)\"\"\" % tablename,
202                ["text","text","text","int","int","int"]),
203                [filename["file"],
204                 content_data["section"],
205                 content_data["package"],
206                 TD["new"]["bin"],
207                 content_data["architecture"],
208                 TD["new"]["suite"]] )
209 $$ LANGUAGE plpythonu VOLATILE SECURITY DEFINER;
210 """)
211
212
213         c.execute( """CREATE OR REPLACE FUNCTION update_contents_for_override() RETURNS trigger AS  $$
214     event = TD["event"]
215     if event == "UPDATE":
216
217         otype = plpy.execute(plpy.prepare("SELECT type from override_type where id=$1",["int"]),[TD["new"]["type"]] )[0];
218         if otype["type"].endswith("deb"):
219             section = plpy.execute(plpy.prepare("SELECT section from section where id=$1",["int"]),[TD["new"]["section"]] )[0];
220
221             table_name = "%s_contents" % otype["type"]
222             plpy.execute(plpy.prepare("UPDATE %s set section=$1 where package=$2 and suite=$3" % table_name,
223                                       ["text","text","int"]),
224                                       [section["section"],
225                                       TD["new"]["package"],
226                                       TD["new"]["suite"]])
227
228 $$ LANGUAGE plpythonu VOLATILE SECURITY DEFINER;
229 """)
230
231         c.execute("""CREATE OR REPLACE FUNCTION update_contents_for_override()
232                       RETURNS trigger AS  $$
233     event = TD["event"]
234     if event == "UPDATE" or event == "INSERT":
235         row = TD["new"]
236         r = plpy.execute(plpy.prepare( \"\"\"SELECT 1 from suite_architectures sa
237                   JOIN binaries b ON b.architecture = sa.architecture
238                   WHERE b.id = $1 and sa.suite = $2\"\"\",
239                 ["int", "int"]),
240                 [row["bin"], row["suite"]])
241         if not len(r):
242             plpy.error("Illegal architecture for this suite")
243
244 $$ LANGUAGE plpythonu VOLATILE;""")
245
246         c.execute( """CREATE TRIGGER illegal_suite_arch_bin_associations_trigger
247                       BEFORE INSERT OR UPDATE ON bin_associations
248                       FOR EACH ROW EXECUTE PROCEDURE update_contents_for_override();""")
249
250         c.execute( """CREATE TRIGGER bin_associations_contents_trigger
251                       AFTER INSERT OR UPDATE OR DELETE ON bin_associations
252                       FOR EACH ROW EXECUTE PROCEDURE update_contents_for_bin_a();""")
253         c.execute("""CREATE TRIGGER override_contents_trigger
254                       AFTER UPDATE ON override
255                       FOR EACH ROW EXECUTE PROCEDURE update_contents_for_override();""")
256
257
258         c.execute( "CREATE INDEX ind_deb_contents_name ON deb_contents(package);");
259         c.execute( "CREATE INDEX ind_udeb_contents_name ON udeb_contents(package);");
260
261         c.execute("UPDATE config SET value = '28' WHERE name = 'db_revision'")
262
263         self.db.commit()
264
265     except psycopg2.ProgrammingError, msg:
266         self.db.rollback()
267         raise DBUpdateError, "Unable to apply process-new update 28, rollback issued. Error message : %s" % (str(msg))
268