]> git.decadent.org.uk Git - dak.git/blob - dak/dakdb/update28.py
1e32f2dd790fc264045d0567efc20f2f027b0198
[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 = :suite""", {'suite' : 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             suite_id = DBConn().get_suite_id(suite)
145             arch_list = arches(c, suite_id)
146             arch_list = arches(c, suite_id)
147
148             for (arch_id,arch_str) in arch_list:
149                 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) )
150
151             for section, sname in [("debian-installer","main"),
152                                   ("non-free/debian-installer", "nonfree")]:
153                 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) )
154
155
156         c.execute( """CREATE OR REPLACE FUNCTION update_contents_for_bin_a() RETURNS trigger AS  $$
157     event = TD["event"]
158     if event == "DELETE" or event == "UPDATE":
159
160         plpy.execute(plpy.prepare("DELETE FROM deb_contents WHERE binary_id=$1 and suite=$2",
161                                   ["int","int"]),
162                                   [TD["old"]["bin"], TD["old"]["suite"]])
163
164     if event == "INSERT" or event == "UPDATE":
165
166        content_data = plpy.execute(plpy.prepare(
167             \"\"\"SELECT s.section, b.package, b.architecture, ot.type
168             FROM override o
169             JOIN override_type ot on o.type=ot.id
170             JOIN binaries b on b.package=o.package
171             JOIN files f on b.file=f.id
172             JOIN location l on l.id=f.location
173             JOIN section s on s.id=o.section
174             WHERE b.id=$1
175             AND o.suite=$2
176             \"\"\",
177             ["int", "int"]),
178             [TD["new"]["bin"], TD["new"]["suite"]])[0]
179
180        tablename="%s_contents" % content_data['type']
181
182        plpy.execute(plpy.prepare(\"\"\"DELETE FROM %s
183                    WHERE package=$1 and arch=$2 and suite=$3\"\"\" % tablename,
184                    ['text','int','int']),
185                    [content_data['package'],
186                    content_data['architecture'],
187                    TD["new"]["suite"]])
188
189        filenames = plpy.execute(plpy.prepare(
190            "SELECT bc.file FROM bin_contents bc where bc.binary_id=$1",
191            ["int"]),
192            [TD["new"]["bin"]])
193
194        for filename in filenames:
195            plpy.execute(plpy.prepare(
196                \"\"\"INSERT INTO %s
197                    (filename,section,package,binary_id,arch,suite)
198                    VALUES($1,$2,$3,$4,$5,$6)\"\"\" % tablename,
199                ["text","text","text","int","int","int"]),
200                [filename["file"],
201                 content_data["section"],
202                 content_data["package"],
203                 TD["new"]["bin"],
204                 content_data["architecture"],
205                 TD["new"]["suite"]] )
206 $$ LANGUAGE plpythonu VOLATILE SECURITY DEFINER;
207 """)
208
209
210         c.execute( """CREATE OR REPLACE FUNCTION update_contents_for_override() RETURNS trigger AS  $$
211     event = TD["event"]
212     if event == "UPDATE":
213
214         otype = plpy.execute(plpy.prepare("SELECT type from override_type where id=$1",["int"]),[TD["new"]["type"]] )[0];
215         if otype["type"].endswith("deb"):
216             section = plpy.execute(plpy.prepare("SELECT section from section where id=$1",["int"]),[TD["new"]["section"]] )[0];
217
218             table_name = "%s_contents" % otype["type"]
219             plpy.execute(plpy.prepare("UPDATE %s set section=$1 where package=$2 and suite=$3" % table_name,
220                                       ["text","text","int"]),
221                                       [section["section"],
222                                       TD["new"]["package"],
223                                       TD["new"]["suite"]])
224
225 $$ LANGUAGE plpythonu VOLATILE SECURITY DEFINER;
226 """)
227
228         c.execute("""CREATE OR REPLACE FUNCTION update_contents_for_override()
229                       RETURNS trigger AS  $$
230     event = TD["event"]
231     if event == "UPDATE" or event == "INSERT":
232         row = TD["new"]
233         r = plpy.execute(plpy.prepare( \"\"\"SELECT 1 from suite_architectures sa
234                   JOIN binaries b ON b.architecture = sa.architecture
235                   WHERE b.id = $1 and sa.suite = $2\"\"\",
236                 ["int", "int"]),
237                 [row["bin"], row["suite"]])
238         if not len(r):
239             plpy.error("Illegal architecture for this suite")
240
241 $$ LANGUAGE plpythonu VOLATILE;""")
242
243         c.execute( """CREATE TRIGGER illegal_suite_arch_bin_associations_trigger
244                       BEFORE INSERT OR UPDATE ON bin_associations
245                       FOR EACH ROW EXECUTE PROCEDURE update_contents_for_override();""")
246
247         c.execute( """CREATE TRIGGER bin_associations_contents_trigger
248                       AFTER INSERT OR UPDATE OR DELETE ON bin_associations
249                       FOR EACH ROW EXECUTE PROCEDURE update_contents_for_bin_a();""")
250         c.execute("""CREATE TRIGGER override_contents_trigger
251                       AFTER UPDATE ON override
252                       FOR EACH ROW EXECUTE PROCEDURE update_contents_for_override();""")
253
254
255         c.execute( "CREATE INDEX ind_deb_contents_name ON deb_contents(package);");
256         c.execute( "CREATE INDEX ind_udeb_contents_name ON udeb_contents(package);");
257
258         c.execute("UPDATE config SET value = '28' WHERE name = 'db_revision'")
259
260         self.db.commit()
261
262     except psycopg2.ProgrammingError, msg:
263         self.db.rollback()
264         raise DBUpdateError, "Unable to apply process-new update 28, rollback issued. Error message : %s" % (str(msg))
265